summaryrefslogtreecommitdiff
path: root/src/wasm-traversal.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm-traversal.h')
-rw-r--r--src/wasm-traversal.h94
1 files changed, 94 insertions, 0 deletions
diff --git a/src/wasm-traversal.h b/src/wasm-traversal.h
index 8384c6a6f..0c5088917 100644
--- a/src/wasm-traversal.h
+++ b/src/wasm-traversal.h
@@ -32,6 +32,8 @@
namespace wasm {
+// A generic visitor, defaulting to doing nothing on each visit
+
template<typename SubType, typename ReturnType = void>
struct Visitor {
// Expression visitors
@@ -115,6 +117,98 @@ struct Visitor {
}
};
+// A visitor which must be overridden for each visitor that is reached.
+
+template<typename SubType, typename ReturnType = void>
+struct OverriddenVisitor {
+ // Expression visitors, which must be overridden
+ #define UNIMPLEMENTED(CLASS_TO_VISIT) \
+ ReturnType visit##CLASS_TO_VISIT(CLASS_TO_VISIT* curr) { \
+ static_assert(&SubType::visit##CLASS_TO_VISIT != &OverriddenVisitor<SubType, ReturnType>::visit##CLASS_TO_VISIT, "Derived class must implement visit" #CLASS_TO_VISIT); \
+ WASM_UNREACHABLE(); \
+ }
+
+ UNIMPLEMENTED(Block);
+ UNIMPLEMENTED(If);
+ UNIMPLEMENTED(Loop);
+ UNIMPLEMENTED(Break);
+ UNIMPLEMENTED(Switch);
+ UNIMPLEMENTED(Call);
+ UNIMPLEMENTED(CallImport);
+ UNIMPLEMENTED(CallIndirect);
+ UNIMPLEMENTED(GetLocal);
+ UNIMPLEMENTED(SetLocal);
+ UNIMPLEMENTED(GetGlobal);
+ UNIMPLEMENTED(SetGlobal);
+ UNIMPLEMENTED(Load);
+ UNIMPLEMENTED(Store);
+ UNIMPLEMENTED(AtomicRMW);
+ UNIMPLEMENTED(AtomicCmpxchg);
+ UNIMPLEMENTED(AtomicWait);
+ UNIMPLEMENTED(AtomicWake);
+ UNIMPLEMENTED(Const);
+ UNIMPLEMENTED(Unary);
+ UNIMPLEMENTED(Binary);
+ UNIMPLEMENTED(Select);
+ UNIMPLEMENTED(Drop);
+ UNIMPLEMENTED(Return);
+ UNIMPLEMENTED(Host);
+ UNIMPLEMENTED(Nop);
+ UNIMPLEMENTED(Unreachable);
+ UNIMPLEMENTED(FunctionType);
+ UNIMPLEMENTED(Import);
+ UNIMPLEMENTED(Export);
+ UNIMPLEMENTED(Global);
+ UNIMPLEMENTED(Function);
+ UNIMPLEMENTED(Table);
+ UNIMPLEMENTED(Memory);
+ UNIMPLEMENTED(Module);
+
+ #undef UNIMPLEMENTED
+
+ ReturnType visit(Expression* curr) {
+ assert(curr);
+
+ #define DELEGATE(CLASS_TO_VISIT) \
+ return static_cast<SubType*>(this)-> \
+ visit##CLASS_TO_VISIT(static_cast<CLASS_TO_VISIT*>(curr))
+
+ switch (curr->_id) {
+ case Expression::Id::BlockId: DELEGATE(Block);
+ case Expression::Id::IfId: DELEGATE(If);
+ case Expression::Id::LoopId: DELEGATE(Loop);
+ case Expression::Id::BreakId: DELEGATE(Break);
+ case Expression::Id::SwitchId: DELEGATE(Switch);
+ case Expression::Id::CallId: DELEGATE(Call);
+ case Expression::Id::CallImportId: DELEGATE(CallImport);
+ case Expression::Id::CallIndirectId: DELEGATE(CallIndirect);
+ case Expression::Id::GetLocalId: DELEGATE(GetLocal);
+ case Expression::Id::SetLocalId: DELEGATE(SetLocal);
+ case Expression::Id::GetGlobalId: DELEGATE(GetGlobal);
+ case Expression::Id::SetGlobalId: DELEGATE(SetGlobal);
+ case Expression::Id::LoadId: DELEGATE(Load);
+ case Expression::Id::StoreId: DELEGATE(Store);
+ case Expression::Id::AtomicRMWId: DELEGATE(AtomicRMW);
+ case Expression::Id::AtomicCmpxchgId: DELEGATE(AtomicCmpxchg);
+ case Expression::Id::AtomicWaitId: DELEGATE(AtomicWait);
+ case Expression::Id::AtomicWakeId: DELEGATE(AtomicWake);
+ case Expression::Id::ConstId: DELEGATE(Const);
+ case Expression::Id::UnaryId: DELEGATE(Unary);
+ case Expression::Id::BinaryId: DELEGATE(Binary);
+ case Expression::Id::SelectId: DELEGATE(Select);
+ case Expression::Id::DropId: DELEGATE(Drop);
+ case Expression::Id::ReturnId: DELEGATE(Return);
+ case Expression::Id::HostId: DELEGATE(Host);
+ case Expression::Id::NopId: DELEGATE(Nop);
+ case Expression::Id::UnreachableId: DELEGATE(Unreachable);
+ case Expression::Id::InvalidId:
+ default: WASM_UNREACHABLE();
+ }
+
+ #undef DELEGATE
+ }
+};
+
// Visit with a single unified visitor, called on every node, instead of
// separate visit* per node