/*
 * Copyright 2026 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 casts (ref.cast and ref.as_non_null) on values that flow into a slot
// whose declared type the uncast value already satisfies. For example:
//
//  (func $callee (param $s (ref $Super)) ..)
//  ..
//  (call $callee
//    (ref.cast (ref $Sub) (local.get $x)) ;; $x is (ref $Super)
//  )
//
// The cast is not needed for validation, and in traps-never-happen mode it can
// be assumed to succeed, so it can be removed:
//
//  (call $callee
//    (local.get $x)
//  )
//
// All value-flowing slots discovered by SubtypingDiscoverer (locals, globals,
// call parameters, function results, struct fields, array elements, control
// flow branches and fallthroughs, etc.) are handled. Casts on the input of a
// ref.test whose outcome is not determined by the input's type are removed as
// well, as they do not affect the result.
//
// Unlike the cast removals done in OptimizeInstructions, which never lose type
// information, the casts removed here may narrow the value beyond the slot
// type. That narrower type is information that refining passes (GUFA,
// signature-refining, type-refining, local-subtyping, etc.) could use to refine
// the slot itself, so this pass is meant to run late in the pipeline, after
// those passes had their chance. It should still be followed by a round of
// general optimizations, as removing the casts can make functions identical
// (helping duplicate-function-elimination) or smaller (helping inlining).
//
// Requires traps-never-happen mode, as removing a cast removes a possible trap.
//

#include <unordered_map>

#include "ir/effects.h"
#include "ir/gc-type-utils.h"
#include "ir/intrinsics.h"
#include "ir/subtype-exprs.h"
#include "pass.h"
#include "passes/passes.h"
#include "wasm-traversal.h"
#include "wasm.h"

namespace wasm {

namespace {

struct StripRefiningCasts
  : public WalkerPass<
      ControlFlowWalker<StripRefiningCasts,
                        SubtypingDiscoverer<StripRefiningCasts>>> {
  using Super =
    WalkerPass<ControlFlowWalker<StripRefiningCasts,
                                 SubtypingDiscoverer<StripRefiningCasts>>>;

  bool isFunctionParallel() override { return true; }

  std::unique_ptr<Pass> create() override {
    return std::make_unique<StripRefiningCasts>();
  }

  void runOnFunction(Module* module, Function* func) override {
    if (getPassOptions().trapsNeverHappen) {
      Super::runOnFunction(module, func);
    }
  }

  // Map from expression slot to the greatest lower bound of all types it must
  // be a subtype of (e.g. a switch value must be a subtype of all its targets).
  std::unordered_map<Expression**, Type> requiredTypes;

  void noteSubtype(Type, Type) {}
  void noteSubtype(HeapType, HeapType) {}
  void noteSubtype(Type, Expression*) {}
  void noteSubtype(Expression*& sub, Type super) {
    auto [it, inserted] = requiredTypes.insert({&sub, super});
    if (!inserted) {
      it->second = Type::getGreatestLowerBound(it->second, super);
    }
  }
  void noteSubtype(Expression*& sub, Expression* super) {
    // TODO: Propagate the required type of |super| itself through fallthrough
    // expressions (e.g. blocks, loops, ifs, selects, br_ifs) and re-finalize
    // them, rather than constraining |sub| by |super|'s current refined type.
    noteSubtype(sub, super->type);
  }
  void noteNonFlowSubtype(Expression*, Type) {}
  void noteCast(HeapType, Type) {}
  void noteCast(Expression*, Type) {}
  void noteCast(Expression*, Expression*) {}

  // Skips casts on |input| while the uncast value is a subtype of |slotType|.
  void skipCasts(Expression*& input, Type slotType) {
    while (true) {
      if (auto* as = input->dynCast<RefAs>()) {
        if (as->op == RefAsNonNull &&
            Type::isSubType(as->value->type, slotType)) {
          input = as->value;
          continue;
        }
      } else if (auto* cast = input->dynCast<RefCast>()) {
        // Removing a descriptor cast also removes the descriptor operand, which
        // we can only do if it has no side effects.
        // TODO: Use ChildLocalizer to preserve side-effecting descriptors in a
        // block and still remove the cast.
        if ((!cast->desc ||
             !EffectAnalyzer(getPassOptions(), *getModule(), cast->desc)
                .hasSideEffects()) &&
            Type::isSubType(cast->ref->type, slotType)) {
          input = cast->ref;
          continue;
        }
      }
      break;
    }
  }

  void visitCall(Call* curr) {
    // call.without.effects operands must also satisfy the signature of the
    // target function operand, not just the import's declared signature.
    if (Intrinsics(*getModule()).isCallWithoutEffects(curr)) {
      return;
    }
    Super::visitCall(curr);
  }

  void visitRefTest(RefTest* curr) {
    // If the type of the input determines the outcome, leave the test to
    // OptimizeInstructions, which will use that type to resolve it.
    // (This also leaves exact tests alone when custom descriptors are disabled,
    // as those are then only valid on inputs of the same exact type, which
    // determines the outcome.)
    if (GCTypeUtils::evaluateCastCheck(curr->ref->type, curr->castType) !=
        GCTypeUtils::Unknown) {
      return;
    }
    // Any input in the hierarchy of the cast type is valid. Nullability does
    // not matter either: a removed cast is assumed to succeed, so it only ever
    // passes its input through unchanged.
    noteSubtype(curr->ref,
                Type(curr->castType.getHeapType().getTop(), Nullable));
  }

  void visitFunction(Function* func) {
    Super::visitFunction(func);
    for (auto& [slot, type] : requiredTypes) {
      skipCasts(*slot, type);
    }
  }
};

} // anonymous namespace

Pass* createStripRefiningCastsPass() { return new StripRefiningCasts(); }

} // namespace wasm
