#ifndef wasm_ir_linear_execution_h
#define wasm_ir_linear_execution_h
#include <ir/properties.h>
#include <wasm-traversal.h>
#include <wasm.h>
namespace wasm {
template<typename SubType, typename VisitorType = Visitor<SubType>>
struct LinearExecutionWalker : public PostWalker<SubType, VisitorType> {
LinearExecutionWalker() = default;
void noteNonLinear(Expression* curr) { abort(); }
static void doNoteNonLinear(SubType* self, Expression** currp) {
self->noteNonLinear(*currp);
}
static void scan(SubType* self, Expression** currp) {
Expression* curr = *currp;
switch (curr->_id) {
case Expression::Id::InvalidId:
WASM_UNREACHABLE("bad id");
case Expression::Id::BlockId: {
self->pushTask(SubType::doVisitBlock, currp);
if (curr->cast<Block>()->name.is()) {
self->pushTask(SubType::doNoteNonLinear, currp);
}
auto& list = curr->cast<Block>()->list;
for (int i = int(list.size()) - 1; i >= 0; i--) {
self->pushTask(SubType::scan, &list[i]);
}
break;
}
case Expression::Id::IfId: {
self->pushTask(SubType::doVisitIf, currp);
self->pushTask(SubType::doNoteNonLinear, currp);
self->maybePushTask(SubType::scan, &curr->cast<If>()->ifFalse);
self->pushTask(SubType::doNoteNonLinear, currp);
self->pushTask(SubType::scan, &curr->cast<If>()->ifTrue);
self->pushTask(SubType::doNoteNonLinear, currp);
self->pushTask(SubType::scan, &curr->cast<If>()->condition);
break;
}
case Expression::Id::LoopId: {
self->pushTask(SubType::doVisitLoop, currp);
self->pushTask(SubType::scan, &curr->cast<Loop>()->body);
self->pushTask(SubType::doNoteNonLinear, currp);
break;
}
case Expression::Id::BreakId: {
self->pushTask(SubType::doVisitBreak, currp);
self->pushTask(SubType::doNoteNonLinear, currp);
self->maybePushTask(SubType::scan, &curr->cast<Break>()->condition);
self->maybePushTask(SubType::scan, &curr->cast<Break>()->value);
break;
}
case Expression::Id::SwitchId: {
self->pushTask(SubType::doVisitSwitch, currp);
self->pushTask(SubType::doNoteNonLinear, currp);
self->pushTask(SubType::scan, &curr->cast<Switch>()->condition);
self->maybePushTask(SubType::scan, &curr->cast<Switch>()->value);
break;
}
case Expression::Id::ReturnId: {
self->pushTask(SubType::doVisitReturn, currp);
self->pushTask(SubType::doNoteNonLinear, currp);
self->maybePushTask(SubType::scan, &curr->cast<Return>()->value);
break;
}
case Expression::Id::TryId: {
self->pushTask(SubType::doVisitTry, currp);
self->pushTask(SubType::doNoteNonLinear, currp);
auto& list = curr->cast<Try>()->catchBodies;
for (int i = int(list.size()) - 1; i >= 0; i--) {
self->pushTask(SubType::scan, &list[i]);
self->pushTask(SubType::doNoteNonLinear, currp);
}
self->pushTask(SubType::scan, &curr->cast<Try>()->body);
break;
}
case Expression::Id::ThrowId: {
self->pushTask(SubType::doVisitThrow, currp);
self->pushTask(SubType::doNoteNonLinear, currp);
auto& list = curr->cast<Throw>()->operands;
for (int i = int(list.size()) - 1; i >= 0; i--) {
self->pushTask(SubType::scan, &list[i]);
}
break;
}
case Expression::Id::RethrowId: {
self->pushTask(SubType::doVisitRethrow, currp);
self->pushTask(SubType::doNoteNonLinear, currp);
break;
}
case Expression::Id::UnreachableId: {
self->pushTask(SubType::doVisitUnreachable, currp);
self->pushTask(SubType::doNoteNonLinear, currp);
break;
}
case Expression::Id::BrOnId: {
self->pushTask(SubType::doVisitBrOn, currp);
self->pushTask(SubType::doNoteNonLinear, currp);
self->pushTask(SubType::scan, &curr->cast<BrOn>()->ref);
break;
}
default: {
assert(!Properties::isControlFlowStructure(curr));
assert(!Properties::isBranch(curr));
PostWalker<SubType, VisitorType>::scan(self, currp);
}
}
}
};
}
#endif