/*
 * Copyright 2023 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 <cstddef>
#include <iterator>
#include <memory>

#include "ir/effects.h"
#include "ir/js-utils.h"
#include "ir/localize.h"
#include "ir/module-utils.h"
#include "ir/names.h"
#include "ir/struct-utils.h"
#include "ir/subtype-exprs.h"
#include "ir/type-updating.h"
#include "ir/utils.h"
#include "pass.h"
#include "support/index.h"
#include "wasm-traversal.h"
#include "wasm-type.h"
#include "wasm.h"

#ifndef UNSUBTYPING_DEBUG
#define UNSUBTYPING_DEBUG 0
#endif

#if UNSUBTYPING_DEBUG
#include "support/insert_ordered.h"
#else
#include <unordered_map>
#include <unordered_set>
#endif

#if UNSUBTYPING_DEBUG
#define DBG(x) x
#else
#define DBG(x)
#endif

// Compute and use the minimal subtype (and descriptor) relations required to
// maintain module validity and behavior. This minimal relation will be a subset
// of the original subtype (and descriptor) relations. Start by walking the IR
// and collecting pairs of types that need to be in the subtype relation for
// each expression to validate (or require a type to have a descriptor). For
// example, a local.set requires that the type of its operand be a subtype of
// the local's type. Casts do not generate subtypings at this point because it
// is not necessary for the cast target to be a subtype of the cast source for
// the cast to validate.
//
// From that initial subtype relation, we then start finding new subtypings (and
// descriptors) that are required by the subtypings we have found already. These
// transitively required subtypings (and descriptors) come from three sources.
//
// The first source is type definitions. Consider these type definitions:
//
//   (type $A (sub (struct (ref $X))))
//   (type $B (sub $A (struct (ref $Y))))
//
// If we have determined that $B must remain a subtype of $A, then we know that
// $Y must remain a subtype of $X as well, since the type definitions would not
// be valid otherwise. Similarly, knowing that $X must remain a subtype of $Y
// may transitively require other subtypings as well based on their type
// definitions.
//
// The second source of transitive subtyping requirements is casts. Although
// casting from one type to another does not necessarily require that those
// types are related, we do need to make sure that we do not change the
// behavior of casts by removing subtype relationships they might observe. For
// example, consider this module:
//
// (module
//  ;; original subtyping: $bot <: $mid <: $top
//  (type $top (sub (struct)))
//  (type $mid (sub $top (struct)))
//  (type $bot (sub $mid (struct)))
//
//  (func $f
//   (local $top (ref $top))
//   (local $mid (ref $mid))
//
//   ;; Requires $bot <: $top
//   (local.set $top (struct.new $bot))
//
//   ;; Cast $top to $mid
//   (local.set $mid (ref.cast (ref $mid) (local.get $top)))
//  )
// )
//
// The only subtype relation directly required by the IR for this module is $bot
// <: $top. However, if we optimized the module so that $bot <: $top was the
// only subtype relation, we would change the behavior of the cast. In the
// original module, a value of type (ref $bot) is cast to (ref $mid). The cast
// succeeds because in the original module, $bot <: $mid. If we optimize so that
// we have $bot <: $top and no other subtypings, though, the cast will fail
// because the value of type (ref $bot) no longer inhabits (ref $mid). To
// prevent the cast's behavior from changing, we need to ensure that $bot <:
// $mid.
//
// The set of subtyping requirements generated by a cast from $src to $dest is
// that for every known remaining subtype $v of $src, if $v <: $dest in the
// original module, then $v <: $dest in the optimized module. In other words,
// for every type $v of values we know can flow into the cast, if the cast would
// have succeeded for values of type $v before, then we know the cast must
// continue to succeed for values of type $v. These requirements arising from
// casts can also generate transitive requirements because we learn about new
// types of values that can flow into casts as we learn about new subtypes of
// cast sources.
//
// The third source of transitive subtyping requirements is the discovery of
// required descriptors (and vice versa). Subtyping and descriptors combine to
// form this diagram, where rightward arrows mean "described by":
//
//   A -> A.desc
//   ^    ^
//   |    |
//   B -> B.desc
//
// If any three of these types exist in these relations with the others, then
// the validation rules require that the fourth type also exist and be in these
// relations. The only exception is that A.desc is allowed to be missing. This
// complex and recursive relationship between subtyping and descriptor relations
// is why we optimize out unneeded descriptors in this pass rather than e.g.
// GlobalTypeOptimization.
//
// Starting with the initial subtype and descriptor relations determined by
// walking the IR, repeatedly search for new subtypings and descriptors by
// analyzing type definitions and casts until we reach a fixed point. This is
// the minimal subtype/descriptor relation that preserves module validity and
// behavior that can be found without a more precise analysis of types that
// might flow into each cast.

namespace wasm {

namespace {

#if UNSUBTYPING_DEBUG
template<typename K, typename V> using Map = InsertOrderedMap<K, V>;
template<typename T> using Set = InsertOrderedSet<T>;
#else
template<typename K, typename V> using Map = std::unordered_map<K, V>;
template<typename T> using Set = std::unordered_set<T>;
#endif

// A tree (or rather a forest) of types with the ability to query and set
// supertypes in constant time and efficiently iterate over supertypes and
// subtypes.
struct TypeTree {
  struct Node {
    // The type represented by this node.
    HeapType type;
    // The index of the parent (supertype) in the list of nodes. Set to the
    // index of this node if there is no parent.
    Index parent;
    // The index of this node in the parent's list of children, if any, enabling
    // O(1) updates.
    Index indexInParent = 0;
    // The indices of the children (subtypes) in the list of nodes.
    std::vector<Index> children;
    // The index of the described and descriptor types, if they are necessary.
    std::optional<Index> described;
    std::optional<Index> descriptor;
    // Whether subtypes of this type might flow out to JS from a JS-called
    // function or via extern.convert_any.
    bool subtypesExposedToJS = false;

    Node(HeapType type, Index index) : type(type), parent(index) {}
  };

  std::vector<Node> nodes;
  Map<HeapType, Index> indices;

  void setSupertype(HeapType sub, HeapType super) {
    auto childIndex = getIndex(sub);
    auto parentIndex = getIndex(super);
    auto& childNode = nodes[childIndex];
    auto& parentNode = nodes[parentIndex];
    // Remove sub from its old supertype if necessary.
    if (auto oldParentIndex = childNode.parent; oldParentIndex != childIndex) {
      auto& oldParentNode = nodes[oldParentIndex];
      // Move sub to the back of its parent's children and then pop it.
      auto& children = oldParentNode.children;
      assert(children[childNode.indexInParent] == childIndex);
      auto& swappedNode = nodes[children.back()];
      assert(swappedNode.indexInParent == children.size() - 1);
      // Swap the indices in the parent's child vector.
      std::swap(children[childNode.indexInParent], children.back());
      // Swap the index in the kept child.
      swappedNode.indexInParent = childNode.indexInParent;
      children.pop_back();
    }
    childNode.parent = parentIndex;
    childNode.indexInParent = parentNode.children.size();
    parentNode.children.push_back(childIndex);
  }

  std::optional<HeapType> getSupertype(HeapType type) const {
    auto index = maybeGetIndex(type);
    if (!index) {
      return std::nullopt;
    }
    auto parentIndex = nodes[*index].parent;
    if (parentIndex == *index) {
      return std::nullopt;
    }
    return nodes[parentIndex].type;
  }

  void setDescriptor(HeapType described, HeapType descriptor) {
    auto describedIndex = getIndex(described);
    auto descriptorIndex = getIndex(descriptor);
    auto& describedNode = nodes[describedIndex];
    auto& descriptorNode = nodes[descriptorIndex];
    // We only ever set the descriptor once.
    assert(!describedNode.descriptor);
    assert(!descriptorNode.described);
    describedNode.descriptor = descriptorIndex;
    descriptorNode.described = describedIndex;
  }

  std::optional<HeapType> getDescriptor(HeapType type) const {
    auto index = maybeGetIndex(type);
    if (!index) {
      return std::nullopt;
    }
    if (auto descIndex = nodes[*index].descriptor) {
      return nodes[*descIndex].type;
    }
    return std::nullopt;
  }

  std::optional<HeapType> getDescribed(HeapType type) const {
    auto index = maybeGetIndex(type);
    if (!index) {
      return std::nullopt;
    }
    if (auto descIndex = nodes[*index].described) {
      return nodes[*descIndex].type;
    }
    return std::nullopt;
  }

  void setSubtypesExposedToJS(HeapType type) {
    auto index = getIndex(type);
    nodes[index].subtypesExposedToJS = true;
  }

  bool areSubtypesExposedToJS(HeapType type) const {
    auto index = maybeGetIndex(type);
    if (!index) {
      return false;
    }
    return nodes[*index].subtypesExposedToJS;
  }

  struct SupertypeIterator {
    using value_type = const HeapType;
    using difference_type = std::ptrdiff_t;
    using reference = const HeapType&;
    using pointer = const HeapType*;
    using iterator_category = std::input_iterator_tag;

    TypeTree* parent;
    std::optional<Index> index;

    bool operator==(const SupertypeIterator& other) const {
      return index == other.index;
    }
    bool operator!=(const SupertypeIterator& other) const {
      return !(*this == other);
    }
    const HeapType& operator*() const { return parent->nodes[*index].type; }
    const HeapType* operator->() const { return &*(*this); }
    SupertypeIterator& operator++() {
      auto parentIndex = parent->nodes[*index].parent;
      if (parentIndex == *index) {
        index = std::nullopt;
      } else {
        index = parentIndex;
      }
      return *this;
    }
    SupertypeIterator operator++(int) {
      auto it = *this;
      ++(*this);
      return it;
    }
  };

  struct Supertypes {
    TypeTree* parent;
    Index index;
    SupertypeIterator begin() { return {parent, index}; }
    SupertypeIterator end() { return {parent, std::nullopt}; }
  };

  Supertypes supertypes(HeapType type) { return {this, getIndex(type)}; }

  struct ImmediateSubtypeIterator {
    using value_type = const HeapType;
    using difference_type = std::ptrdiff_t;
    using reference = const HeapType&;
    using pointer = const HeapType*;
    using iterator_category = std::input_iterator_tag;

    TypeTree* parent;
    std::vector<Index>::const_iterator child;

    bool operator==(const ImmediateSubtypeIterator& other) const {
      return child == other.child;
    }
    bool operator!=(const ImmediateSubtypeIterator& other) const {
      return !(*this == other);
    }
    const HeapType& operator*() const { return parent->nodes[*child].type; }
    const HeapType* operator->() const { return &*(*this); }
    ImmediateSubtypeIterator& operator++() {
      ++child;
      return *this;
    }
    ImmediateSubtypeIterator operator++(int) {
      auto it = *this;
      ++(*this);
      return it;
    }
  };

  struct ImmediateSubtypes {
    TypeTree* parent;
    Index index;
    ImmediateSubtypeIterator begin() {
      return {parent, parent->nodes[index].children.begin()};
    }
    ImmediateSubtypeIterator end() {
      return {parent, parent->nodes[index].children.end()};
    }
  };

  ImmediateSubtypes immediateSubtypes(HeapType type) {
    return {this, getIndex(type)};
  }

  struct SubtypeIterator {
    using value_type = const HeapType;
    using difference_type = std::ptrdiff_t;
    using reference = const HeapType&;
    using pointer = const HeapType*;
    using iterator_category = std::input_iterator_tag;

    TypeTree* parent;

    // DFS stack of (node index, child index) pairs.
    std::vector<std::pair<Index, Index>> stack;

    bool operator==(const SubtypeIterator& other) {
      return stack == other.stack;
    }
    bool operator!=(const SubtypeIterator& other) { return !(*this == other); }
    const HeapType& operator*() const {
      return parent->nodes[stack.back().first].type;
    }
    const HeapType* operator->() const { return &*(*this); }
    SubtypeIterator& operator++() {
      while (true) {
        if (stack.empty()) {
          return *this;
        }
        auto& [index, childIndex] = stack.back();
        auto& children = parent->nodes[index].children;
        if (childIndex == children.size()) {
          stack.pop_back();
        } else {
          auto child = children[childIndex++];
          stack.push_back({child, 0u});
          return *this;
        }
      }
    }
    SubtypeIterator operator++(int) {
      auto it = *this;
      ++(*this);
      return it;
    }
  };

  struct Subtypes {
    TypeTree* parent;
    Index index;
    SubtypeIterator begin() { return {parent, {std::make_pair(index, 0u)}}; }
    SubtypeIterator end() { return {parent, {}}; }
  };

  Subtypes subtypes(HeapType type) { return {this, getIndex(type)}; }

#if UNSUBTYPING_DEBUG
  void dump(Module& wasm) {
    for (auto& node : nodes) {
      std::cerr << ModuleHeapType(wasm, node.type);
      if (auto super = getSupertype(node.type)) {
        std::cerr << " <: " << ModuleHeapType(wasm, *super);
      }
      if (auto desc = getDescribed(node.type)) {
        std::cerr << ", describes " << ModuleHeapType(wasm, *desc);
      }
      if (auto desc = getDescriptor(node.type)) {
        std::cerr << ", descriptor " << ModuleHeapType(wasm, *desc);
      }
      std::cerr << ", children:";
      for (auto child : node.children) {
        std::cerr << " " << ModuleHeapType(wasm, nodes[child].type);
      }
      if (node.subtypesExposedToJS) {
        std::cerr << ", subtypes exposed to JS";
      }
      std::cerr << '\n';
    }
  }
#endif

private:
  Index getIndex(HeapType type) {
    auto [it, inserted] = indices.insert({type, nodes.size()});
    if (inserted) {
      nodes.emplace_back(type, nodes.size());
    }
    return it->second;
  }

  std::optional<Index> maybeGetIndex(HeapType type) const {
    if (auto it = indices.find(type); it != indices.end()) {
      return it->second;
    }
    return std::nullopt;
  }
};

// There are two contexts where we have to note subtypings and casts: in the
// initial parallel analysis of the module and in the follow-on fixed point
// analysis over the type tree. Most of the logic is the same in both cases, but
// the final update of data structures is different. This CRTP utility
// deduplicates the shared logic.
template<typename Self> struct Noter {
  DBG(Module* wasm = nullptr);

  Self& self() { return *static_cast<Self*>(this); }

  void noteSubtype(HeapType sub, HeapType super) {
    // Bottom types are uninteresting, but other basic heap types can be
    // interesting because of their interactions with casts.
    if (sub == super || sub.isBottom()) {
      return;
    }
    DBG(std::cerr << "noting " << ModuleHeapType(*wasm, sub)
                  << " <: " << ModuleHeapType(*wasm, super) << '\n');
    self().doNoteSubtype(sub, super);
  }

  void noteSubtype(Type sub, Type super) {
    if (sub.isTuple()) {
      assert(super.isTuple() && sub.size() == super.size());
      for (size_t i = 0, size = sub.size(); i < size; ++i) {
        noteSubtype(sub[i], super[i]);
      }
      return;
    }
    if (!sub.isRef() || !super.isRef()) {
      return;
    }
    noteSubtype(sub.getHeapType(), super.getHeapType());
  }

  void noteSubtype(Type sub, Expression* super) {
    noteSubtype(sub, super->type);
  }

  void noteSubtype(Expression* sub, Type super) {
    noteSubtype(sub->type, super);
  }

  void noteSubtype(Expression* sub, Expression* super) {
    noteSubtype(sub->type, super->type);
  }

  void noteDescriptor(HeapType described, HeapType descriptor) {
    DBG(std::cerr << "noting " << ModuleHeapType(*wasm, described) << " -> "
                  << ModuleHeapType(*wasm, descriptor) << '\n');
    self().doNoteDescriptor(described, descriptor);
  }

  void noteDescribed(HeapType type) {
    auto desc = type.getDescriptorType();
    assert(desc);
    noteDescriptor(type, *desc);
  }

  void noteDescriptor(HeapType type) {
    auto desc = type.getDescribedType();
    assert(desc);
    noteDescriptor(*desc, type);
  }

  void noteCast(HeapType src, Type dstType) {
    auto dst = dstType.getHeapType();
    // Casts to self and casts that must fail because they have incompatible
    // types are uninteresting.
    if (dst == src) {
      return;
    }
    if (HeapType::isSubType(dst, src)) {
      if (dstType.isExact()) {
        // This cast only tests that the exact destination type is a subtype
        // of the source type and does not impose additional requirements on
        // subtypes of the destination type like a normal cast does.
        noteSubtype(dst, src);
        return;
      }
      self().doNoteCast(src, dst);
      return;
    }
    if (HeapType::isSubType(src, dst)) {
      // This is an upcast that will always succeed, but only if we ensure
      // src <: dst.
      noteSubtype(src, dst);
    }
  }

  void noteCast(Expression* src, Type dst) {
    if (src->type.isRef() && dst.isRef()) {
      noteCast(src->type.getHeapType(), dst);
    }
  }

  void noteCast(Expression* src, Expression* dst) {
    if (src->type.isRef() && dst->type.isRef()) {
      noteCast(src->type.getHeapType(), dst->type);
    }
  }
};

struct Unsubtyping : Pass, Noter<Unsubtyping> {
  // The kind of work to process.
  enum class Kind { Subtype, Descriptor };
  // (sub, super) pairs that we have discovered but not yet processed.
  std::vector<std::tuple<Kind, HeapType, HeapType>> work;

  // Record the type tree with supertype and subtype relations in such a way
  // that we can add new supertype relationships in constant time.
  TypeTree types;

  // Map from cast source types to their destinations.
  Map<HeapType, std::vector<HeapType>> casts;

  void run(Module* wasm) override {
    DBG(this->wasm = wasm);
    if (!wasm->features.hasGC()) {
      return;
    }

    if (!getPassOptions().closedWorld) {
      Fatal() << "Unsubtyping requires --closed-world";
    }

    // Initialize the subtype relation based on what is immediately required to
    // keep the code and public types valid.
    analyzePublicTypes(*wasm);
    analyzeJSInterface(*wasm);
    analyzeModule(*wasm);

    // Find further subtypings and iterate to a fixed point.
    while (!work.empty()) {
      auto [kind, a, b] = work.back();
      work.pop_back();
      switch (kind) {
        case Kind::Subtype:
          processSubtype(a, b);
          break;
        case Kind::Descriptor:
          processDescriptor(a, b);
          break;
      }
    }

    DBG(types.dump(*wasm));
    // If we removed a descriptor from a type, we may need to update its
    // allocation sites accordingly.
    fixupAllocations(*wasm);

    rewriteTypes(*wasm);

    // Cast types may be refinable if their source and target types are no
    // longer related. TODO: Experiment with running this only after checking
    // whether it is necessary.
    ReFinalize().run(getPassRunner(), wasm);
  }

  void doNoteSubtype(HeapType sub, HeapType super) {
    work.push_back({Kind::Subtype, sub, super});
  }

  void doNoteCast(HeapType src, HeapType dst) { casts[src].push_back(dst); }

  void doNoteDescriptor(HeapType described, HeapType descriptor) {
    work.push_back({Kind::Descriptor, described, descriptor});
  }

  void noteExposedToJS(Type type) {
    if (!type.isRef()) {
      return;
    }
    noteExposedToJS(type.getHeapType(), type.getExactness());
  }

  void noteExposedToJS(HeapType type, Exactness exact = Inexact) {
    // Keep any descriptor that may configure a prototype.
    if (auto desc = type.getDescriptorType();
        desc && JSUtils::hasPossibleJSPrototypeField(*desc)) {
      noteDescriptor(type, *desc);
    }
    if (exact == Inexact) {
      types.setSubtypesExposedToJS(type);
    }
  }

  void analyzePublicTypes(Module& wasm) {
    // We cannot change supertypes for anything public.
    for (auto type : ModuleUtils::getPublicHeapTypes(wasm)) {
      if (auto super = type.getDeclaredSuperType()) {
        noteSubtype(type, *super);
      }
      if (auto desc = type.getDescriptorType()) {
        noteDescriptor(type, *desc);
      }
    }
  }

  void analyzeJSInterface(const Module& wasm) {
    if (!wasm.features.hasCustomDescriptors()) {
      return;
    }
    Type anyref(HeapType::any, Nullable);

    // Values flowing in from JS are implicitly cast from any.
    auto flowIn = [&](Type type) {
      if (Type::isSubType(type, anyref)) {
        noteCast(HeapType::any, type);
      }
    };

    // Values flowing out to JS are converted to extern and might come back in
    // as anyrefs. Their descriptors may need to be kept to configure JS
    // prototypes.
    auto flowOut = [&](Type type) {
      if (Type::isSubType(type, anyref)) {
        noteSubtype(type.getHeapType(), HeapType::any);
        noteExposedToJS(type);
      }
    };

    JSUtils::iterJSInterface(wasm, flowIn, flowOut);
  }

  void analyzeModule(Module& wasm) {
    struct Info {
      // (source, target) pairs for casts.
      Set<std::pair<HeapType, HeapType>> casts;

      // Observed (sub, super) subtype constraints.
      Set<std::pair<HeapType, HeapType>> subtypings;

      // Observed (described, descriptor) requirements.
      Set<std::pair<HeapType, HeapType>> descriptors;

      // Observed externalized types.
      Set<Type> exposedToJS;
    };

    struct Collector
      : ControlFlowWalker<Collector, SubtypingDiscoverer<Collector>>,
        Noter<Collector> {
      using Super =
        ControlFlowWalker<Collector, SubtypingDiscoverer<Collector>>;

      Info& info;
      bool trapsNeverHappen;

      Collector(Info& info, bool trapsNeverHappen, Module* wasm)
        : info(info), trapsNeverHappen(trapsNeverHappen) {
        DBG(this->wasm = wasm);
      }

      void doNoteSubtype(HeapType sub, HeapType super) {
        info.subtypings.insert({sub, super});
      }

      void noteNonFlowSubtype(Expression* sub, Type super) {
        // This expression's type must be a subtype of |super|, but the value
        // does not flow anywhere - this is a static constraint. As the value
        // does not flow, it cannot reach anywhere else, which means we need
        // this in order to validate but it does not interact with casts. Given
        // that, if super is a basic type then we can simply ignore this: we
        // only remove subtyping between user types, so subtyping wrt basic
        // types is unchanged, and so this constraint will never be a problem.
        //
        // This is sort of a hack because in general to be precise we should not
        // just consider basic types here - in general, we should note for each
        // constraint whether it is a flow-based one or not, and only take the
        // flow-based ones into account when looking at the impact of casts.
        // However, in practice this is enough as the only non-trivial case of
        // |noteNonFlowSubtype| is for RefEq, which uses a basic type (eqref).
        // Other cases of non-flow subtyping end up trivial, e.g., the target of
        // a CallRef is compared to itself (and we ignore constraints of A :>
        // A). However, if we change how |noteNonFlowSubtype| is used in
        // SubtypingDiscoverer then we may need to generalize this.
        if (super.isRef() && super.getHeapType().isBasic()) {
          return;
        }

        // Otherwise, we must take this into account.
        noteSubtype(sub, super);
      }

      void doNoteCast(HeapType src, HeapType dst) {
        info.casts.insert({src, dst});
      }

      void doNoteDescriptor(HeapType described, HeapType descriptor) {
        info.descriptors.insert({described, descriptor});
      }

      void visitRefGetDesc(RefGetDesc* curr) {
        Super::visitRefGetDesc(curr);
        if (!curr->ref->type.isStruct()) {
          return;
        }
        noteDescribed(curr->ref->type.getHeapType());
      }
      void visitRefCast(RefCast* curr) {
        Super::visitRefCast(curr);
        if (!curr->desc || !curr->desc->type.isStruct()) {
          return;
        }
        noteDescriptor(curr->desc->type.getHeapType());
      }
      void visitBrOn(BrOn* curr) {
        Super::visitBrOn(curr);
        if (!curr->desc || !curr->desc->type.isStruct()) {
          return;
        }
        noteDescriptor(curr->desc->type.getHeapType());
      }
      void visitStructNew(StructNew* curr) {
        Super::visitStructNew(curr);
        if (curr->type == Type::unreachable || !curr->desc) {
          return;
        }
        // Normally we do not treat struct.new as requiring a descriptor, even
        // if it has one. We are happy to optimize out descriptors that are set
        // in allocations and then never used. But if the descriptor is nullable
        // and outside a function context and we assume it may be null and cause
        // a trap, then we have no way to preserve that trap without keeping the
        // descriptor around.
        if (trapsNeverHappen || getFunction() ||
            curr->desc->type.isNonNullable()) {
          return;
        }
        // We must preserve the potential trap. When we update the instructions
        // later we will move this allocation to a new global if necessary to
        // preserve the potential trap even if a parent of the current
        // expression is removed.
        noteDescribed(curr->type.getHeapType());
      }
      void visitRefAs(RefAs* curr) {
        Super::visitRefAs(curr);
        // extern.convert_any makes its operand type visible to JS, which may
        // require us to keep descriptors that configure prototypes.
        if (curr->op == ExternConvertAny && curr->value->type.isRef()) {
          info.exposedToJS.insert(curr->value->type);
        }
      }
    };

    bool trapsNeverHappen = getPassOptions().trapsNeverHappen;

    // Collect subtyping constraints and casts from functions in parallel.
    ModuleUtils::ParallelFunctionAnalysis<Info> analysis(
      wasm, [&](Function* func, Info& info) {
        if (!func->imported()) {
          Collector(info, trapsNeverHappen, &wasm)
            .walkFunctionInModule(func, &wasm);
        }
      });

    Info collectedInfo;
    for (auto& [_, info] : analysis.map) {
      collectedInfo.casts.insert(info.casts.begin(), info.casts.end());
      collectedInfo.subtypings.insert(info.subtypings.begin(),
                                      info.subtypings.end());
      collectedInfo.descriptors.insert(info.descriptors.begin(),
                                       info.descriptors.end());
      collectedInfo.exposedToJS.insert(info.exposedToJS.begin(),
                                       info.exposedToJS.end());
    }

    // Collect constraints from module-level code as well.
    Collector collector(collectedInfo, trapsNeverHappen, &wasm);
    collector.walkModuleCode(&wasm);
    collector.setModule(&wasm);
    for (auto& global : wasm.globals) {
      collector.visitGlobal(global.get());
    }
    for (auto& table : wasm.tables) {
      collector.visitTable(table.get());
    }
    for (auto& segment : wasm.elementSegments) {
      collector.visitElementSegment(segment.get());
    }

    // Prepare the collected information for the upcoming processing loop.
    for (auto type : collectedInfo.exposedToJS) {
      noteExposedToJS(type);
    }
    for (auto& [sub, super] : collectedInfo.subtypings) {
      noteSubtype(sub, super);
    }
    // Combine casts we have already noted into the newly gathered casts.
    for (auto& [src, dsts] : casts) {
      for (auto dst : dsts) {
        collectedInfo.casts.insert({src, dst});
      }
      dsts.clear();
    }
    // Record the deduplicated cast info.
    for (auto [src, dst] : collectedInfo.casts) {
      casts[src].push_back(dst);
    }
    for (auto [described, descriptor] : collectedInfo.descriptors) {
      noteDescriptor(described, descriptor);
    }
  }

  void processSubtype(HeapType sub, HeapType super) {
    DBG(std::cerr << "processing " << ModuleHeapType(*wasm, sub)
                  << " <: " << ModuleHeapType(*wasm, super) << '\n');
    assert(HeapType::isSubType(sub, super));
    auto oldSuper = types.getSupertype(sub);
    if (oldSuper) {
      // We already had a recorded supertype. The new supertype might be
      // deeper,shallower, or equal to the old supertype. We must recursively
      // note the relationship between the old and new supertypes.
      if (super == *oldSuper) {
        // Nothing new to do here.
        return;
      }
      if (HeapType::isSubType(*oldSuper, super)) {
        // sub <: oldSuper <: super
        noteSubtype(*oldSuper, super);
        // We already handled sub <: oldSuper, so we're done.
        return;
      }
      // sub <: super <: oldSuper
      // Eagerly process super <: oldSuper first. This ensures that sub and
      // super will already be in the same tree when we process them below, so
      // when we process casts we will know that we only need to process up to
      // oldSuper.
      processSubtype(super, *oldSuper);
    }

    types.setSupertype(sub, super);

    // If the supertype is exposed to JS, the subtype potentially is as well.
    // `sub` may be the root of some existing subtype tree, and we have to
    // propagate the exposure to JS to all those existing subtypes. We could
    // just iterate over subtypes(), but manually traverse using
    // immediateSubtypes() so we can avoid visiting subtrees that have already
    // been marked.
    if (types.areSubtypesExposedToJS(super)) {
      std::vector<HeapType> work{{sub}};
      while (!work.empty()) {
        auto curr = work.back();
        work.pop_back();
        if (!types.areSubtypesExposedToJS(curr)) {
          noteExposedToJS(curr);
          auto subtypes = types.immediateSubtypes(curr);
          work.insert(work.end(), subtypes.begin(), subtypes.end());
        }
      }
    }

    // Complete the descriptor squares to the left and right of the new
    // subtyping edge if those squares can possibly exist based on the original
    // types.
    if (super.getDescribedType()) {
      completeDescriptorSquare(
        types.getDescribed(super), super, types.getDescribed(sub), sub);
    }
    if (super.getDescriptorType()) {
      completeDescriptorSquare(
        super, types.getDescriptor(super), sub, types.getDescriptor(sub));
    }

    // Find the implied subtypings from the type definitions and casts.
    processDefinitions(sub, super);
    processCasts(sub, super, oldSuper);
  }

  void processDescriptor(HeapType described, HeapType descriptor) {
    DBG(std::cerr << "processing " << ModuleHeapType(*wasm, described) << " -> "
                  << ModuleHeapType(*wasm, descriptor) << '\n');
    assert(described.getDescriptorType() &&
           *described.getDescriptorType() == descriptor);
    if (auto oldDesc = types.getDescriptor(described)) {
      // We already know about this descriptor.
      assert(*oldDesc == descriptor);
      return;
    }

    types.setDescriptor(described, descriptor);

    // Complete the descriptor squares above and below the new descriptor edge.
    completeDescriptorSquare(
      std::nullopt, types.getSupertype(descriptor), described, descriptor);
    for (auto sub : types.immediateSubtypes(described)) {
      completeDescriptorSquare(
        described, descriptor, sub, types.getDescriptor(sub));
    }
    for (auto subDesc : types.immediateSubtypes(descriptor)) {
      completeDescriptorSquare(
        described, descriptor, types.getDescribed(subDesc), subDesc);
    }
  }

  void processDefinitions(HeapType sub, HeapType super) {
    if (super.isBasic()) {
      return;
    }
    switch (sub.getKind()) {
      case HeapTypeKind::Func: {
        auto sig = sub.getSignature();
        auto superSig = super.getSignature();
        noteSubtype(superSig.params, sig.params);
        noteSubtype(sig.results, superSig.results);
        break;
      }
      case HeapTypeKind::Struct: {
        const auto& fields = sub.getStruct().fields;
        const auto& superFields = super.getStruct().fields;
        for (size_t i = 0, size = superFields.size(); i < size; ++i) {
          noteSubtype(fields[i].type, superFields[i].type);
        }
        break;
      }
      case HeapTypeKind::Array: {
        auto elem = sub.getArray().element;
        noteSubtype(elem.type, super.getArray().element.type);
        break;
      }
      case HeapTypeKind::Cont: {
        noteSubtype(sub.getContinuation().type, super.getContinuation().type);
        break;
      }
      case HeapTypeKind::Basic:
        WASM_UNREACHABLE("unexpected kind");
    }
  }

  void
  processCasts(HeapType sub, HeapType super, std::optional<HeapType> oldSuper) {
    // We are either attaching the one tree rooted at `sub` under a new
    // supertype in another tree, or we are reparenting `sub` below a
    // descendent of `oldSuper` in the same tree. In the former case, we must
    // evaluate `sub` and all its subtypes against all its new supertypes and
    // their cast destinations. In the latter case, `sub` and all its subtypes
    // must have already been evaluated against `oldSuper` and its supertypes,
    // so we only need to additionally evaluate them against supertypes up to
    // `oldSuper`.
    for (auto type : types.subtypes(sub)) {
      for (auto src : types.supertypes(super)) {
        if (oldSuper && src == *oldSuper) {
          break;
        }
        for (auto dst : casts[src]) {
          if (HeapType::isSubType(type, dst)) {
            noteSubtype(type, dst);
          }
        }
      }
    }
  }

  void completeDescriptorSquare(std::optional<HeapType> super,
                                std::optional<HeapType> superDesc,
                                std::optional<HeapType> sub,
                                std::optional<HeapType> subDesc) {
    if ((super && super->isBasic()) || (superDesc && superDesc->isBasic())) {
      // Basic types do not have descriptors or described types, so do not form
      // descriptor squares.
      return;
    }
    if (bool(super) + bool(superDesc) + bool(sub) + bool(subDesc) < 3) {
      // We must have two adjacent edges (involving at least 3 types) for there
      // to be any further requirements.
      return;
    }
    // There may be up to one missing type. Look it up using its original
    // descriptor relation with the present types and add the missing edges.
    if (!super) {
      super = superDesc->getDescribedType();
    } else if (!sub) {
      sub = subDesc->getDescribedType();
    } else if (!subDesc) {
      subDesc = sub->getDescriptorType();
    } else if (!superDesc) {
      // This is the only type that is allowed to be missing.
      return;
    }
    // Add all the edges. Don't worry about duplicating existing edges because
    // checking whether they're necessary now would be about as expensive as
    // discarding them later.
    noteSubtype(*sub, *super);
    noteSubtype(*subDesc, *superDesc);
    noteDescriptor(*super, *superDesc);
    noteDescriptor(*sub, *subDesc);
  }

  void rewriteTypes(Module& wasm) {
    struct Rewriter : GlobalTypeRewriter {
      Unsubtyping& parent;
      Rewriter(Unsubtyping& parent, Module& wasm)
        : GlobalTypeRewriter(wasm), parent(parent) {}
      std::optional<HeapType> getDeclaredSuperType(HeapType type) override {
        if (auto super = parent.types.getSupertype(type);
            super && !super->isBasic()) {
          return *super;
        }
        return std::nullopt;
      }
      void modifyTypeBuilderEntry(TypeBuilder& typeBuilder,
                                  Index i,
                                  HeapType oldType) override {
        if (!parent.types.getDescribed(oldType)) {
          typeBuilder[i].describes(std::nullopt);
        }
        if (!parent.types.getDescriptor(oldType)) {
          typeBuilder[i].descriptor(std::nullopt);
        }
      }
    };
    Rewriter(*this, wasm).update();
  }

  void fixupAllocations(Module& wasm) {
    if (!wasm.features.hasCustomDescriptors()) {
      return;
    }
    // TODO: Consider running the fixup only if we are actually removing any
    // descriptors. This would require a better way of detecting this than
    // collecting and iterating over all the types, though.
    struct Rewriter : WalkerPass<PostWalker<Rewriter>> {
      const TypeTree& types;

      // Allocations that might trap that have been removed from module-level
      // initializers. These need to be placed in new globals to preserve any
      // instantiation-time traps.
      std::vector<Expression*> removedTrappingInits;

      Rewriter(const TypeTree& types) : types(types) {}

      bool isFunctionParallel() override { return true; }
      // Only introduces locals that are set immediately before they are used.
      bool requiresNonNullableLocalFixups() override { return false; }
      std::unique_ptr<Pass> create() override {
        return std::make_unique<Rewriter>(types);
      }

      void visitStructNew(StructNew* curr) {
        if (curr->type == Type::unreachable) {
          return;
        }
        if (!curr->desc) {
          return;
        }
        if (types.getDescriptor(curr->type.getHeapType())) {
          return;
        }
        // We need to drop the descriptor argument. In a function context, use
        // ChildLocalizer. Outside a function context just drop the operand
        // because there can be no side effects anyway.
        if (auto* func = getFunction()) {
          // Preserve a trap from a null descriptor if necessary.
          if (!getPassOptions().trapsNeverHappen &&
              curr->desc->type.isNullable()) {
            curr->desc =
              Builder(*getModule()).makeRefAs(RefAsNonNull, curr->desc);
          }
          auto* block =
            ChildLocalizer(curr, func, *getModule(), getPassOptions())
              .getChildrenReplacement();
          block->list.push_back(curr);
          block->type = curr->type;
          replaceCurrent(block);
        } else {
          // We are dropping this descriptor, but it might have a potential trap
          // nested inside it. In that case we need to preserve the trap by
          // moving this descriptor to a new global.
          if (curr->desc->is<StructNew>() &&
              EffectAnalyzer(getPassOptions(), *getModule(), curr->desc).trap) {
            removedTrappingInits.push_back(curr->desc);
          }
        }
        curr->desc = nullptr;
      }
    };

    Rewriter rewriter(types);
    rewriter.run(getPassRunner(), &wasm);
    rewriter.runOnModuleCode(getPassRunner(), &wasm);

    // Insert globals necessary to preserve instantiation-time trapping of
    // removed allocations.
    for (Index i = 0; i < rewriter.removedTrappingInits.size(); ++i) {
      auto* curr = rewriter.removedTrappingInits[i];
      auto name = Names::getValidGlobalName(
        wasm, std::string("unsubtyping-removed-") + std::to_string(i));
      wasm.addGlobal(
        Builder::makeGlobal(name, curr->type, curr, Builder::Immutable));
    }
  }
};

} // anonymous namespace

Pass* createUnsubtypingPass() { return new Unsubtyping(); }

} // namespace wasm
