diff options
author | Alon Zakai <azakai@google.com> | 2022-04-22 10:42:43 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-04-22 10:42:43 -0700 |
commit | 2ab19d9ac528ff11fa14b184a84c92e72d5b0163 (patch) | |
tree | 015d0a00203a1fc08c95e795b2e1c9bc68817050 /src/ir/module-utils.cpp | |
parent | 6000629ae7cc2962483cd0d7ae4a770c8f2a34a0 (diff) | |
download | binaryen-2ab19d9ac528ff11fa14b184a84c92e72d5b0163.tar.gz binaryen-2ab19d9ac528ff11fa14b184a84c92e72d5b0163.tar.bz2 binaryen-2ab19d9ac528ff11fa14b184a84c92e72d5b0163.zip |
[NominalFuzzing] Fix getHeapTypeCounts() on unreachable casts (#4609)
The cast instruction may be unreachable but the intended type for the cast
still needs to be collected. Otherwise we end up with problems both during
optimizations that look at heap types and in printing (which will use the heap
type in code but not declare it).
Diff without whitespace is much smaller: this just moves code around so
that we can use a template to avoid code duplication. The actual change
is just to scan ->intendedType unconditionally, and not ignore it if the
cast is unreachable.
Diffstat (limited to 'src/ir/module-utils.cpp')
-rw-r--r-- | src/ir/module-utils.cpp | 106 |
1 files changed, 53 insertions, 53 deletions
diff --git a/src/ir/module-utils.cpp b/src/ir/module-utils.cpp index b5d0d7d48..a061782f9 100644 --- a/src/ir/module-utils.cpp +++ b/src/ir/module-utils.cpp @@ -42,65 +42,65 @@ struct Counts : public InsertOrderedMap<HeapType, size_t> { } }; -Counts getHeapTypeCounts(Module& wasm) { - struct CodeScanner - : PostWalker<CodeScanner, UnifiedExpressionVisitor<CodeScanner>> { - Counts& counts; +struct CodeScanner + : PostWalker<CodeScanner, UnifiedExpressionVisitor<CodeScanner>> { + Counts& counts; - CodeScanner(Module& wasm, Counts& counts) : counts(counts) { - setModule(&wasm); - } + CodeScanner(Module& wasm, Counts& counts) : counts(counts) { + setModule(&wasm); + } - void visitExpression(Expression* curr) { - if (auto* call = curr->dynCast<CallIndirect>()) { - counts.note(call->heapType); - } else if (curr->is<RefNull>()) { + void visitExpression(Expression* curr) { + if (auto* call = curr->dynCast<CallIndirect>()) { + counts.note(call->heapType); + } else if (curr->is<RefNull>()) { + counts.note(curr->type); + } else if (curr->is<RttCanon>() || curr->is<RttSub>()) { + counts.note(curr->type.getRtt().heapType); + } else if (auto* make = curr->dynCast<StructNew>()) { + handleMake(make); + } else if (auto* make = curr->dynCast<ArrayNew>()) { + handleMake(make); + } else if (auto* make = curr->dynCast<ArrayInit>()) { + handleMake(make); + } else if (auto* cast = curr->dynCast<RefCast>()) { + handleCast(cast); + } else if (auto* cast = curr->dynCast<RefTest>()) { + handleCast(cast); + } else if (auto* cast = curr->dynCast<BrOn>()) { + if (cast->op == BrOnCast || cast->op == BrOnCastFail) { + handleCast(cast); + } + } else if (auto* get = curr->dynCast<StructGet>()) { + counts.note(get->ref->type); + } else if (auto* set = curr->dynCast<StructSet>()) { + counts.note(set->ref->type); + } else if (Properties::isControlFlowStructure(curr)) { + if (curr->type.isTuple()) { + // TODO: Allow control flow to have input types as well + counts.note(Signature(Type::none, curr->type)); + } else { counts.note(curr->type); - } else if (curr->is<RttCanon>() || curr->is<RttSub>()) { - counts.note(curr->type.getRtt().heapType); - } else if (auto* make = curr->dynCast<StructNew>()) { - // Some operations emit a HeapType in the binary format, if they are - // static and not dynamic (if dynamic, the RTT provides the heap type). - if (!make->rtt && make->type != Type::unreachable) { - counts.note(make->type.getHeapType()); - } - } else if (auto* make = curr->dynCast<ArrayNew>()) { - if (!make->rtt && make->type != Type::unreachable) { - counts.note(make->type.getHeapType()); - } - } else if (auto* make = curr->dynCast<ArrayInit>()) { - if (!make->rtt && make->type != Type::unreachable) { - counts.note(make->type.getHeapType()); - } - } else if (auto* cast = curr->dynCast<RefCast>()) { - if (!cast->rtt && cast->type != Type::unreachable) { - counts.note(cast->getIntendedType()); - } - } else if (auto* cast = curr->dynCast<RefTest>()) { - if (!cast->rtt && cast->type != Type::unreachable) { - counts.note(cast->getIntendedType()); - } - } else if (auto* cast = curr->dynCast<BrOn>()) { - if (cast->op == BrOnCast || cast->op == BrOnCastFail) { - if (!cast->rtt && cast->type != Type::unreachable) { - counts.note(cast->getIntendedType()); - } - } - } else if (auto* get = curr->dynCast<StructGet>()) { - counts.note(get->ref->type); - } else if (auto* set = curr->dynCast<StructSet>()) { - counts.note(set->ref->type); - } else if (Properties::isControlFlowStructure(curr)) { - if (curr->type.isTuple()) { - // TODO: Allow control flow to have input types as well - counts.note(Signature(Type::none, curr->type)); - } else { - counts.note(curr->type); - } } } - }; + } + + template<typename T> void handleMake(T* curr) { + if (!curr->rtt && curr->type != Type::unreachable) { + counts.note(curr->type.getHeapType()); + } + } + template<typename T> void handleCast(T* curr) { + // Some operations emit a HeapType in the binary format, if they are + // static and not dynamic (if dynamic, the RTT provides the heap type). + if (!curr->rtt) { + counts.note(curr->intendedType); + } + } +}; + +Counts getHeapTypeCounts(Module& wasm) { // Collect module-level info. Counts counts; CodeScanner(wasm, counts).walkModuleCode(&wasm); |