summaryrefslogtreecommitdiff
path: root/src/wasm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm.cpp')
-rw-r--r--src/wasm.cpp84
1 files changed, 84 insertions, 0 deletions
diff --git a/src/wasm.cpp b/src/wasm.cpp
new file mode 100644
index 000000000..2157992e3
--- /dev/null
+++ b/src/wasm.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#include "wasm.h"
+#include "wasm-traversal.h"
+#include "ast_utils.h"
+
+namespace wasm {
+
+struct BlockTypeSeeker : public PostWalker<BlockTypeSeeker, Visitor<BlockTypeSeeker>> {
+ Block* target; // look for this one
+ WasmType type = unreachable;
+
+ BlockTypeSeeker(Block* target) : target(target) {}
+
+ void noteType(WasmType other) {
+ // once none, stop. it then indicates a poison value, that must not be consumed
+ // and ignore unreachable
+ if (type != none) {
+ if (other == none) {
+ type = none;
+ } else if (other != unreachable) {
+ type = other;
+ }
+ }
+ }
+
+ void visitBreak(Break *curr) {
+ if (curr->name == target->name) {
+ noteType(curr->value ? curr->value->type : none);
+ }
+ }
+
+ void visitSwitch(Switch *curr) {
+ for (auto name : curr->targets) {
+ if (name == target->name) noteType(curr->value ? curr->value->type : none);
+ }
+ }
+
+ void visitBlock(Block *curr) {
+ if (curr == target) {
+ if (curr->list.size() > 0) noteType(curr->list.back()->type);
+ } else {
+ type = unreachable; // ignore all breaks til now, they were captured by someone with the same name
+ }
+ }
+};
+
+void Block::finalize() {
+ if (list.size() > 0) {
+ auto last = list.back()->type;
+ if (last != unreachable) {
+ // well that was easy
+ type = last;
+ return;
+ }
+ }
+ if (!name.is()) {
+ // that was rather silly
+ type = unreachable;
+ return;
+ }
+ // oh no this is hard
+ BlockTypeSeeker seeker(this);
+ Expression* temp = this;
+ seeker.walk(temp);
+ type = seeker.type;
+}
+
+} // namespace wasm
+