summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/hash-stringify-walker.cpp2
-rw-r--r--src/passes/stringify-walker-impl.h47
-rw-r--r--src/passes/stringify-walker.h101
-rw-r--r--test/gtest/stringify.cpp106
4 files changed, 185 insertions, 71 deletions
diff --git a/src/passes/hash-stringify-walker.cpp b/src/passes/hash-stringify-walker.cpp
index 9a7cee08f..43cc3d544 100644
--- a/src/passes/hash-stringify-walker.cpp
+++ b/src/passes/hash-stringify-walker.cpp
@@ -52,7 +52,7 @@ bool StringifyEquator::operator()(Expression* lhs, Expression* rhs) const {
return ExpressionAnalyzer::shallowEqual(lhs, rhs);
}
-void HashStringifyWalker::addUniqueSymbol() {
+void HashStringifyWalker::addUniqueSymbol(SeparatorReason reason) {
// Use a negative value to distinguish symbols for separators from symbols
// for Expressions
assert((uint32_t)nextSeparatorVal >= nextVal);
diff --git a/src/passes/stringify-walker-impl.h b/src/passes/stringify-walker-impl.h
index e856773c9..8ed166d75 100644
--- a/src/passes/stringify-walker-impl.h
+++ b/src/passes/stringify-walker-impl.h
@@ -31,28 +31,12 @@ inline void StringifyWalker<SubType>::doWalkModule(Module* module) {
template<typename SubType>
inline void StringifyWalker<SubType>::doWalkFunction(Function* func) {
- walk(func->body);
- /*
- * We add a unique symbol after walking the function body to separate the
- * string generated from visiting the function body as a single unit from the
- * subsequent strings that will be generated from visiting the sub-expressions
- * of the function body. If we did not add this unique symbol and a program
- * had two functions with the same instructions, we would incorrectly create a
- * new function with the instructions repeated twice.
- *
- * It might be helpful to think of the function body as a block that needs to
- * be separated from subsequent instructions.
- */
- addUniqueSymbol();
-}
-
-template<typename SubType>
-inline void StringifyWalker<SubType>::walk(Expression* curr) {
- Super::walk(curr);
- do {
- addUniqueSymbol();
+ addUniqueSymbol(SeparatorReason::makeFuncStart(func));
+ Super::walk(func->body);
+ addUniqueSymbol(SeparatorReason::makeEnd());
+ while (!controlFlowQueue.empty()) {
dequeueControlFlow();
- } while (!controlFlowQueue.empty());
+ }
}
template<typename SubType>
@@ -76,10 +60,6 @@ inline void StringifyWalker<SubType>::scan(SubType* self, Expression** currp) {
// of control flow.
template<typename SubType> void StringifyWalker<SubType>::dequeueControlFlow() {
auto& queue = controlFlowQueue;
- if (queue.empty()) {
- return;
- }
-
Expression** currp = queue.front();
queue.pop();
Expression* curr = *currp;
@@ -88,32 +68,41 @@ template<typename SubType> void StringifyWalker<SubType>::dequeueControlFlow() {
switch (curr->_id) {
case Expression::Id::BlockId: {
auto* block = curr->cast<Block>();
+ addUniqueSymbol(SeparatorReason::makeBlockStart(block));
for (auto& child : block->list) {
Super::walk(child);
}
+ addUniqueSymbol(SeparatorReason::makeEnd());
break;
}
case Expression::Id::IfId: {
auto* iff = curr->cast<If>();
+ addUniqueSymbol(SeparatorReason::makeIfStart(iff));
Super::walk(iff->ifTrue);
if (iff->ifFalse) {
- addUniqueSymbol();
+ addUniqueSymbol(SeparatorReason::makeElseStart(iff));
Super::walk(iff->ifFalse);
}
+ addUniqueSymbol(SeparatorReason::makeEnd());
break;
}
case Expression::Id::TryId: {
auto* tryy = curr->cast<Try>();
+ addUniqueSymbol(SeparatorReason::makeTryBodyStart());
Super::walk(tryy->body);
+ addUniqueSymbol(SeparatorReason::makeEnd());
for (auto& child : tryy->catchBodies) {
- addUniqueSymbol();
+ addUniqueSymbol(SeparatorReason::makeTryCatchStart());
Super::walk(child);
+ addUniqueSymbol(SeparatorReason::makeEnd());
}
break;
}
case Expression::Id::LoopId: {
auto* loop = curr->cast<Loop>();
+ addUniqueSymbol(SeparatorReason::makeLoopStart(loop));
Super::walk(loop->body);
+ addUniqueSymbol(SeparatorReason::makeEnd());
break;
}
default: {
@@ -131,13 +120,13 @@ void StringifyWalker<SubType>::doVisitExpression(SubType* self,
}
template<typename SubType>
-inline void StringifyWalker<SubType>::addUniqueSymbol() {
+inline void StringifyWalker<SubType>::addUniqueSymbol(SeparatorReason reason) {
// TODO: Add the following static_assert when the compilers running our GitHub
// actions are updated enough to know that this is a constant condition:
// static_assert(&StringifyWalker<SubType>::addUniqueSymbol !=
// &SubType::addUniqueSymbol);
auto self = static_cast<SubType*>(this);
- self->addUniqueSymbol();
+ self->addUniqueSymbol(reason);
}
} // namespace wasm
diff --git a/src/passes/stringify-walker.h b/src/passes/stringify-walker.h
index c20d250ec..129021bc4 100644
--- a/src/passes/stringify-walker.h
+++ b/src/passes/stringify-walker.h
@@ -66,6 +66,103 @@ struct StringifyWalker
using Super = PostWalker<SubType, UnifiedExpressionVisitor<SubType>>;
+ struct SeparatorReason {
+ struct FuncStart {
+ Function* func;
+ };
+
+ struct BlockStart {
+ Block* curr;
+ };
+
+ struct IfStart {
+ If* iff;
+ };
+
+ struct ElseStart {
+ If* iff;
+ };
+
+ struct LoopStart {
+ Loop* loop;
+ };
+
+ struct TryBodyStart {};
+
+ struct TryCatchStart {};
+
+ struct End {
+ Expression* curr;
+ };
+ using Separator = std::variant<FuncStart,
+ BlockStart,
+ IfStart,
+ ElseStart,
+ LoopStart,
+ TryBodyStart,
+ TryCatchStart,
+ End>;
+
+ Separator reason;
+
+ SeparatorReason(Separator reason) : reason(reason) {}
+
+ static SeparatorReason makeFuncStart(Function* func) {
+ return SeparatorReason(FuncStart{func});
+ }
+ static SeparatorReason makeBlockStart(Block* block) {
+ return SeparatorReason(BlockStart{block});
+ }
+ static SeparatorReason makeIfStart(If* iff) {
+ return SeparatorReason(IfStart{iff});
+ }
+ static SeparatorReason makeElseStart(If* iff) {
+ return SeparatorReason(ElseStart{iff});
+ }
+ static SeparatorReason makeLoopStart(Loop* loop) {
+ return SeparatorReason(LoopStart{loop});
+ }
+ static SeparatorReason makeTryCatchStart() {
+ return SeparatorReason(TryCatchStart{});
+ }
+ static SeparatorReason makeTryBodyStart() {
+ return SeparatorReason(TryBodyStart{});
+ }
+ static SeparatorReason makeEnd() { return SeparatorReason(End{}); }
+ bool isFuncStart() { return std::get_if<FuncStart>(&reason); }
+ bool isBlockStart() { return std::get_if<BlockStart>(&reason); }
+ bool isIfStart() { return std::get_if<IfStart>(&reason); }
+ bool isElseStart() { return std::get_if<ElseStart>(&reason); }
+ bool isLoopStart() { return std::get_if<LoopStart>(&reason); }
+ bool isTryBodyStart() { return std::get_if<TryBodyStart>(&reason); }
+ bool isTryCatchStart() { return std::get_if<TryCatchStart>(&reason); }
+ bool isEnd() { return std::get_if<End>(&reason); }
+ };
+
+ friend std::ostream&
+ operator<<(std::ostream& o,
+ typename StringifyWalker::SeparatorReason reason) {
+ if (reason.isFuncStart()) {
+ return o << "Func Start";
+ } else if (reason.isBlockStart()) {
+ return o << "Block Start";
+ } else if (reason.isIfStart()) {
+ return o << "If Start";
+ } else if (reason.isElseStart()) {
+ return o << "Else Start";
+ } else if (reason.isLoopStart()) {
+ return o << "Loop Start";
+ } else if (reason.isTryBodyStart()) {
+ return o << "Try Body Start";
+ } else if (reason.isTryCatchStart()) {
+ return o << "Try Catch Start";
+ } else if (reason.isEnd()) {
+ return o << "End";
+ }
+
+ return o << "~~~Undefined in operator<< overload~~~";
+ }
+
std::queue<Expression**> controlFlowQueue;
/*
@@ -77,7 +174,7 @@ struct StringifyWalker
* appropriate points during the walk and should be implemented by subclasses.
*/
void visitExpression(Expression* curr);
- void addUniqueSymbol();
+ void addUniqueSymbol(SeparatorReason reason);
void doWalkModule(Module* module);
void doWalkFunction(Function* func);
@@ -130,7 +227,7 @@ struct HashStringifyWalker : public StringifyWalker<HashStringifyWalker> {
std::unordered_map<Expression*, uint32_t, StringifyHasher, StringifyEquator>
exprToCounter;
- void addUniqueSymbol();
+ void addUniqueSymbol(SeparatorReason reason);
void visitExpression(Expression* curr);
};
diff --git a/test/gtest/stringify.cpp b/test/gtest/stringify.cpp
index 01d7ad7af..22b194484 100644
--- a/test/gtest/stringify.cpp
+++ b/test/gtest/stringify.cpp
@@ -56,50 +56,64 @@ TEST_F(StringifyTest, Print) {
)
)wasm";
- auto stringifyText = R"stringify(in visitExpression for block
-adding unique symbol
+ auto stringifyText = R"stringify(adding unique symbol for Func Start
+in visitExpression for block
+adding unique symbol for End
+adding unique symbol for Block Start
in visitExpression for block $block_a
in visitExpression for block $block_b
in visitExpression for block $block_c
in visitExpression for block $block_d
in visitExpression for block $block_e
-adding unique symbol
+adding unique symbol for End
+adding unique symbol for Block Start
in visitExpression for i32.const 20
in visitExpression for drop
in visitExpression for i32.const 10
in visitExpression for drop
-adding unique symbol
+adding unique symbol for End
+adding unique symbol for Block Start
in visitExpression for i32.const 0
in visitExpression for if
in visitExpression for drop
-adding unique symbol
+adding unique symbol for End
+adding unique symbol for Block Start
in visitExpression for i32.const 1
in visitExpression for if
in visitExpression for drop
-adding unique symbol
+adding unique symbol for End
+adding unique symbol for Block Start
in visitExpression for try $try_a
-adding unique symbol
+adding unique symbol for End
+adding unique symbol for Block Start
in visitExpression for try $try_b
-adding unique symbol
+adding unique symbol for End
+adding unique symbol for If Start
in visitExpression for i32.const 40
-adding unique symbol
+adding unique symbol for Else Start
in visitExpression for i32.const 5
-adding unique symbol
+adding unique symbol for End
+adding unique symbol for If Start
in visitExpression for i32.const 30
-adding unique symbol
+adding unique symbol for End
+adding unique symbol for Try Body Start
in visitExpression for nop
-adding unique symbol
+adding unique symbol for End
+adding unique symbol for Try Catch Start
in visitExpression for i32.const 8
in visitExpression for drop
-adding unique symbol
+adding unique symbol for End
+adding unique symbol for Try Catch Start
in visitExpression for i32.const 15
in visitExpression for drop
-adding unique symbol
+adding unique symbol for End
+adding unique symbol for Try Body Start
in visitExpression for nop
-adding unique symbol
+adding unique symbol for End
+adding unique symbol for Try Catch Start
in visitExpression for i32.const 33
in visitExpression for drop
-adding unique symbol
+adding unique symbol for End
)stringify";
struct TestStringifyWalker : public StringifyWalker<TestStringifyWalker> {
@@ -107,7 +121,9 @@ adding unique symbol
TestStringifyWalker(std::ostream& os) : os(os){};
- void addUniqueSymbol() { os << "adding unique symbol\n"; }
+ void addUniqueSymbol(SeparatorReason reason) {
+ os << "adding unique symbol for " << reason << "\n";
+ }
void visitExpression(Expression* curr) {
os << "in visitExpression for " << ShallowExpression{curr, getModule()}
@@ -174,51 +190,63 @@ TEST_F(StringifyTest, Stringify) {
EXPECT_EQ(hashString,
(std::vector<uint32_t>{
+ (uint32_t)-1, // function start
0, // function block evaluated as a whole
- (uint32_t)-1, // separate function block from function contents
+ (uint32_t)-2, // end
+ (uint32_t)-3, // block start
1, // block_a evaluated as a whole
2, // block_b evaluated as a whole
3, // block_c evaluated as a whole
1, // block_d has the same contents as block_a
3, // block_e has the same contents as block_c
4, // block_f evaluated as a whole
- (uint32_t)-2, // separate blocks from block contents
+ (uint32_t)-4, // end
+ (uint32_t)-5, // block start for block_a
5, // i32.const 20
6, // drop, all drops will be the same symbol
7, // i32.const 10
6, // drop
- (uint32_t)-3, // separate block_a contents
+ (uint32_t)-6, // end
+ (uint32_t)-7, // block start for block_b
8, // i32.const 0, if condition
9, // block_b's if evaluated as a whole
6, // drop
- (uint32_t)-4, // separate block_b contents
+ (uint32_t)-8, // end
+ (uint32_t)-9, // block start for block_c
10, // i32.const 1, if condition
11, // block_c's if evaluated as a whole
6, // drop
- (uint32_t)-5, // separate block_c contents
+ (uint32_t)-10, // end
+ (uint32_t)-11, // block start for block_d
5, // i32.const 20
6, // drop
7, // i32.const 10
6, // drop
- (uint32_t)-6, // separate block_d contents
+ (uint32_t)-12, // end
+ (uint32_t)-13, // block start for block_e
10, // i32.const 1, if condition
11, // block_e if evaluated as a whole
6, // drop
- (uint32_t)-7, // separate block_e contents
+ (uint32_t)-14, // end
+ (uint32_t)-15, // block start for block_f
8, // i32.const 0, if condition
11, // block_f's if evaluated as a whole
6, // drop
- (uint32_t)-8, // separate block_f contents
+ (uint32_t)-16, // end
+ (uint32_t)-17, // if start in block_b
12, // i32.const 40
- (uint32_t)-9, // separate block_b if-true
+ (uint32_t)-18, // else start in block_b
13, // i32.const 5
- (uint32_t)-10, // separate block_b if-false
+ (uint32_t)-19, // end
+ (uint32_t)-20, // if start in block_c
14, // i32.const 30
- (uint32_t)-11, // separate block_c if-true
+ (uint32_t)-21, // end
+ (uint32_t)-22, // if start in block_e
14, // i32.const 30
- (uint32_t)-12, // separate block_e if-true
+ (uint32_t)-23, // end
+ (uint32_t)-24, // if start in block_f
14, // i32.const 30
- (uint32_t)-13 // separate block_f if-true
+ (uint32_t)-25, // end
}));
}
@@ -251,15 +279,15 @@ TEST_F(StringifyTest, Substrings) {
substrings,
(std::vector<SuffixTree::RepeatedSubstring>{
// 5, 6, 7, 6 appears at idx 9 and again at 22
- SuffixTree::RepeatedSubstring{4u, (std::vector<unsigned>{9, 22})},
+ SuffixTree::RepeatedSubstring{4u, (std::vector<unsigned>{12, 28})},
// 6, 7, 6 appears at idx 10 and again at 23
- SuffixTree::RepeatedSubstring{3u, (std::vector<unsigned>{10, 23})},
+ SuffixTree::RepeatedSubstring{3u, (std::vector<unsigned>{13, 29})},
// 10, 11, 6 appears at idx 18 and again at 27
- SuffixTree::RepeatedSubstring{3u, (std::vector<unsigned>{18, 27})},
+ SuffixTree::RepeatedSubstring{3u, (std::vector<unsigned>{23, 34})},
// 11, 6 appears at idx 32, 19 and again at 28
- SuffixTree::RepeatedSubstring{2u, (std::vector<unsigned>{32, 19, 28})},
+ SuffixTree::RepeatedSubstring{2u, (std::vector<unsigned>{40, 24, 35})},
// 7, 6 appears at idx 11 and again at 24
- SuffixTree::RepeatedSubstring{2u, (std::vector<unsigned>{11, 24})}}));
+ SuffixTree::RepeatedSubstring{2u, (std::vector<unsigned>{14, 30})}}));
}
TEST_F(StringifyTest, DedupeSubstrings) {
@@ -273,8 +301,8 @@ TEST_F(StringifyTest, DedupeSubstrings) {
EXPECT_EQ(
result,
(std::vector<SuffixTree::RepeatedSubstring>{
- // 5, 6, 7, 6 appears at idx 9 and again at 22
- SuffixTree::RepeatedSubstring{4u, (std::vector<unsigned>{9, 22})},
- // 10, 11, 6 appears at idx 18 and again at 27
- SuffixTree::RepeatedSubstring{3u, (std::vector<unsigned>{18, 27})}}));
+ // 5, 6, 7, 6 appears at idx 12 and again at 28
+ SuffixTree::RepeatedSubstring{4u, (std::vector<unsigned>{12, 28})},
+ // 10, 11, 6 appears at idx 23 and again at 34
+ SuffixTree::RepeatedSubstring{3u, (std::vector<unsigned>{23, 34})}}));
}