#include <pass.h>
#include <wasm.h>
namespace wasm {
struct RemoveUnusedNames : public WalkerPass<PostWalker<RemoveUnusedNames>> {
bool isFunctionParallel() override { return true; }
Pass* create() override { return new RemoveUnusedNames; }
std::map<Name, std::set<Expression*>> branchesSeen;
void visitBreak(Break* curr) { branchesSeen[curr->name].insert(curr); }
void visitSwitch(Switch* curr) {
for (auto name : curr->targets) {
branchesSeen[name].insert(curr);
}
branchesSeen[curr->default_].insert(curr);
}
void visitBrOnExn(BrOnExn* curr) { branchesSeen[curr->name].insert(curr); }
void handleBreakTarget(Name& name) {
if (name.is()) {
if (branchesSeen.find(name) == branchesSeen.end()) {
name = Name();
} else {
branchesSeen.erase(name);
}
}
}
void visitBlock(Block* curr) {
if (curr->name.is() && curr->list.size() == 1) {
auto* child = curr->list[0]->dynCast<Block>();
if (child && child->name.is() && child->type == curr->type) {
auto& branches = branchesSeen[curr->name];
for (auto* branch : branches) {
if (Break* br = branch->dynCast<Break>()) {
if (br->name == curr->name) {
br->name = child->name;
}
} else if (Switch* sw = branch->dynCast<Switch>()) {
for (auto& target : sw->targets) {
if (target == curr->name) {
target = child->name;
}
}
if (sw->default_ == curr->name) {
sw->default_ = child->name;
}
} else if (BrOnExn* br = branch->dynCast<BrOnExn>()) {
if (br->name == curr->name) {
br->name = child->name;
}
} else {
WASM_UNREACHABLE("unexpected expr type");
}
}
child->finalize(child->type);
replaceCurrent(child);
}
}
handleBreakTarget(curr->name);
}
void visitLoop(Loop* curr) {
handleBreakTarget(curr->name);
if (!curr->name.is() && curr->body->type == curr->type) {
replaceCurrent(curr->body);
}
}
void visitFunction(Function* curr) { assert(branchesSeen.empty()); }
};
Pass* createRemoveUnusedNamesPass() { return new RemoveUnusedNames(); }
}