summaryrefslogtreecommitdiff
path: root/src/passes/stringify-walker-impl.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes/stringify-walker-impl.h')
-rw-r--r--src/passes/stringify-walker-impl.h129
1 files changed, 129 insertions, 0 deletions
diff --git a/src/passes/stringify-walker-impl.h b/src/passes/stringify-walker-impl.h
new file mode 100644
index 000000000..176813179
--- /dev/null
+++ b/src/passes/stringify-walker-impl.h
@@ -0,0 +1,129 @@
+#include "stringify-walker.h"
+
+#ifndef wasm_passes_stringify_walker_impl_h
+#define wasm_passes_stringify_walker_impl_h
+
+namespace wasm {
+
+// This walker supplies its own doWalkModule because it does not make sense to
+// walk anything besides defined functions.
+template<typename SubType>
+inline void StringifyWalker<SubType>::doWalkModule(Module* module) {
+ ModuleUtils::iterDefinedFunctions(
+ *module, [&](Function* func) { this->walkFunction(func); });
+}
+
+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();
+ dequeueControlFlow();
+ } while (!controlFlowQueue.empty());
+}
+
+template<typename SubType>
+inline void StringifyWalker<SubType>::scan(SubType* self, Expression** currp) {
+ Expression* curr = *currp;
+ if (Properties::isControlFlowStructure(curr)) {
+ self->controlFlowQueue.push(currp);
+ self->pushTask(doVisitExpression, currp);
+ // The if-condition is a value child consumed by the if control flow, which
+ // makes the if-condition a true sibling rather than part of its contents in
+ // the binary format
+ for (auto*& child : ValueChildIterator(curr)) {
+ Super::scan(self, &child);
+ }
+ } else {
+ Super::scan(self, currp);
+ }
+}
+
+// This dequeueControlFlow is responsible for visiting the children expressions
+// 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;
+
+ // TODO: Issue #5796, Make a ControlChildIterator
+ switch (curr->_id) {
+ case Expression::Id::BlockId: {
+ auto* block = curr->cast<Block>();
+ for (auto& child : block->list) {
+ Super::walk(child);
+ }
+ break;
+ }
+ case Expression::Id::IfId: {
+ auto* iff = curr->cast<If>();
+ Super::walk(iff->ifTrue);
+ if (iff->ifFalse) {
+ addUniqueSymbol();
+ Super::walk(iff->ifFalse);
+ }
+ break;
+ }
+ case Expression::Id::TryId: {
+ auto* tryy = curr->cast<Try>();
+ Super::walk(tryy->body);
+ for (auto& child : tryy->catchBodies) {
+ addUniqueSymbol();
+ Super::walk(child);
+ }
+ break;
+ }
+ case Expression::Id::LoopId: {
+ auto* loop = curr->cast<Loop>();
+ Super::walk(loop->body);
+ break;
+ }
+ default: {
+ assert(Properties::isControlFlowStructure(curr));
+ WASM_UNREACHABLE("unexpected expression");
+ }
+ }
+}
+
+template<typename SubType>
+void StringifyWalker<SubType>::doVisitExpression(SubType* self,
+ Expression** currp) {
+ Expression* curr = *currp;
+ self->visit(curr);
+}
+
+template<typename SubType>
+inline void StringifyWalker<SubType>::addUniqueSymbol() {
+ // 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();
+}
+
+} // namespace wasm
+
+#endif // wasm_passes_stringify_walker_impl_h