diff options
author | Alon Zakai <azakai@google.com> | 2021-06-28 14:25:40 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-28 14:25:40 -0700 |
commit | 395b071ae9b09f0b4fe3ce0f3a43f16ba74f01a5 (patch) | |
tree | 9f16560e351cab779236f804398fba1ce6c9df01 /src/ir/linear-execution.h | |
parent | 1b0d724fd5938931e6924941641dd8924ad49938 (diff) | |
download | binaryen-395b071ae9b09f0b4fe3ce0f3a43f16ba74f01a5.tar.gz binaryen-395b071ae9b09f0b4fe3ce0f3a43f16ba74f01a5.tar.bz2 binaryen-395b071ae9b09f0b4fe3ce0f3a43f16ba74f01a5.zip |
Refactor LinearExecutionWalker to a separate file. NFC (#3956)
Diffstat (limited to 'src/ir/linear-execution.h')
-rw-r--r-- | src/ir/linear-execution.h | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/src/ir/linear-execution.h b/src/ir/linear-execution.h new file mode 100644 index 000000000..b1d0b96c3 --- /dev/null +++ b/src/ir/linear-execution.h @@ -0,0 +1,139 @@ +/* + * Copyright 2021 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef wasm_ir_linear_execution_h +#define wasm_ir_linear_execution_h + +#include <wasm-traversal.h> +#include <wasm.h> + +namespace wasm { + +// Traversal in the order of execution. This is quick and simple, but +// does not provide the same comprehensive information that a full +// conversion to basic blocks would. What it does give is a quick +// way to view straightline execution traces, i.e., that have no +// branching. This can let optimizations get most of what they +// want without the cost of creating another AST. +// +// When execution is no longer linear, this notifies via a call +// to noteNonLinear(). + +template<typename SubType, typename VisitorType = Visitor<SubType>> +struct LinearExecutionWalker : public PostWalker<SubType, VisitorType> { + LinearExecutionWalker() = default; + + // subclasses should implement this + 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: + abort(); + 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->maybePushTask(SubType::scan, &curr->cast<Switch>()->value); + self->pushTask(SubType::scan, &curr->cast<Switch>()->condition); + 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; + } + default: { + // other node types do not have control flow, use regular post-order + PostWalker<SubType, VisitorType>::scan(self, currp); + } + } + } +}; + +} // namespace wasm + +#endif // wasm_ir_linear_execution_h |