diff options
Diffstat (limited to 'src/ast')
-rw-r--r-- | src/ast/branch-utils.h | 55 | ||||
-rw-r--r-- | src/ast/label-utils.h | 62 |
2 files changed, 117 insertions, 0 deletions
diff --git a/src/ast/branch-utils.h b/src/ast/branch-utils.h index a54b8151f..bdf52d36a 100644 --- a/src/ast/branch-utils.h +++ b/src/ast/branch-utils.h @@ -18,6 +18,7 @@ #define wasm_ast_branch_h #include "wasm.h" +#include "wasm-traversal.h" namespace wasm { @@ -36,6 +37,60 @@ inline bool isBranchTaken(Switch* sw) { sw->condition->type != unreachable; } +// returns the set of targets to which we branch that are +// outside of a node +inline std::set<Name> getExitingBranches(Expression* ast) { + struct Scanner : public PostWalker<Scanner> { + std::set<Name> targets; + + void visitBreak(Break* curr) { + targets.insert(curr->name); + } + void visitSwitch(Switch* curr) { + for (auto target : targets) { + targets.insert(target); + } + targets.insert(curr->default_); + } + void visitBlock(Block* curr) { + if (curr->name.is()) { + targets.erase(curr->name); + } + } + void visitLoop(Loop* curr) { + if (curr->name.is()) { + targets.erase(curr->name); + } + } + }; + Scanner scanner; + scanner.walk(ast); + // anything not erased is a branch out + return scanner.targets; +} + +// returns the list of all branch targets in a node + +inline std::set<Name> getBranchTargets(Expression* ast) { + struct Scanner : public PostWalker<Scanner> { + std::set<Name> targets; + + void visitBlock(Block* curr) { + if (curr->name.is()) { + targets.insert(curr->name); + } + } + void visitLoop(Loop* curr) { + if (curr->name.is()) { + targets.insert(curr->name); + } + } + }; + Scanner scanner; + scanner.walk(ast); + return scanner.targets; +} + } // namespace BranchUtils } // namespace wasm diff --git a/src/ast/label-utils.h b/src/ast/label-utils.h new file mode 100644 index 000000000..6ec9ecf5d --- /dev/null +++ b/src/ast/label-utils.h @@ -0,0 +1,62 @@ +/* + * Copyright 2017 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_ast_label_h +#define wasm_ast_label_h + +#include "wasm.h" +#include "wasm-traversal.h" + +namespace wasm { + +namespace LabelUtils { + +// Handles branch/loop labels in a function; makes it easy to add new +// ones without duplicates +class LabelManager : public PostWalker<LabelManager> { +public: + LabelManager(Function* func) { + walkFunction(func); + } + + Name getUnique(std::string prefix) { + while (1) { + auto curr = Name(prefix + std::to_string(counter++)); + if (labels.find(curr) == labels.end()) { + labels.insert(curr); + return curr; + } + } + } + + void visitBlock(Block* curr) { + labels.insert(curr->name); + } + void visitLoop(Loop* curr) { + labels.insert(curr->name); + } + +private: + std::set<Name> labels; + size_t counter = 0; +}; + +} // namespace LabelUtils + +} // namespace wasm + +#endif // wasm_ast_label_h + |