diff options
-rw-r--r-- | src/wasm/parsing.cpp | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/src/wasm/parsing.cpp b/src/wasm/parsing.cpp index 46ec39865..c6134922a 100644 --- a/src/wasm/parsing.cpp +++ b/src/wasm/parsing.cpp @@ -16,6 +16,7 @@ #include "parsing.h" #include "ir/branch-utils.h" +#include "support/small_set.h" namespace wasm { @@ -104,7 +105,48 @@ void UniqueNameMapper::clear() { reverseLabelMapping.clear(); } +namespace { + +struct DuplicateNameScanner + : public PostWalker<DuplicateNameScanner, + UnifiedExpressionVisitor<DuplicateNameScanner>> { + + // Whether things are ok. If not, we need to fix things up. + bool ok = true; + + // It is rare to have many nested names in general, so track the seen names + // as we go in an efficient way. + SmallUnorderedSet<Name, 10> seen; + + void visitExpression(Expression* curr) { + BranchUtils::operateOnScopeNameDefs(curr, [&](Name& name) { + if (!name.is()) { + return; + } + // TODO: This could be done in a single insert operation that checks + // whether we actually inserted, if we improved + // SmallSetBase::insert to return a value like std::set does. + if (seen.count(name)) { + // A name has been defined more than once; we'll need to fix that. + ok = false; + } else { + seen.insert(name); + } + }); + } +}; + +} // anonymous namespace + void UniqueNameMapper::uniquify(Expression* curr) { + // First, scan the code to see if anything needs to be fixed up, since in the + // common case nothing needs fixing, and we can verify that very quickly. + DuplicateNameScanner scanner; + scanner.walk(curr); + if (scanner.ok) { + return; + } + struct Walker : public ControlFlowWalker<Walker, UnifiedExpressionVisitor<Walker>> { UniqueNameMapper mapper; @@ -132,9 +174,8 @@ void UniqueNameMapper::uniquify(Expression* curr) { } }); } - }; + } walker; - Walker walker; walker.walk(curr); } |