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

#include "ir/drop.h"
#include "ir/branch-utils.h"
#include "ir/effects.h"
#include "ir/iteration.h"
#include "wasm-builder.h"
#include "wasm.h"

namespace wasm {

Expression* getDroppedChildrenAndAppend(Expression* parent,
                                        Module& wasm,
                                        const PassOptions& options,
                                        Expression* last,
                                        DropMode mode) {
  // We check for shallow effects here, since we may be able to remove |parent|
  // itself but keep its children around - we don't want effects in the children
  // to stop us from improving the code. Note that there are cases where the
  // combined parent+children has fewer effects than parent itself, such as if
  // parent is a block and the child branches to it, but in such cases we cannot
  // remove parent anyhow (those cases are ruled out below), so looking at
  // non-shallow effects would never help us (and would be slower to run).
  bool keepParent = false;
  if (mode == DropMode::NoticeParentEffects) {
    ShallowEffectAnalyzer effects(options, wasm, parent);
    // Ignore a trap, as the unreachable replacement would trap too.
    if (last->is<Unreachable>()) {
      effects.set(EffectAnalyzer::Bits::Trap, false);
    }
    keepParent = effects.hasUnremovableSideEffects();
  }

  // We cannot remove
  // 1. Expressions with unremovable side effects
  // 2. if: 'if's contains conditional expressions
  // 3. try: Removing a try could leave a pop without a proper parent
  // 4. pop: Pops are struturally necessary in catch bodies
  // 5. Branch targets: We will need the target for the branches to it to
  //                    validate.
  Builder builder(wasm);
  if (keepParent || parent->is<If>() || parent->is<Try>() ||
      parent->is<Pop>() || BranchUtils::getDefinedName(parent).is()) {
    // If parent is concrete we must drop it. Or, if it is unreachable or none,
    // then we can leave it as it is.
    if (parent->type.isConcrete()) {
      parent = builder.makeDrop(parent);
    }
    return builder.makeSequence(parent, last);
  }

  std::vector<Expression*> contents;
  for (auto* child : ChildIterator(parent)) {
    if (!EffectAnalyzer(options, wasm, child).hasUnremovableSideEffects()) {
      continue;
    }
    // See above.
    if (child->type.isConcrete()) {
      contents.push_back(builder.makeDrop(child));
    } else {
      contents.push_back(child);
    }
  }
  if (contents.empty()) {
    return last;
  }
  contents.push_back(last);
  return builder.makeBlock(contents);
}

} // namespace wasm
