/* * Copyright 2018 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_iteration_h #define wasm_ir_iteration_h #include "wasm.h" namespace wasm { // // Allows iteration over the children of the expression, in order of execution // where relevant. // // * This skips missing children, e.g. if an if has no else, it is represented // as having 2 children (and not 3 with the last a nullptr). // // In general, it is preferable not to use this class and to directly access // the children (using e.g. iff->ifTrue etc.), as that is faster. However, in // cases where speed does not matter, this can be convenient. // class ChildIterator { struct Iterator { const ChildIterator& parent; Index index; Iterator(const ChildIterator& parent, Index index) : parent(parent), index(index) {} bool operator!=(const Iterator& other) const { return index != other.index || &parent != &(other.parent); } void operator++() { index++; } Expression* operator*() { return parent.children[index]; } }; public: std::vector children; ChildIterator(Expression* expr) { switch (expr->_id) { case Expression::Id::BlockId: { auto& list = expr->cast()->list; for (auto* child : list) { children.push_back(child); } break; } case Expression::Id::IfId: { auto* iff = expr->cast(); children.push_back(iff->condition); children.push_back(iff->ifTrue); if (iff->ifFalse) children.push_back(iff->ifFalse); break; } case Expression::Id::LoopId: { children.push_back(expr->cast()->body); break; } case Expression::Id::BreakId: { auto* br = expr->cast(); if (br->value) children.push_back(br->value); if (br->condition) children.push_back(br->condition); break; } case Expression::Id::SwitchId: { auto* br = expr->cast(); if (br->value) children.push_back(br->value); children.push_back(br->condition); break; } case Expression::Id::CallId: { auto& operands = expr->cast()->operands; for (auto* child : operands) { children.push_back(child); } break; } case Expression::Id::CallImportId: { auto& operands = expr->cast()->operands; for (auto* child : operands) { children.push_back(child); } break; } case Expression::Id::CallIndirectId: { auto* call = expr->cast(); auto& operands = call->operands; for (auto* child : operands) { children.push_back(child); } children.push_back(call->target); break; } case Expression::Id::SetLocalId: { children.push_back(expr->cast()->value); break; } case Expression::Id::SetGlobalId: { children.push_back(expr->cast()->value); break; } case Expression::Id::LoadId: { children.push_back(expr->cast()->ptr); break; } case Expression::Id::StoreId: { auto* store = expr->cast(); children.push_back(store->ptr); children.push_back(store->value); break; } case Expression::Id::UnaryId: { children.push_back(expr->cast()->value); break; } case Expression::Id::BinaryId: { auto* binary = expr->cast(); children.push_back(binary->left); children.push_back(binary->right); break; } case Expression::Id::SelectId: { auto* select = expr->cast