/*
 * Copyright 2015 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.
 */

//
// Removes names from locations that are never branched to, and
// merge names when possible (by merging their blocks)
//

#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; }

  // We maintain a list of branches that we saw in children, then when we reach
  // a parent block, we know if it was branched to
  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) {
        // we have just one child, this block, so breaking out of it goes to the
        // same place as breaking out of us, we just need one name (and block)
        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(); }

} // namespace wasm
