Skip to content

Simplify BinaryenIRWriter #3110

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 39 additions & 13 deletions src/ir/iteration.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#ifndef wasm_ir_iteration_h
#define wasm_ir_iteration_h

#include "ir/properties.h"
#include "wasm-traversal.h"
#include "wasm.h"

Expand All @@ -29,18 +30,24 @@ namespace wasm {
// * 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.
// 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. TODO: reimplement these
// to avoid materializing all the chilren at once.
//

class ChildIterator {
// ChildIterator - Iterates over all children
//
// ValueChildIterator - Iterates over all children that produce values used by
// this instruction. For example, includes If::condition
// but not If::ifTrue.
//
template<template<class, class> class Scanner> class AbstractChildIterator {
using Self = AbstractChildIterator<Scanner>;
struct Iterator {
const ChildIterator& parent;
const Self& parent;
Index index;

Iterator(const ChildIterator& parent, Index index)
: parent(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);
Expand All @@ -52,21 +59,21 @@ class ChildIterator {
};

public:
std::vector<Expression*> children;
SmallVector<Expression*, 4> children;

ChildIterator(Expression* parent) {
AbstractChildIterator(Expression* parent) {
struct Traverser : public PostWalker<Traverser> {
Expression* parent;
std::vector<Expression*>* children;
SmallVector<Expression*, 4>* children;

// We need to scan subchildren exactly once - just the parent.
bool scanned = false;

static void scan(Traverser* self, Expression** currp) {
if (!self->scanned) {
self->scanned = true;
PostWalker<Traverser, UnifiedExpressionVisitor<Traverser>>::scan(
self, currp);
Scanner<Traverser, UnifiedExpressionVisitor<Traverser>>::scan(self,
currp);
} else {
// This is one of the children. Do not scan further, just note it.
self->children->push_back(*currp);
Expand All @@ -82,6 +89,25 @@ class ChildIterator {
Iterator end() const { return Iterator(*this, children.size()); }
};

template<class SubType, class Visitor>
struct ValueChildScanner : PostWalker<SubType, Visitor> {
static void scan(SubType* self, Expression** currp) {
auto* curr = *currp;
if (Properties::isControlFlowStructure(curr)) {
// If conditions are the only value children of control flow structures
if (auto* iff = curr->dynCast<If>()) {
self->pushTask(SubType::scan, &iff->condition);
}
} else {
// All children on non-control flow expressions are value children
PostWalker<SubType, Visitor>::scan(self, currp);
}
}
};

using ChildIterator = AbstractChildIterator<PostWalker>;
using ValueChildIterator = AbstractChildIterator<ValueChildScanner>;

// Returns true if the current expression contains a certain kind of expression,
// within the given depth of BFS. If depth is -1, this searches all children.
template<typename T> bool containsChild(Expression* parent, int depth = -1) {
Expand Down
1 change: 0 additions & 1 deletion src/ir/properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

#include "ir/bits.h"
#include "ir/effects.h"
#include "ir/iteration.h"
#include "wasm.h"

namespace wasm {
Expand Down
20 changes: 7 additions & 13 deletions src/ir/stack-utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

#include "stack-utils.h"
#include "ir/iteration.h"
#include "ir/properties.h"

namespace wasm {
Expand Down Expand Up @@ -56,20 +57,13 @@ bool mayBeUnreachable(Expression* expr) {
} // namespace StackUtils

StackSignature::StackSignature(Expression* expr) {
params = Type::none;
if (Properties::isControlFlowStructure(expr)) {
if (expr->is<If>()) {
params = Type::i32;
}
} else {
std::vector<Type> inputs;
for (auto* child : ChildIterator(expr)) {
assert(child->type.isConcrete());
// Children might be tuple pops, so expand their types
inputs.insert(inputs.end(), child->type.begin(), child->type.end());
}
params = Type(inputs);
std::vector<Type> inputs;
for (auto* child : ValueChildIterator(expr)) {
assert(child->type.isConcrete());
// Children might be tuple pops, so expand their types
inputs.insert(inputs.end(), child->type.begin(), child->type.end());
}
params = Type(inputs);
if (expr->type == Type::unreachable) {
unreachable = true;
results = Type::none;
Expand Down
Loading