summaryrefslogtreecommitdiff
path: root/src/ir/linear-execution.h
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2021-06-28 14:25:40 -0700
committerGitHub <noreply@github.com>2021-06-28 14:25:40 -0700
commit395b071ae9b09f0b4fe3ce0f3a43f16ba74f01a5 (patch)
tree9f16560e351cab779236f804398fba1ce6c9df01 /src/ir/linear-execution.h
parent1b0d724fd5938931e6924941641dd8924ad49938 (diff)
downloadbinaryen-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.h139
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