#ifndef wasm_ir_iteration_h
#define wasm_ir_iteration_h
#include "ir/properties.h"
#include "wasm.h"
namespace wasm {
template<class Specific> class AbstractChildIterator {
using Self = AbstractChildIterator<Specific>;
struct Iterator {
using difference_type = std::ptrdiff_t;
using value_type = Expression*;
using pointer = Expression**;
using reference = Expression*&;
using iterator_category = std::forward_iterator_tag;
const Self* parent;
Index index;
Iterator(const Self* parent, Index index) : parent(parent), index(index) {}
bool operator!=(const Iterator& other) const {
return index != other.index || parent != other.parent;
}
bool operator==(const Iterator& other) const { return !(*this != other); }
void operator++() { index++; }
Expression*& operator*() {
return *parent->children[parent->mapIndex(index)];
}
};
friend struct Iterator;
Index mapIndex(Index index) const {
assert(index < children.size());
return children.size() - 1 - index;
}
public:
SmallVector<Expression**, 4> children;
AbstractChildIterator(Expression* parent) {
auto* self = (Specific*)this;
#define DELEGATE_ID parent->_id
#define DELEGATE_START(id) [[maybe_unused]] auto* cast = parent->cast<id>();
#define DELEGATE_GET_FIELD(id, field) cast->field
#define DELEGATE_FIELD_CHILD(id, field) self->addChild(parent, &cast->field);
#define DELEGATE_FIELD_OPTIONAL_CHILD(id, field) \
if (cast->field) { \
self->addChild(parent, &cast->field); \
}
#define DELEGATE_FIELD_INT(id, field)
#define DELEGATE_FIELD_INT_ARRAY(id, field)
#define DELEGATE_FIELD_LITERAL(id, field)
#define DELEGATE_FIELD_NAME(id, field)
#define DELEGATE_FIELD_NAME_VECTOR(id, field)
#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, field)
#define DELEGATE_FIELD_SCOPE_NAME_USE(id, field)
#define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, field)
#define DELEGATE_FIELD_TYPE(id, field)
#define DELEGATE_FIELD_HEAPTYPE(id, field)
#define DELEGATE_FIELD_ADDRESS(id, field)
#include "wasm-delegations-fields.def"
}
Iterator begin() const { return Iterator(this, 0); }
Iterator end() const { return Iterator(this, children.size()); }
void addChild(Expression* parent, Expression** child) {
children.push_back(child);
}
Expression*& getChild(Index index) { return *children[mapIndex(index)]; }
Index getNumChildren() { return children.size(); }
};
class ChildIterator : public AbstractChildIterator<ChildIterator> {
public:
ChildIterator(Expression* parent)
: AbstractChildIterator<ChildIterator>(parent) {}
};
class ValueChildIterator : public AbstractChildIterator<ValueChildIterator> {
public:
ValueChildIterator(Expression* parent)
: AbstractChildIterator<ValueChildIterator>(parent) {}
void addChild(Expression* parent, Expression** child) {
if (Properties::isControlFlowStructure(parent)) {
if (auto* iff = parent->dynCast<If>()) {
if (child == &iff->condition) {
children.push_back(child);
}
}
} else {
children.push_back(child);
}
}
};
template<typename T> bool containsChild(Expression* parent, int depth = -1) {
std::vector<Expression*> exprs;
std::vector<Expression*> nextExprs;
exprs.push_back(parent);
while (!exprs.empty() && depth > 0) {
for (auto* expr : exprs) {
for (auto* child : ChildIterator(expr)) {
if (child->is<T>()) {
return true;
}
nextExprs.push_back(child);
}
}
exprs.swap(nextExprs);
nextExprs.clear();
if (depth > 0) {
depth--;
}
}
return false;
}
}
#endif