/*
 * 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 <optional>
#include <variant>

#include "analysis/cfg.h"
#include "ir/bits.h"
#include "ir/branch-utils.h"
#include "ir/eh-utils.h"
#include "ir/gc-type-utils.h"
#include "ir/linear-execution.h"
#include "ir/local-graph.h"
#include "ir/module-utils.h"
#include "ir/possible-contents.h"
#include "support/insert_ordered.h"

#ifndef POSSIBLE_CONTENTS_DEBUG
#define POSSIBLE_CONTENTS_DEBUG 0
#endif

#if POSSIBLE_CONTENTS_DEBUG
#include "support/timing.h"
#endif
#include "wasm-type.h"
#include "wasm.h"

namespace std {

std::ostream& operator<<(std::ostream& stream,
                         const wasm::PossibleContents& contents) {
  contents.dump(stream);
  return stream;
}

} // namespace std

namespace wasm {

PossibleContents PossibleContents::combine(const PossibleContents& a,
                                           const PossibleContents& b) {
  auto aType = a.getType();
  auto bType = b.getType();
  // First handle the trivial cases of them being equal, or one of them is
  // None or Many.
  if (a == b) {
    return a;
  }
  if (b.isNone()) {
    return a;
  }
  if (a.isNone()) {
    return b;
  }
  if (a.isMany()) {
    return a;
  }
  if (b.isMany()) {
    return b;
  }

  if (!aType.isRef() || !bType.isRef()) {
    // At least one is not a reference. The only possibility left for a useful
    // combination here is if they have the same type (since we've already ruled
    // out the case of them being equal). If they have the same type then
    // neither is a reference and we can emit an exact type (since subtyping is
    // not relevant for non-references).
    if (aType == bType) {
      return ExactType(aType);
    } else {
      return Many();
    }
  }

  // Special handling for references from here.

  if (a.isNull() && b.isNull()) {
    // These must be nulls in different hierarchies, otherwise a would have
    // been handled by the `a == b` case above.
    assert(aType != bType);
    return Many();
  }

  auto lub = Type::getLeastUpperBound(aType, bType);
  if (lub == Type::none) {
    // The types are not in the same hierarchy.
    return Many();
  }

  // From here we can assume there is a useful LUB.

  // Nulls can be combined in by just adding nullability to a type.
  if (a.isNull() || b.isNull()) {
    // Only one of them can be null here, since we already handled the case
    // where they were both null.
    assert(!a.isNull() || !b.isNull());
    // If only one is a null then we can use the type info from the b, and
    // just add in nullability. For example, a literal of type T and a null
    // becomes an exact type of T that allows nulls, and so forth.
    auto mixInNull = [](ConeType cone) {
      cone.type = cone.type.with(Nullable);
      return cone;
    };
    if (!a.isNull()) {
      return mixInNull(a.getCone());
    } else if (!b.isNull()) {
      return mixInNull(b.getCone());
    }
  }

  // Find a ConeType that describes both inputs, using the shared ancestor which
  // is the LUB. We need to find how big a cone we need: the cone must be big
  // enough to contain both the inputs.
  auto aDepth = a.getCone().depth;
  auto bDepth = b.getCone().depth;
  Index newDepth;
  if (aDepth == FullDepth || bDepth == FullDepth) {
    // At least one has full (infinite) depth, so we know the new depth must
    // be the same.
    newDepth = FullDepth;
  } else {
    // The depth we need under the lub is how far from the lub we are, plus
    // the depth of our cone.
    // TODO: we could make a single loop that also does the LUB, at the same
    // time, and also avoids calling getDepth() which loops once more?
    auto aDepthFromRoot = aType.getHeapType().getDepth();
    auto bDepthFromRoot = bType.getHeapType().getDepth();
    auto lubDepthFromRoot = lub.getHeapType().getDepth();
    assert(lubDepthFromRoot <= aDepthFromRoot);
    assert(lubDepthFromRoot <= bDepthFromRoot);
    Index aDepthUnderLub = aDepthFromRoot - lubDepthFromRoot + aDepth;
    Index bDepthUnderLub = bDepthFromRoot - lubDepthFromRoot + bDepth;

    // The total cone must be big enough to contain all the above.
    newDepth = std::max(aDepthUnderLub, bDepthUnderLub);
  }

  return ConeType{lub, newDepth};
}

void PossibleContents::intersect(const PossibleContents& other) {
  // This does not yet handle all possible content.
  assert((other.isConeType() &&
          (other.getType().isExact() || other.hasFullCone())) ||
         other.isLiteral() || other.isNone());

  if (*this == other) {
    // Nothing changes.
    return;
  }

  if (!haveIntersection(*this, other)) {
    // There is no intersection at all.
    // Note that this code path handles |this| or |other| being None.
    value = None();
    return;
  }

  if (isSubContents(other, *this)) {
    // The intersection is just |other|.
    // Note that this code path handles |this| being Many.
    value = other.value;
    return;
  }

  if (isSubContents(*this, other)) {
    // The intersection is just |this|.
    return;
  }

  if (isLiteral() || other.isLiteral()) {
    // We've ruled out either being a subcontents of the other. A literal has
    // no other intersection possibility.
    value = None();
    return;
  }

  auto type = getType();
  auto otherType = other.getType();
  auto heapType = type.getHeapType();
  auto otherHeapType = otherType.getHeapType();

  // Intersect the types.
  auto newType = Type::getGreatestLowerBound(type, otherType);

  auto setNoneOrNull = [&]() {
    if (newType.isNullable()) {
      value = Literal::makeNull(heapType);
    } else {
      value = None();
    }
  };

  if (newType == Type::unreachable || newType.isNull()) {
    setNoneOrNull();
    return;
  }

  // The heap types are compatible, so intersect the cones.
  auto depthFromRoot = heapType.getDepth();
  auto otherDepthFromRoot = otherHeapType.getDepth();
  auto newDepthFromRoot = newType.getHeapType().getDepth();

  // Note the global's information, if we started as a global. In that case, the
  // code below will refine our type but we can remain a global, which we will
  // accomplish by restoring our global status at the end.
  std::optional<GlobalInfo> global;
  if (isGlobal()) {
    global = getGlobal();
  }

  if (hasFullCone() && other.hasFullCone()) {
    // Both are full cones, so the result is as well.
    value = DefaultConeType(newType);
  } else {
    // The result is a partial cone. Check whether the cones overlap, and if
    // they do, find the new depth.
    if (newDepthFromRoot - depthFromRoot > getCone().depth ||
        newDepthFromRoot - otherDepthFromRoot > other.getCone().depth) {
      setNoneOrNull();
      return;
    }
    Index newDepth = getCone().depth - (newDepthFromRoot - depthFromRoot);
    Index otherNewDepth =
      other.getCone().depth - (newDepthFromRoot - otherDepthFromRoot);
    value = ConeType{newType, std::min(newDepth, otherNewDepth)};
  }

  if (global) {
    // Restore the global but keep the new and refined type.
    value = GlobalInfo{global->name, global->kind, getType()};
  }
}

bool PossibleContents::haveIntersection(const PossibleContents& a,
                                        const PossibleContents& b) {
  if (a.isNone() || b.isNone()) {
    // One is the empty set, so nothing can intersect here.
    return false;
  }

  if (a.isMany() || b.isMany()) {
    // One is the set of all things, so definitely something can intersect since
    // we've ruled out an empty set for both.
    return true;
  }

  if (a == b) {
    // The intersection is equal to them.
    return true;
  }

  auto aType = a.getType();
  auto bType = b.getType();

  if (!aType.isRef() || !bType.isRef()) {
    // At least one is not a reference. The only way they can intersect is if
    // the type is identical, and they are not both literals (we've already
    // ruled out them being identical earlier).
    return aType == bType && (!a.isLiteral() || !b.isLiteral());
  }

  // From here on we focus on references.

  auto aHeapType = aType.getHeapType();
  auto bHeapType = bType.getHeapType();

  if (aType.isNullable() && bType.isNullable() &&
      aHeapType.getBottom() == bHeapType.getBottom()) {
    // A compatible null is possible on both sides.
    return true;
  }

  // We ruled out having a compatible null on both sides. If one is simply a
  // null then no chance for an intersection remains.
  if (a.isNull() || b.isNull()) {
    return false;
  }

  auto aSubB = HeapType::isSubType(aHeapType, bHeapType);
  auto bSubA = HeapType::isSubType(bHeapType, aHeapType);
  if (!aSubB && !bSubA) {
    // No type can appear in both a and b, so the types differ, so the values
    // do not overlap.
    return false;
  }

  // From here on we focus on references and can ignore the case of null - any
  // intersection must be of a non-null value, so we can focus on the heap
  // types.

  auto aDepthFromRoot = aHeapType.getDepth();
  auto bDepthFromRoot = bHeapType.getDepth();

  if (aSubB) {
    // A is a subtype of B. For there to be an intersection we need their cones
    // to intersect, that is, to rule out the case where the cone from B is not
    // deep enough to reach A.
    assert(aDepthFromRoot >= bDepthFromRoot);
    return aDepthFromRoot - bDepthFromRoot <= b.getCone().depth;
  } else if (bSubA) {
    assert(bDepthFromRoot >= aDepthFromRoot);
    return bDepthFromRoot - aDepthFromRoot <= a.getCone().depth;
  } else {
    WASM_UNREACHABLE("we ruled out no subtyping before");
  }

  // TODO: we can also optimize things like different Literals, but existing
  //       passes do such things already so it is low priority.
}

bool PossibleContents::isSubContents(const PossibleContents& a,
                                     const PossibleContents& b) {
  if (a == b) {
    return true;
  }

  if (a.isNone()) {
    return true;
  }

  if (b.isNone()) {
    return false;
  }

  if (a.isMany()) {
    return false;
  }

  if (b.isMany()) {
    return true;
  }

  if (a.isLiteral()) {
    // Note we already checked for |a == b| above. We need b to be a set that
    // contains the literal a.
    return !b.isLiteral() && Type::isSubType(a.getType(), b.getType());
  }

  if (b.isLiteral()) {
    return false;
  }

  if (b.isFullConeType()) {
    if (a.isNull()) {
      return b.getType().isNullable();
    }
    return Type::isSubType(a.getType(), b.getType());
  }

  if (a.isFullConeType()) {
    // We've already ruled out b being a full cone type before.
    return false;
  }

  if (b.isGlobal()) {
    // We've already ruled out anything but another global or non-full cone type
    // for a.
    return false;
  }

  assert(b.isConeType() && (a.isConeType() || a.isGlobal()));
  if (!Type::isSubType(a.getType(), b.getType())) {
    return false;
  }
  // Check that a's cone type is enclosed in b's cone type.
  return a.getType().getHeapType().getDepth() + a.getCone().depth <=
         b.getType().getHeapType().getDepth() + b.getCone().depth;
}

namespace {

// We are going to do a very large flow operation, potentially, as we create
// a Location for every interesting part in the entire wasm, and some of those
// places will have lots of links (like a struct field may link out to every
// single struct.get of that type), so we must make the data structures here
// as efficient as possible. Towards that goal, we work with location
// *indexes* where possible, which are small (32 bits) and do not require any
// complex hashing when we use them in sets or maps.
//
// Note that we do not use indexes everywhere, since the initial analysis is
// done in parallel, and we do not have a fixed indexing of locations yet. When
// we merge the parallel data we create that indexing, and use indexes from then
// on.
using LocationIndex = uint32_t;

#ifndef NDEBUG
// Assert on not having duplicates in a vector.
template<typename T> void disallowDuplicates(const T& targets) {
#if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
  std::unordered_set<LocationIndex> uniqueTargets;
  for (const auto& target : targets) {
    uniqueTargets.insert(target);
  }
  assert(uniqueTargets.size() == targets.size());
#endif
}
#endif

// A link indicates a flow of content from one location to another. For
// example, if we do a local.get and return that value from a function, then
// we have a link from the ExpressionLocation of that local.get to a
// ResultLocation.
template<typename T> struct Link {
  T from;
  T to;

  bool operator==(const Link<T>& other) const {
    return from == other.from && to == other.to;
  }
};

using LocationLink = Link<Location>;
using IndexLink = Link<LocationIndex>;

} // anonymous namespace

} // namespace wasm

namespace std {

template<> struct hash<wasm::LocationLink> {
  size_t operator()(const wasm::LocationLink& loc) const {
    return std::hash<std::pair<wasm::Location, wasm::Location>>{}(
      {loc.from, loc.to});
  }
};

template<> struct hash<wasm::IndexLink> {
  size_t operator()(const wasm::IndexLink& loc) const {
    return std::hash<std::pair<wasm::LocationIndex, wasm::LocationIndex>>{}(
      {loc.from, loc.to});
  }
};

} // namespace std

namespace wasm {

namespace {

// Information that is shared with InfoCollector.
struct SharedInfo {
  // Subtyping info.
  const SubTypes& subTypes;

  // The names of tables that are imported or exported.
  std::unordered_set<Name> publicTables;

  SharedInfo(const SubTypes& subTypes) : subTypes(subTypes) {}
};

// The data we gather from each function, as we process them in parallel. Later
// this will be merged into a single big graph.
struct CollectedFuncInfo {
  // All the links we found in this function. Rarely are there duplicates
  // in this list (say when writing to the same global location from another
  // global location), and we do not try to deduplicate here, just store them in
  // a plain array for now, which is faster (later, when we merge all the info
  // from the functions, we need to deduplicate anyhow).
  std::vector<LocationLink> links;

  // All the roots of the graph, that is, places that begin by containing some
  // particular content. That includes i32.const, ref.func, struct.new, etc. All
  // possible contents in the rest of the graph flow from such places.
  //
  // The vector here is of the location of the root and then its contents.
  std::vector<std::pair<Location, PossibleContents>> roots;

  // In some cases we need to know the parent of the expression. Consider this:
  //
  //  (struct.set $A k
  //    (local.get $ref)
  //    (local.get $value)
  //  )
  //
  // Imagine that the first local.get, for $ref, receives a new value. That can
  // affect where the struct.set sends values: if previously that local.get had
  // no possible contents, and now it does, then we have DataLocations to
  // update. Likewise, when the second local.get is updated we must do the same,
  // but again which DataLocations we update depends on the ref passed to the
  // struct.set. To handle such things, we set add a childParent link, and then
  // when we update the child we can find the parent and handle any special
  // behavior we need there.
  std::unordered_map<Expression*, Expression*> childParents;

  // All functions that might be called from the outside. Any RefFunc suggests
  // that, in open world. (We could be more precise and use our flow analysis to
  // see which, in fact, flow outside, but it is unclear how useful that would
  // be. Anyhow, closed-world is more important to optimize, and avoids this.)
  std::unordered_set<Name> calledFromOutside;
};

// Does a walk while maintaining a map of names of branch targets to those
// expressions, so they can be found by their name.
// TODO: can this replace ControlFlowWalker in other places?
template<typename SubType, typename VisitorType = Visitor<SubType>>
struct BreakTargetWalker : public PostWalker<SubType, VisitorType> {
  std::unordered_map<Name, Expression*> breakTargets;

  Expression* findBreakTarget(Name name) { return breakTargets[name]; }

  static void scan(SubType* self, Expression** currp) {
    auto* curr = *currp;
    BranchUtils::operateOnScopeNameDefs(
      curr, [&](Name name) { self->breakTargets[name] = curr; });

    PostWalker<SubType, VisitorType>::scan(self, currp);
  }
};

// Walk the wasm and find all the links we need to care about, and the locations
// and roots related to them. This builds up a CollectedFuncInfo data structure.
// After all InfoCollectors run, those data structures will be merged and the
// main flow will begin.
struct InfoCollector
  : public BreakTargetWalker<InfoCollector, OverriddenVisitor<InfoCollector>> {
  SharedInfo& shared;
  CollectedFuncInfo& info;
  const PassOptions& options;

  InfoCollector(SharedInfo& shared,
                CollectedFuncInfo& info,
                const PassOptions& options)
    : shared(shared), info(info), options(options) {}

  // Check if a type is relevant for us. If not, we can ignore it entirely.
  bool isRelevant(Type type) {
    if (type == Type::unreachable || type == Type::none) {
      return false;
    }
    if (type.isTuple()) {
      for (auto t : type) {
        if (isRelevant(t)) {
          return true;
        }
      }
    }
    return true;
  }

  bool isRelevant(Signature sig) {
    return isRelevant(sig.params) || isRelevant(sig.results);
  }

  bool isRelevant(Expression* curr) { return curr && isRelevant(curr->type); }

  template<typename T> bool isRelevant(const T& vec) {
    for (auto* expr : vec) {
      if (isRelevant(expr->type)) {
        return true;
      }
    }
    return false;
  }

  // Each visit*() call is responsible for connecting the children of a node to
  // that node. Responsibility for connecting the node's output to anywhere
  // else (another expression or the function itself, if we are at the top
  // level) is the responsibility of the outside.

  void visitBlock(Block* curr) {
    if (curr->list.empty()) {
      return;
    }

    // The final item in the block can flow a value to here as well.
    receiveChildValue(curr->list.back(), curr);
  }
  void visitIf(If* curr) {
    // Each arm may flow out a value.
    receiveChildValue(curr->ifTrue, curr);
    receiveChildValue(curr->ifFalse, curr);
  }
  void visitLoop(Loop* curr) { receiveChildValue(curr->body, curr); }
  void visitBreak(Break* curr) {
    // Connect the value (if present) to the break target.
    handleBreakValue(curr);

    // The value may also flow through in a br_if (the type will indicate that,
    // which receiveChildValue will notice).
    receiveChildValue(curr->value, curr);
  }
  void visitSwitch(Switch* curr) { handleBreakValue(curr); }
  void visitLoad(Load* curr) {
    // We could infer the exact type here, but as no subtyping is possible, it
    // would have no benefit, so just add a generic root (which will be "Many").
    // See the comment on the ContentOracle class.
    addRoot(curr);
  }
  void visitStore(Store* curr) {}
  void visitAtomicRMW(AtomicRMW* curr) { addRoot(curr); }
  void visitAtomicCmpxchg(AtomicCmpxchg* curr) { addRoot(curr); }
  void visitAtomicWait(AtomicWait* curr) { addRoot(curr); }
  void visitAtomicNotify(AtomicNotify* curr) { addRoot(curr); }
  void visitAtomicFence(AtomicFence* curr) {}
  void visitPause(Pause* curr) {}
  void visitSIMDExtract(SIMDExtract* curr) { addRoot(curr); }
  void visitSIMDReplace(SIMDReplace* curr) { addRoot(curr); }
  void visitSIMDShuffle(SIMDShuffle* curr) { addRoot(curr); }
  void visitSIMDTernary(SIMDTernary* curr) { addRoot(curr); }
  void visitSIMDShift(SIMDShift* curr) { addRoot(curr); }
  void visitSIMDLoad(SIMDLoad* curr) { addRoot(curr); }
  void visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) { addRoot(curr); }
  void visitMemoryInit(MemoryInit* curr) {}
  void visitDataDrop(DataDrop* curr) {}
  void visitMemoryCopy(MemoryCopy* curr) {}
  void visitMemoryFill(MemoryFill* curr) {}
  void visitConst(Const* curr) {
    addRoot(curr, PossibleContents::literal(curr->value));
  }
  void visitUnary(Unary* curr) {
    // We could optimize cases like this using interpreter integration: if the
    // input is a Literal, we could interpret the Literal result. However, if
    // the input is a literal then the GUFA pass will emit a Const there, and
    // the Precompute pass can use that later to interpret a result. That is,
    // the input we need here, a constant, is already something GUFA can emit as
    // an output. As a result, integrating the interpreter here would perhaps
    // make compilation require fewer steps, but it wouldn't let us optimize
    // more than we could before.
    addRoot(curr);
  }
  void visitBinary(Binary* curr) { addRoot(curr); }
  void visitWideIntAddSub(WideIntAddSub* curr) { addRoot(curr); }
  void visitWideIntMul(WideIntMul* curr) { addRoot(curr); }
  void visitSelect(Select* curr) {
    receiveChildValue(curr->ifTrue, curr);
    receiveChildValue(curr->ifFalse, curr);
  }
  void visitDrop(Drop* curr) {}
  void visitMemorySize(MemorySize* curr) { addRoot(curr); }
  void visitMemoryGrow(MemoryGrow* curr) { addRoot(curr); }
  void visitRefNull(RefNull* curr) {
    addRoot(
      curr,
      PossibleContents::literal(Literal::makeNull(curr->type.getHeapType())));
  }
  void visitRefIsNull(RefIsNull* curr) {
    // TODO: Optimize when possible. For example, if we can infer an exact type
    //       here which allows us to know the result then we should do so. This
    //       is unlike the case in visitUnary, above: the information that lets
    //       us optimize *cannot* be written into Binaryen IR (unlike a Literal)
    //       so using it during this pass allows us to optimize new things.
    addRoot(curr);
  }
  void visitRefFunc(RefFunc* curr) {
    if (!getModule()->getFunction(curr->func)->imported()) {
      // This is not imported, so we know the exact function literal.
      addRoot(
        curr,
        PossibleContents::literal(Literal::makeFunc(curr->func, *getModule())));
    } else {
      // This is imported, so it is effectively a global.
      addRoot(curr,
              PossibleContents::global(
                curr->func, ExternalKind::Function, curr->type));
    }

    // The presence of a RefFunc indicates the function may be called
    // indirectly, so add the relevant connections for this particular function.
    // We do so here in the RefFunc so that we only do it for functions that
    // actually have a RefFunc.
    auto* func = getModule()->getFunction(curr->func);
    for (Index i = 0; i < func->getParams().size(); i++) {
      info.links.push_back({SignatureParamLocation{func->type.getHeapType(), i},
                            ParamLocation{func, i}});
    }
    for (Index i = 0; i < func->getResults().size(); i++) {
      info.links.push_back(
        {ResultLocation{func, i},
         SignatureResultLocation{func->type.getHeapType(), i}});
    }

    if (options.worldMode == WorldMode::Open) {
      info.calledFromOutside.insert(curr->func);
    }
  }
  void visitRefEq(RefEq* curr) { addRoot(curr); }
  void visitTableGet(TableGet* curr) {
    // TODO: be more precise
    addRoot(curr);
  }
  void visitTableSet(TableSet* curr) {}
  void visitTableSize(TableSize* curr) { addRoot(curr); }
  void visitTableGrow(TableGrow* curr) { addRoot(curr); }
  void visitTableFill(TableFill* curr) { addRoot(curr); }
  void visitTableCopy(TableCopy* curr) { addRoot(curr); }
  void visitTableInit(TableInit* curr) {}
  void visitElemDrop(ElemDrop* curr) {}

  void visitNop(Nop* curr) {}
  void visitUnreachable(Unreachable* curr) {}

#ifndef NDEBUG
  // For now we only handle pops in a catch body, see visitTry(). To check for
  // errors, use counter of the pops we handled and all the pops; those sums
  // must agree at the end, or else we've seen something we can't handle.
  Index totalPops = 0;
  Index handledPops = 0;
#endif

  void visitPop(Pop* curr) {
#ifndef NDEBUG
    totalPops++;
#endif
  }
  void visitRefI31(RefI31* curr) {
    // TODO: optimize like struct references
    addRoot(curr);
  }
  void visitI31Get(I31Get* curr) {
    // TODO: optimize like struct references
    addRoot(curr);
  }

  void visitRefCast(RefCast* curr) { receiveChildValue(curr->ref, curr); }
  void visitRefTest(RefTest* curr) { addRoot(curr); }
  void visitRefGetDesc(RefGetDesc* curr) {
    // Parallel to StructGet.
    if (!isRelevant(curr->ref)) {
      addRoot(curr);
      return;
    }
    addChildParentLink(curr->ref, curr);
  }
  void visitBrOn(BrOn* curr) {
    // TODO: optimize when possible
    handleBreakValue(curr);
    receiveChildValue(curr->ref, curr);
  }
  void visitRefAs(RefAs* curr) {
    if (curr->op == ExternConvertAny || curr->op == AnyConvertExtern) {
      // The external conversion ops emit something of a completely different
      // type, which we must mark as a root.
      addRoot(curr);
      return;
    }

    // All other RefAs operations flow values through while refining them (the
    // filterExpressionContents method will handle the refinement
    // automatically).
    receiveChildValue(curr->value, curr);
  }

  void visitLocalSet(LocalSet* curr) {
    if (!isRelevant(curr->value->type)) {
      return;
    }

    // Tees flow out the value (receiveChildValue will see if this is a tee
    // based on the type, automatically).
    receiveChildValue(curr->value, curr);

    // We handle connecting local.gets to local.sets below, in visitFunction.
  }
  void visitLocalGet(LocalGet* curr) {
    // We handle connecting local.gets to local.sets below, in visitFunction.
  }

  // Globals read and write from their location.
  void visitGlobalGet(GlobalGet* curr) {
    if (isRelevant(curr->type)) {
      // FIXME: we allow tuples in globals, so GlobalLocation needs a tupleIndex
      //        and we should loop here.
      assert(!curr->type.isTuple());
      info.links.push_back(
        {GlobalLocation{curr->name}, ExpressionLocation{curr, 0}});
    }
  }
  void visitGlobalSet(GlobalSet* curr) {
    if (isRelevant(curr->value->type)) {
      info.links.push_back(
        {ExpressionLocation{curr->value, 0}, GlobalLocation{curr->name}});
    }
  }

  // Iterates over a list of children and adds links to parameters and results
  // as needed. The param/result functions receive the index and create the
  // proper location for it.
  template<typename T>
  void handleCall(T* curr,
                  std::function<Location(Index)> makeParamLocation,
                  std::function<Location(Index)> makeResultLocation) {
    Index i = 0;
    for (auto* operand : curr->operands) {
      if (isRelevant(operand->type)) {
        info.links.push_back(
          {ExpressionLocation{operand, 0}, makeParamLocation(i)});
      }
      i++;
    }

    // Add results, if anything flows out.
    for (Index i = 0; i < curr->type.size(); i++) {
      if (isRelevant(curr->type[i])) {
        info.links.push_back(
          {makeResultLocation(i), ExpressionLocation{curr, i}});
      }
    }

    // If this is a return call then send the result to the function return as
    // well.
    if (curr->isReturn) {
      auto results = getFunction()->getResults();
      for (Index i = 0; i < results.size(); i++) {
        auto result = results[i];
        if (isRelevant(result)) {
          info.links.push_back(
            {makeResultLocation(i), ResultLocation{getFunction(), i}});
        }
      }
    }
  }

  // Calls send values to params in their possible targets, and receive
  // results.

  template<typename T> void handleDirectCall(T* curr, Name targetName) {
    auto* target = getModule()->getFunction(targetName);
    handleCall(
      curr,
      [&](Index i) {
        assert(i <= target->getParams().size());
        return ParamLocation{target, i};
      },
      [&](Index i) {
        assert(i <= target->getResults().size());
        return ResultLocation{target, i};
      });
  }
  template<typename T>
  void handleIndirectCall(T* curr, HeapType targetType, Exactness exact) {
    // If the heap type is not a signature, which is the case for a bottom type
    // (null) then nothing can be called.
    if (!targetType.isSignature()) {
      assert(targetType.isBottom());
      return;
    }
    // Connect us to the given type.
    auto sig = targetType.getSignature();
    handleCall(
      curr,
      [&](Index i) {
        assert(i <= sig.params.size());
        return SignatureParamLocation{targetType, i};
      },
      [&](Index i) {
        assert(i <= sig.results.size());
        return SignatureResultLocation{targetType, i};
      });
    // If the type is exact, we only need to read SignatureParamLocation /
    // SignatureResultLocation of this exact type, and we are done.
    if (exact == Exact) {
      return;
    }
    // Inexact type, so subtyping is relevant: add the relevant links.
    // TODO: SignatureParamLocation is handled below in an inefficient way, see
    //       there.
    // TODO: For CallRef, we could do something like readFromData() and use the
    //       flowing function reference's type, not the static type. We could
    //       even reuse ConeReadLocation if we generalized it to function types.
    for (Index i = 0; i < sig.results.size(); i++) {
      if (isRelevant(sig.results[i])) {
        shared.subTypes.iterSubTypes(
          targetType, [&](HeapType subType, Index depth) {
            info.links.push_back({SignatureResultLocation{subType, i},
                                  ExpressionLocation{curr, i}});
            if (curr->isReturn) {
              // Send the result to the function's results as well.
              info.links.push_back({SignatureResultLocation{subType, i},
                                    ResultLocation{getFunction(), i}});
            }
            return true;
          });
      }
    }
  }
  template<typename T> void handleIndirectCall(T* curr, Type targetType) {
    // If the type is unreachable, nothing can be called (and there is no heap
    // type to get).
    if (targetType != Type::unreachable) {
      handleIndirectCall(
        curr, targetType.getHeapType(), targetType.getExactness());
    }
  }

  void visitCall(Call* curr) {
    if (!Intrinsics(*getModule()).isCallWithoutEffects(curr)) {
      // This is just a normal call.
      handleDirectCall(curr, curr->target);
      return;
    }
    // A call-without-effects receives a function reference and calls it, the
    // same as a CallRef. When we have a flag for non-closed-world, we should
    // handle this automatically by the reference flowing out to an import,
    // which is what binaryen intrinsics look like. For now, to support use
    // cases of a closed world but that also use this intrinsic, handle the
    // intrinsic specifically here. (Without that, the closed world assumption
    // makes us ignore the function ref that flows to an import, so we are not
    // aware that it is actually called.)
    auto* target = curr->operands.back();

    // We must ignore the last element when handling the call - the target is
    // used to perform the call, and not sent during the call.
    curr->operands.pop_back();

    if (auto* refFunc = target->dynCast<RefFunc>()) {
      // We can see exactly where this goes.
      handleDirectCall(curr, refFunc->func);
    } else {
      // We can't see where this goes. We must be pessimistic and assume it
      // can call anything of the proper type, the same as a CallRef. (We could
      // look at the possible contents of |target| during the flow, but that
      // would require special logic like we have for StructGet etc., and the
      // intrinsics will be lowered away anyhow, so just running after that is
      // a workaround.)
      handleIndirectCall(curr, target->type);
    }

    // Restore the target.
    curr->operands.push_back(target);
  }
  void visitCallIndirect(CallIndirect* curr) {
    // TODO: optimize the call target like CallRef
    // CallIndirect only knows a heap type, so it is always inexact.
    handleIndirectCall(curr, curr->heapType, Inexact);

    // If this goes to a public table, then we must root the output, as the
    // table could contain anything at all, and calling functions there could
    // return anything at all.
    if (shared.publicTables.contains(curr->table)) {
      addRoot(curr);
    }
    // TODO: the table identity could also be used here in more ways
  }
  void visitCallRef(CallRef* curr) {
    handleIndirectCall(curr, curr->target->type);
  }

  Location getTypeLocation(Type type) {
    auto location = TypeLocation{type};
    addRoot(location, PossibleContents::fromType(type));
    return location;
  }

  Location getNullLocation(Type type) {
    auto location = NullLocation{type};
    addRoot(location, PossibleContents::literal(Literal::makeZero(type)));
    return location;
  }

  // Iterates over a list of children and adds links from them. The target of
  // those link is created using a function that is passed in, which receives
  // the index of the child.
  void linkChildList(ExpressionList& operands,
                     std::function<Location(Index)> makeTarget) {
    Index i = 0;
    for (auto* operand : operands) {
      // This helper is not used from places that allow a tuple (hence we can
      // hardcode the index 0 a few lines down).
      assert(!operand->type.isTuple());

      if (isRelevant(operand->type)) {
        info.links.push_back({ExpressionLocation{operand, 0}, makeTarget(i)});
      }
      i++;
    }
  }

  void visitStructNew(StructNew* curr) {
    if (curr->type == Type::unreachable) {
      return;
    }
    auto type = curr->type.getHeapType();
    if (curr->isWithDefault()) {
      // Link the default values to the struct's fields.
      auto& fields = type.getStruct().fields;
      for (Index i = 0; i < fields.size(); i++) {
        info.links.push_back(
          {getNullLocation(fields[i].type), DataLocation{type, i}});
      }
    } else {
      // Link the operands to the struct's fields.
      linkChildList(curr->operands,
                    [&](Index i) { return DataLocation{type, i}; });
    }
    if (curr->desc) {
      info.links.push_back({ExpressionLocation{curr->desc, 0},
                            DataLocation{type, DataLocation::DescriptorIndex}});
    }
    addRoot(curr, PossibleContents::exactType(curr->type));
  }
  void visitArrayNew(ArrayNew* curr) {
    if (curr->type == Type::unreachable) {
      return;
    }
    auto type = curr->type.getHeapType();
    if (curr->init) {
      info.links.push_back(
        {ExpressionLocation{curr->init, 0}, DataLocation{type, 0}});
    } else {
      info.links.push_back(
        {getNullLocation(type.getArray().element.type), DataLocation{type, 0}});
    }
    addRoot(curr, PossibleContents::exactType(curr->type));
  }
  void visitArrayNewData(ArrayNewData* curr) {
    if (curr->type == Type::unreachable) {
      return;
    }
    addRoot(curr, PossibleContents::exactType(curr->type));
    auto heapType = curr->type.getHeapType();
    Type elemType = heapType.getArray().element.type;
    addRoot(DataLocation{heapType, 0}, PossibleContents::fromType(elemType));
  }
  void visitArrayNewElem(ArrayNewElem* curr) {
    if (curr->type == Type::unreachable) {
      return;
    }
    addRoot(curr, PossibleContents::exactType(curr->type));
    auto heapType = curr->type.getHeapType();
    Type segType = getModule()->getElementSegment(curr->segment)->type;
    addRoot(DataLocation{heapType, 0}, PossibleContents::fromType(segType));
    return;
  }
  void visitArrayNewFixed(ArrayNewFixed* curr) {
    if (curr->type == Type::unreachable) {
      return;
    }
    if (!curr->values.empty()) {
      auto type = curr->type.getHeapType();
      linkChildList(curr->values, [&](Index i) {
        // The index i is ignored, as we do not track indexes in Arrays -
        // everything is modeled as if at index 0.
        return DataLocation{type, 0};
      });
    }
    addRoot(curr, PossibleContents::exactType(curr->type));
  }

  // Struct operations access the struct fields' locations.
  void visitStructGet(StructGet* curr) {
    if (!isRelevant(curr->ref)) {
      // If references are irrelevant then we will ignore them, and we won't
      // have information about this struct.get's reference, which means we
      // won't have information to compute relevant values for this struct.get.
      // Instead, just mark this as an unknown value (root).
      addRoot(curr);
      return;
    }
    // The struct.get will receive different values depending on the contents
    // in the reference, so mark us as the parent of the ref, and we will
    // handle all of this in a special way during the flow. Note that we do
    // not even create a DataLocation here; anything that we need will be
    // added during the flow.
    addChildParentLink(curr->ref, curr);
  }
  void visitStructSet(StructSet* curr) {
    if (curr->ref->type == Type::unreachable) {
      return;
    }
    // See comment on visitStructGet. Here we also connect the value.
    addChildParentLink(curr->ref, curr);
    addChildParentLink(curr->value, curr);
  }
  void visitStructRMW(StructRMW* curr) {
    if (curr->ref->type == Type::unreachable) {
      return;
    }
    addChildParentLink(curr->ref, curr);
    addChildParentLink(curr->value, curr);
    // TODO: Model the output
    addRoot(curr);
  }
  void visitStructCmpxchg(StructCmpxchg* curr) {
    if (curr->ref->type == Type::unreachable) {
      return;
    }
    addChildParentLink(curr->ref, curr);
    addChildParentLink(curr->expected, curr);
    addChildParentLink(curr->replacement, curr);
    // TODO: Model the output
    addRoot(curr);
  }
  void visitStructWait(StructWait* curr) { addRoot(curr); }
  void visitWaitqueueNew(WaitqueueNew* curr) { addRoot(curr); }
  void visitWaitqueueNotify(WaitqueueNotify* curr) { addRoot(curr); }
  void visitPublish(Publish* curr) { receiveChildValue(curr->ref, curr); }
  // Array operations access the array's location, parallel to how structs work.
  void visitArrayGet(ArrayGet* curr) {
    if (!isRelevant(curr->ref)) {
      addRoot(curr);
      return;
    }
    addChildParentLink(curr->ref, curr);
  }
  void visitArraySet(ArraySet* curr) {
    if (curr->ref->type == Type::unreachable) {
      return;
    }
    addChildParentLink(curr->ref, curr);
    addChildParentLink(curr->value, curr);
  }
  void visitArrayLoad(ArrayLoad* curr) {
    if (!isRelevant(curr->ref)) {
      addRoot(curr);
      return;
    }
    addChildParentLink(curr->ref, curr);
  }
  void visitArrayStore(ArrayStore* curr) {
    if (curr->ref->type == Type::unreachable) {
      return;
    }
    addChildParentLink(curr->ref, curr);
    addChildParentLink(curr->value, curr);
  }

  void visitArrayLen(ArrayLen* curr) {
    // TODO: optimize when possible (perhaps we can infer a Literal for the
    //       length)
    addRoot(curr);
  }
  void visitArrayCopy(ArrayCopy* curr) {
    if (curr->type == Type::unreachable) {
      return;
    }
    // Our flow handling of GC data is not simple: we have special code for each
    // read and write instruction. Therefore, to avoid adding special code for
    // ArrayCopy, model it as a combination of an ArrayRead and ArrayWrite, by
    // just emitting fake expressions for those. The fake expressions are not
    // part of the main IR, which is potentially confusing during debugging,
    // however, which is a downside.
    Builder builder(*getModule());
    auto* get = builder.makeArrayGet(
      curr->srcRef, curr->srcIndex, MemoryOrder::Unordered, curr->srcRef->type);
    visitArrayGet(get);
    auto* set = builder.makeArraySet(
      curr->destRef, curr->destIndex, get, MemoryOrder::Unordered);
    visitArraySet(set);
  }
  void visitArrayFill(ArrayFill* curr) {
    if (curr->type == Type::unreachable) {
      return;
    }
    // See ArrayCopy, above.
    Builder builder(*getModule());
    auto* set = builder.makeArraySet(
      curr->ref, curr->index, curr->value, MemoryOrder::Unordered);
    visitArraySet(set);
  }

  void handleArrayWrite(Expression* ref) {
    // Check for both unreachability and a bottom type. In either case we have
    // no work to do, and would error on an assertion below in finding the array
    // type.
    auto field = GCTypeUtils::getField(ref->type);
    if (!field) {
      return;
    }
    // See ArrayCopy, above. Here an additional complexity is that we need to
    // model the read from the segment. As in TableGet, for now we just assume
    // any value is possible there (a root in the graph), which we set up
    // manually here as a fake unknown value, using a fake local.get that we
    // root.
    // TODO: be more precise about what is in the table
    auto valueType = field->type;
    Builder builder(*getModule());
    auto* get = builder.makeLocalGet(-1, valueType);
    addRoot(get);
    // The index does not matter, as we do not track array indexes yet TODO
    Expression* index = builder.makeNop();
    auto* set = builder.makeArraySet(ref, index, get, MemoryOrder::Unordered);
    visitArraySet(set);
  }

  void visitArrayInitData(ArrayInitData* curr) { handleArrayWrite(curr->ref); }
  void visitArrayInitElem(ArrayInitElem* curr) { handleArrayWrite(curr->ref); }
  void visitArrayRMW(ArrayRMW* curr) {
    if (curr->ref->type == Type::unreachable) {
      return;
    }
    addChildParentLink(curr->ref, curr);
    addChildParentLink(curr->value, curr);
    // TODO: Model the output
    addRoot(curr);
  }
  void visitArrayCmpxchg(ArrayCmpxchg* curr) {
    if (curr->ref->type == Type::unreachable) {
      return;
    }
    addChildParentLink(curr->ref, curr);
    addChildParentLink(curr->expected, curr);
    addChildParentLink(curr->replacement, curr);
    // TODO: Model the output
    addRoot(curr);
  }
  void visitStringNew(StringNew* curr) {
    if (curr->type == Type::unreachable) {
      return;
    }
    addRoot(curr, PossibleContents::exactType(curr->type));
  }
  void visitStringConst(StringConst* curr) {
    addRoot(curr, PossibleContents::literal(Literal(curr->string.view())));
  }
  void visitStringMeasure(StringMeasure* curr) {
    // TODO: optimize when possible
    addRoot(curr);
  }
  void visitStringEncode(StringEncode* curr) {
    // TODO: optimize when possible
    handleArrayWrite(curr->array);
    addRoot(curr);
  }
  void visitStringConcat(StringConcat* curr) {
    // TODO: optimize when possible
    addRoot(curr);
  }
  void visitStringEq(StringEq* curr) {
    // TODO: optimize when possible
    addRoot(curr);
  }
  void visitStringTest(StringTest* curr) {
    // TODO: optimize when possible
    addRoot(curr);
  }
  void visitStringWTF16Get(StringWTF16Get* curr) {
    // TODO: optimize when possible
    addRoot(curr);
  }
  void visitStringSliceWTF(StringSliceWTF* curr) {
    // TODO: optimize when possible
    addRoot(curr);
  }

  // TODO: Model which throws can go to which catches. For now, anything thrown
  //       is sent to the location of that tag, and any catch of that tag can
  //       read them.
  void visitTry(Try* curr) {
    receiveChildValue(curr->body, curr);
    for (auto* catchBody : curr->catchBodies) {
      receiveChildValue(catchBody, curr);
    }

    auto numTags = curr->catchTags.size();
    for (Index tagIndex = 0; tagIndex < numTags; tagIndex++) {
      auto tag = curr->catchTags[tagIndex];
      auto* body = curr->catchBodies[tagIndex];

      auto params = getModule()->getTag(tag)->params();
      if (params.size() == 0) {
        continue;
      }

      // Find the pop of the tag's contents. The body must start with such a
      // pop, which might be of a tuple.
      auto* pop = EHUtils::findPop(body);
      // There must be a pop since we checked earlier if it was an empty tag,
      // and would not reach here.
      assert(pop);
      assert(pop->type.size() == params.size());
      for (Index i = 0; i < params.size(); i++) {
        if (isRelevant(params[i])) {
          info.links.push_back(
            {TagLocation{tag, i}, ExpressionLocation{pop, i}});
        }
      }

#ifndef NDEBUG
      // This pop was in the position we can handle, note that (see visitPop
      // for details).
      handledPops++;
#endif
    }
  }
  void visitTryTable(TryTable* curr) {
    receiveChildValue(curr->body, curr);

    // Connect caught tags with their branch targets, and materialize non-null
    // exnref values.
    auto numTags = curr->catchTags.size();
    for (Index tagIndex = 0; tagIndex < numTags; tagIndex++) {
      auto tag = curr->catchTags[tagIndex];
      auto target = curr->catchDests[tagIndex];

      Index exnrefIndex = 0;
      if (tag.is()) {
        auto params = getModule()->getTag(tag)->params();

        for (Index i = 0; i < params.size(); i++) {
          if (isRelevant(params[i])) {
            info.links.push_back(
              {TagLocation{tag, i}, getBreakTargetLocation(target, i)});
          }
        }

        exnrefIndex = params.size();
      }

      if (curr->catchRefs[tagIndex]) {
        auto location = getTypeLocation(Type(HeapType::exn, NonNullable));
        info.links.push_back(
          {location, getBreakTargetLocation(target, exnrefIndex)});
      }
    }
  }
  template<typename T> void handleThrow(T* curr) {
    auto& operands = curr->operands;
    if (!isRelevant(operands)) {
      return;
    }

    auto tag = curr->tag;
    for (Index i = 0; i < curr->operands.size(); i++) {
      info.links.push_back(
        {ExpressionLocation{operands[i], 0}, TagLocation{tag, i}});
    }
  }
  void visitThrow(Throw* curr) { handleThrow(curr); }
  void visitRethrow(Rethrow* curr) {}
  void visitThrowRef(ThrowRef* curr) {}

  void visitTupleMake(TupleMake* curr) {
    if (isRelevant(curr->type)) {
      for (Index i = 0; i < curr->operands.size(); i++) {
        info.links.push_back({ExpressionLocation{curr->operands[i], 0},
                              ExpressionLocation{curr, i}});
      }
    }
  }
  void visitTupleExtract(TupleExtract* curr) {
    if (isRelevant(curr->type)) {
      info.links.push_back({ExpressionLocation{curr->tuple, curr->index},
                            ExpressionLocation{curr, 0}});
    }
  }

  // Adds a result to the current function, such as from a return or the value
  // that flows out.
  void addResult(Expression* value) {
    if (value && isRelevant(value->type)) {
      for (Index i = 0; i < value->type.size(); i++) {
        info.links.push_back(
          {ExpressionLocation{value, i}, ResultLocation{getFunction(), i}});
      }
    }
  }

  void visitReturn(Return* curr) { addResult(curr->value); }

  void visitContNew(ContNew* curr) {
    // TODO: optimize when possible
    addRoot(curr);

    // The function reference that is passed in here will be called, just as if
    // we were a call_ref, except at a potentially later time.
    if (!curr->func->type.isRef()) {
      return;
    }
    auto targetType = curr->func->type.getHeapType();
    if (!targetType.isSignature()) {
      assert(targetType.isBottom());
      return;
    }
    // Unlike call_ref, we do not have the call operands here. Assume any
    // value for the signature for now, but we could track them from cont.bind
    // and resume TODO (it is simpler for now to do it here, where we have the
    // original funcref that is called, before cont.bind alters the signature)
    Index i = 0;
    for (auto param : targetType.getSignature().params) {
      if (isRelevant(param)) {
        // Send anything of the proper type to all functions of this signature,
        // since they are all callable.
        info.links.push_back(
          {getTypeLocation(param), SignatureParamLocation{targetType, i}});
      }
      i++;
    }
  }
  void visitContBind(ContBind* curr) {
    // TODO: optimize when possible
    addRoot(curr);
  }
  void visitSuspend(Suspend* curr) {
    // TODO: optimize when possible
    addRoot(curr);

    // The given values are written to the tag, just the same as a throw.
    handleThrow(curr);
  }

  template<typename T> void handleResume(T* curr) {
    // TODO: optimize when possible
    addRoot(curr);

    // Connect handled tags with their branch targets, and materialize non-null
    // continuation values.
    auto numTags = curr->handlerTags.size();
    for (Index tagIndex = 0; tagIndex < numTags; tagIndex++) {
      auto target = curr->handlerBlocks[tagIndex];
      if (!target) {
        // A switch handler does not branch to a target block.
        continue;
      }
      auto tag = curr->handlerTags[tagIndex];
      auto params = getModule()->getTag(tag)->params();

      // Add the values from the tag.
      for (Index i = 0; i < params.size(); i++) {
        if (isRelevant(params[i])) {
          info.links.push_back(
            {TagLocation{tag, i}, getBreakTargetLocation(target, i)});
        }
      }

      // Add the continuation. Its type is determined by the block we break to,
      // as the last result.
      auto targetType = findBreakTarget(target)->type;
      assert(targetType.size() >= 1);
      auto contType = targetType[targetType.size() - 1];
      auto location = getTypeLocation(contType);
      info.links.push_back(
        {location, getBreakTargetLocation(target, params.size())});
    }
  }

  void visitResume(Resume* curr) { handleResume(curr); }
  void visitResumeThrow(ResumeThrow* curr) {
    handleResume(curr);
    handleThrow(curr);
  }
  void visitStackSwitch(StackSwitch* curr) {
    // TODO: optimize when possible
    addRoot(curr);
  }

  void visitFunction(Function* func) {
    // Functions with a result can flow a value out from their body.
    addResult(func->body);

    // See visitPop().
    assert(handledPops == totalPops);

    // Handle local.get/sets: each set must write to the proper gets.
    //
    // Note that we do not use LocalLocation because LocalGraph gives us more
    // precise information: we generate direct links from sets to relevant gets
    // rather than consider each local index a single location, which
    // LocalLocation does. (LocalLocation is useful in cases where we do need a
    // single location, such as when we consider what type to give the local;
    // the type must be the same for all gets of that local.)
    LocalGraph localGraph(func, getModule());

    for (auto& [curr, _] : localGraph.locations) {
      auto* get = curr->dynCast<LocalGet>();
      if (!get) {
        continue;
      }

      auto index = get->index;
      auto type = func->getLocalType(index);
      if (!isRelevant(type)) {
        continue;
      }

      // Each get reads from its relevant sets.
      for (auto* set : localGraph.getSets(get)) {
        for (Index i = 0; i < type.size(); i++) {
          Location source;
          if (set) {
            // This is a normal local.set.
            source = ExpressionLocation{set->value, i};
          } else if (getFunction()->isParam(index)) {
            // This is a parameter.
            source = ParamLocation{getFunction(), index};
          } else {
            // This is the default value from the function entry, a null.
            source = getNullLocation(type[i]);
          }
          info.links.push_back({source, ExpressionLocation{get, i}});
        }
      }
    }
  }

  // Helpers

  // Returns the location of a break target by the name (e.g. returns the
  // location of a block, if the name is the name of a block). Also receives the
  // index in a tuple, if this is part of a tuple value.
  Location getBreakTargetLocation(Name target, Index i) {
    return ExpressionLocation{findBreakTarget(target), i};
  }

  // Handles the value sent in a break instruction. Does not handle anything
  // else like the condition etc.
  void handleBreakValue(Expression* curr) {
    BranchUtils::operateOnScopeNameUsesAndSentValues(
      curr, [&](Name target, Expression* value) {
        if (value && isRelevant(value->type)) {
          for (Index i = 0; i < value->type.size(); i++) {
            // Breaks send the contents of the break value to the branch target
            // that the break goes to.
            info.links.push_back({ExpressionLocation{value, i},
                                  getBreakTargetLocation(target, i)});
          }
        }
      });
  }

  // Connect a child's value to the parent, that is, all content in the child is
  // now considered possible in the parent as well.
  void receiveChildValue(Expression* child, Expression* parent) {
    if (isRelevant(parent) && isRelevant(child)) {
      // The tuple sizes must match (or, if not a tuple, the size should be 1 in
      // both cases).
      assert(child->type.size() == parent->type.size());
      for (Index i = 0; i < child->type.size(); i++) {
        info.links.push_back(
          {ExpressionLocation{child, i}, ExpressionLocation{parent, i}});
      }
    }
  }

  // See the comment on CollectedFuncInfo::childParents.
  void addChildParentLink(Expression* child, Expression* parent) {
    if (isRelevant(child->type)) {
      info.childParents[child] = parent;
    }
  }

  // Adds a root, if the expression is relevant. If the value is not specified,
  // mark the root as containing Many (which is the common case, so avoid
  // verbose code).
  void addRoot(Expression* curr,
               PossibleContents contents = PossibleContents::many()) {
    // TODO Use a cone type here when relevant
    if (isRelevant(curr)) {
      if (contents.isMany()) {
        contents = PossibleContents::fromType(curr->type);
      }

      if (!curr->type.isTuple()) {
        addRoot(ExpressionLocation{curr, 0}, contents);
      } else {
        // For a tuple, we create a root for each index.
        for (Index i = 0; i < curr->type.size(); i++) {
          addRoot(ExpressionLocation{curr, i}, contents.getTupleItem(i));
        }
      }
    }
  }

  // As above, but given an arbitrary location and not just an expression.
  void addRoot(Location loc,
               PossibleContents contents = PossibleContents::many()) {
    info.roots.emplace_back(loc, contents);
  }
};

// TrapsNeverHappen Oracle. This makes inferences *backwards* from traps that we
// know will not happen due to the TNH assumption. For example,
//
//  (local.get $a)
//  (ref.cast $B (local.get $a))
//
// The cast happens right after the first local.get, and we assume it does not
// fail, so the local must contain a B, even though the IR only has A.
//
// This analysis complements ContentOracle, which uses this analysis internally.
// ContentOracle does a forward flow analysis (as content moves from place to
// place) which increases from "nothing", while this does a backwards analysis
// that decreases from "everything" (or rather, from the type declared in the
// IR), so the two cannot be done at once.
//
// TODO: We could cycle between this and ContentOracle for repeated
//       improvements.
// TODO: This pass itself could benefit from internal cycles.
//
// This analysis mainly focuses on information across calls, as simple backwards
// inference is done in OptimizeCasts. Note that it is not needed if a call is
// inlined, obviously, and so it mostly helps cases like functions too large to
// inline, or when optimizing for size, or with indirect calls.
//
// We track cast parameters by mapping an index to the type it is definitely
// cast to if the function is entered. From that information we can infer things
// about the values being sent to the function (which we can assume must have
// the right type so that the casts do not trap).
using CastParams = std::unordered_map<Index, Type>;

// The information we collect and utilize as we operate in parallel in each
// function.
struct TNHInfo {
  CastParams castParams;

  // TODO: Returns as well: when we see (ref.cast (call $foo)) in all callers
  //       then we can refine inside $foo (in closed world).

  // We gather calls in parallel in order to process them later.
  std::vector<Call*> calls;
  std::vector<CallRef*> callRefs;

  // Note if a function body definitely traps.
  bool traps = false;

  // We gather inferences in parallel and combine them at the end.
  std::unordered_map<Expression*, PossibleContents> inferences;
};

class TNHOracle : public ModuleUtils::ParallelFunctionAnalysis<TNHInfo> {
  const PassOptions& options;

public:
  using Parent = ModuleUtils::ParallelFunctionAnalysis<TNHInfo>;
  TNHOracle(Module& wasm, const PassOptions& options)
    : Parent(wasm,
             [this, &options](Function* func, TNHInfo& info) {
               scan(func, info, options);
             }),
      options(options) {

    // After the scanning phase that we run in the constructor, continue to the
    // second phase of analysis: inference.
    infer();
  }

  // Get the type we inferred was possible at a location.
  PossibleContents getContents(Expression* curr) {
    auto naiveContents = PossibleContents::coneType(curr->type);

    // If we inferred nothing, use the naive type.
    auto iter = inferences.find(curr);
    if (iter == inferences.end()) {
      return naiveContents;
    }

    auto& contents = iter->second;
    // We only store useful contents that improve on the naive estimate that
    // uses the type in the IR.
    assert(contents != naiveContents);
    return contents;
  }

private:
  // Maps expressions to the content we inferred there. If an expression is not
  // here then expression->type (the type in Binaryen IR) is all we have.
  std::unordered_map<Expression*, PossibleContents> inferences;

  // Phase 1: Scan to find cast parameters and calls. This operates on a single
  // function, and is called in parallel.
  void scan(Function* func, TNHInfo& info, const PassOptions& options);

  // Phase 2: Infer contents based on what we scanned.
  void infer();

  // Optimize one specific call (or call_ref).
  void optimizeCallCasts(Expression* call,
                         const ExpressionList& operands,
                         const CastParams& targetCastParams,
                         const analysis::CFGBlockIndexes& blockIndexes,
                         TNHInfo& info);
};

void TNHOracle::scan(Function* func,
                     TNHInfo& info,
                     const PassOptions& options) {
  if (func->imported()) {
    return;
  }

  // Gather parameters that are definitely cast in the function entry.
  struct EntryScanner : public LinearExecutionWalker<EntryScanner> {
    Module& wasm;
    const PassOptions& options;
    TNHInfo& info;

    EntryScanner(Module& wasm, const PassOptions& options, TNHInfo& info)
      : wasm(wasm), options(options), info(info) {}

    // Note while we are still in the entry (first) block.
    bool inEntryBlock = true;

    static void doNoteNonLinear(EntryScanner* self, Expression** currp) {
      // This is the end of the first basic block.
      self->inEntryBlock = false;
    }

    // We note params that are written to, as local changes prevent us from
    // inferences:
    //
    //  (func $foo (param $x)
    //    (local.set $x ..)
    //    (ref.cast (local.get $x)) ;; this is no longer casting the actual
    //                              ;; parameter
    //
    std::unordered_set<Index> writtenParams;

    void visitLocalSet(LocalSet* curr) {
      if (getFunction()->isParam(curr->index)) {
        writtenParams.insert(curr->index);
      }
    }

    void visitCall(Call* curr) { info.calls.push_back(curr); }

    void visitCallRef(CallRef* curr) {
      // We can only optimize call_ref in closed world, as otherwise the
      // call can go somewhere we can't see.
      if (options.worldMode == WorldMode::Closed) {
        info.callRefs.push_back(curr);
      }
    }

    void visitRefAs(RefAs* curr) {
      if (curr->op == RefAsNonNull) {
        noteCast(curr->value, curr->type);
      }
    }
    void visitRefCast(RefCast* curr) { noteCast(curr->ref, curr->type); }

    // Note a cast of an expression to a particular type.
    void noteCast(Expression* expr, Type type) {
      if (!inEntryBlock) {
        return;
      }

      auto* fallthrough = Properties::getFallthrough(expr, options, wasm);
      if (auto* get = fallthrough->dynCast<LocalGet>()) {
        // To optimize, this needs to be an unmodified param, and of a useful
        // type.
        //
        // Note that if we see more than one cast we keep the first one. This is
        // not important in optimized code, as the most refined cast would be
        // the only one to exist there, so it's ok to keep things simple here.
        if (getFunction()->isParam(get->index) && type != get->type &&
            !info.castParams.contains(get->index) &&
            !writtenParams.contains(get->index)) {
          info.castParams[get->index] = type;
        }
      }
    }

    // Operations that trap on null are equivalent to casts to non-null, in that
    // they imply that their input is non-null if traps never happen.
    //
    // We only look at them if the input is actually nullable, since if they
    // are non-nullable then we can add no information. (This is equivalent
    // to the handling of RefAsNonNull above, in the sense that in optimized
    // code the RefAs will not appear if the input is already non-nullable).
    // This function is called with the reference that will be trapped on,
    // if it is null.
    void notePossibleTrap(Expression* expr) {
      if (!expr->type.isRef() || expr->type.isNonNullable()) {
        return;
      }
      noteCast(expr, Type(expr->type.getHeapType(), NonNullable));
    }

    void visitStructGet(StructGet* curr) { notePossibleTrap(curr->ref); }
    void visitStructSet(StructSet* curr) { notePossibleTrap(curr->ref); }
    void visitStructRMW(StructRMW* curr) { notePossibleTrap(curr->ref); }
    void visitStructCmpxchg(StructCmpxchg* curr) {
      notePossibleTrap(curr->ref);
    }
    // TODO: visitStructWait
    void visitArrayGet(ArrayGet* curr) { notePossibleTrap(curr->ref); }
    void visitArraySet(ArraySet* curr) { notePossibleTrap(curr->ref); }
    void visitArrayLoad(ArrayLoad* curr) { notePossibleTrap(curr->ref); }
    void visitArrayStore(ArrayStore* curr) { notePossibleTrap(curr->ref); }
    void visitArrayLen(ArrayLen* curr) { notePossibleTrap(curr->ref); }
    void visitArrayCopy(ArrayCopy* curr) {
      notePossibleTrap(curr->srcRef);
      notePossibleTrap(curr->destRef);
    }
    void visitArrayFill(ArrayFill* curr) { notePossibleTrap(curr->ref); }
    void visitArrayInitData(ArrayInitData* curr) {
      notePossibleTrap(curr->ref);
    }
    void visitArrayInitElem(ArrayInitElem* curr) {
      notePossibleTrap(curr->ref);
    }
    void visitArrayRMW(ArrayRMW* curr) { notePossibleTrap(curr->ref); }
    void visitArrayCmpxchg(ArrayCmpxchg* curr) { notePossibleTrap(curr->ref); }

    void visitFunction(Function* curr) {
      // In optimized TNH code, a function that always traps will be turned
      // into a singleton unreachable instruction, so it is enough to check
      // for that.
      if (curr->body->is<Unreachable>()) {
        info.traps = true;
      }
    }
  } scanner(wasm, options, info);
  scanner.walkFunction(func);
}

void TNHOracle::infer() {
  // Phase 2: Inside each function, optimize calls based on the cast params of
  // the called function (which we noted during phase 1).
  //
  // Specifically, each time we call a target that will cast a param, we can
  // infer that the param must have that type (or else we'd trap, but we are
  // assuming traps never happen).
  //
  // While doing so we must be careful of control flow transfers right before
  // the call:
  //
  //  (call $target
  //    (A)
  //    (br_if ..)
  //    (B)
  //  )
  //
  // If we branch in the br_if then we might execute A and then something else
  // entirely, and not reach B or the call. In that case we can't infer anything
  // about A (perhaps, for example, we branch away exactly when A would fail the
  // cast). Therefore in the optimization below we only optimize code that, if
  // reached, will definitely reach the call, like B.
  //
  // TODO: Some control flow transfers are ok, so long as we must reach the
  //       call, like if we replace the br_if with an if with two arms (and no
  //       branches in either).
  // TODO: We can also infer backwards past basic blocks from casts, even
  //       without calls. Any cast tells us something about the uses of that
  //       value that must reach the cast.
  // TODO: We can do a whole-program flow of this information.

  // For call_ref, we need to know which functions belong to each type. Gather
  // that first. This map will map each heap type to each function that is of
  // that type or a subtype, i.e., might be called when that type is seen in a
  // call_ref target.
  std::unordered_map<HeapType, std::vector<Function*>> typeFunctions;
  if (options.worldMode == WorldMode::Closed) {
    for (auto& func : wasm.functions) {
      auto type = func->type;
      auto& info = map[wasm.getFunction(func->name)];
      if (info.traps) {
        // This function definitely traps, so we can assume it is never called,
        // and don't need to even bother putting it in |typeFunctions|.
        continue;
      }
      while (1) {
        typeFunctions[type.getHeapType()].push_back(func.get());
        if (auto super = type.getHeapType().getDeclaredSuperType()) {
          type = type.with(*super);
        } else {
          break;
        }
      }
    }
  }

  doAnalysis([&](Function* func, TNHInfo& info) {
    // We will need some CFG information below. Computing this is expensive, so
    // only do it if we find optimization opportunities.
    std::optional<analysis::CFGBlockIndexes> blockIndexes;

    auto ensureCFG = [&]() {
      if (!blockIndexes) {
        auto cfg = analysis::CFG::fromFunction(func, &wasm);
        blockIndexes = analysis::CFGBlockIndexes(cfg);
      }
    };

    for (auto* call : info.calls) {
      auto& targetInfo = map[wasm.getFunction(call->target)];

      auto& targetCastParams = targetInfo.castParams;
      if (targetCastParams.empty()) {
        continue;
      }

      // This looks promising, create the CFG if we haven't already, and
      // optimize.
      ensureCFG();
      optimizeCallCasts(
        call, call->operands, targetCastParams, *blockIndexes, info);

      // Note that we don't need to do anything for targetInfo.traps for a
      // direct call: the inliner will inline the singleton unreachable in the
      // target function anyhow.
    }

    for (auto* call : info.callRefs) {
      auto targetType = call->target->type;
      if (!targetType.isRef()) {
        // This is unreachable or null, and other passes will optimize that.
        continue;
      }

      // We should only get here in a closed world, in which we know which
      // functions might be called (the scan phase only notes callRefs if we are
      // in fact in a closed world).
      assert(options.worldMode == WorldMode::Closed);

      auto iter = typeFunctions.find(targetType.getHeapType());
      if (iter == typeFunctions.end()) {
        // No function exists of this type, so the call_ref will trap. We can
        // mark the target as empty, which has the identical effect.
        info.inferences[call->target] = PossibleContents::none();
        continue;
      }

      // Go through the targets and ignore any that will trap. That will leave
      // us with the actually possible targets.
      //
      // Note that we did not even add functions that certainly trap to
      // |typeFunctions| at all, so those are already excluded.
      const auto& targets = iter->second;
      std::vector<Function*> possibleTargets;
      for (Function* target : targets) {
        auto& targetInfo = map[target];

        // If any of our operands will fail a cast, then we will trap.
        bool traps = false;
        for (auto& [castIndex, castType] : targetInfo.castParams) {
          auto operandType = call->operands[castIndex]->type;
          auto result = GCTypeUtils::evaluateCastCheck(operandType, castType);
          if (result == GCTypeUtils::Failure) {
            traps = true;
            break;
          }
        }
        if (!traps) {
          possibleTargets.push_back(target);
        }
      }

      if (possibleTargets.empty()) {
        // No target is possible.
        info.inferences[call->target] = PossibleContents::none();
        continue;
      }

      if (possibleTargets.size() == 1) {
        // There is exactly one possible call target, which means we can
        // actually infer what the call_ref is calling. Add that as an
        // inference.
        // TODO: We could also optimizeCallCasts() here, but it is low priority
        //       as other opts will make this call direct later, after which a
        //       lot of other optimizations become possible anyhow.
        auto target = possibleTargets[0]->name;
        info.inferences[call->target] =
          PossibleContents::literal(Literal::makeFunc(target, wasm));
        continue;
      }

      // More than one target exists: apply the intersection of their
      // constraints. That is, if they all cast the k-th parameter to type T (or
      // more) than we can apply that here.
      auto numParams = call->operands.size();
      std::vector<Type> sharedCastParamsVec(numParams, Type::unreachable);
      for (auto* target : possibleTargets) {
        auto& targetInfo = map[target];
        auto& targetCastParams = targetInfo.castParams;
        for (Index i = 0; i < numParams; i++) {
          auto iter = targetCastParams.find(i);
          if (iter == targetCastParams.end()) {
            // If the target does not cast, we cannot do anything with this
            // parameter; mark it as unoptimizable with an impossible type.
            sharedCastParamsVec[i] = Type::none;
            continue;
          }

          // This function casts this param. Combine this with existing info.
          auto castType = iter->second;
          sharedCastParamsVec[i] =
            Type::getLeastUpperBound(sharedCastParamsVec[i], castType);
        }
      }

      // Build a map of the interesting cast params we found, and if there are
      // any, optimize using them.
      CastParams sharedCastParams;
      for (Index i = 0; i < numParams; i++) {
        auto type = sharedCastParamsVec[i];
        if (type != Type::none) {
          sharedCastParams[i] = type;
        }
      }
      if (!sharedCastParams.empty()) {
        ensureCFG();
        optimizeCallCasts(
          call, call->operands, sharedCastParams, *blockIndexes, info);
      }
    }
  });

  // Combine all of our inferences from the parallel phase above us into the
  // final list of inferences.
  for (auto& [_, info] : map) {
    for (auto& [expr, contents] : info.inferences) {
      inferences[expr] = contents;
    }
  }
}

void TNHOracle::optimizeCallCasts(Expression* call,
                                  const ExpressionList& operands,
                                  const CastParams& targetCastParams,
                                  const analysis::CFGBlockIndexes& blockIndexes,
                                  TNHInfo& info) {
  // Optimize in the same basic block as the call: all instructions still in
  // that block will definitely execute if the call is reached. We will do that
  // by going backwards through the call's operands and fallthrough values, and
  // optimizing while we are still in the same basic block.
  auto callBlockIndex = blockIndexes.get(call);

  // Operands must exist since there is a cast param, so a param exists.
  assert(operands.size() > 0);
  for (int i = int(operands.size() - 1); i >= 0; i--) {
    auto* operand = operands[i];

    if (blockIndexes.get(operand) != callBlockIndex) {
      // Control flow might transfer; stop.
      break;
    }

    auto iter = targetCastParams.find(i);
    if (iter == targetCastParams.end()) {
      // This param is not cast, so skip it.
      continue;
    }

    // If the call executes then this parameter is definitely reached (since it
    // is in the same basic block), and we know that it will be cast to a more
    // refined type.
    auto castType = iter->second;

    // Apply what we found to the operand and also to its fallthrough
    // values.
    //
    // At the loop entry |curr| has been checked for a possible control flow
    // transfer (and that problem ruled out).
    auto* curr = operand;
    while (1) {
      // Note the type if it is useful.
      if (castType != curr->type) {
        // There are two constraints on this location: any value there must
        // be of the declared type (curr->type) and also the cast type, so
        // we know only their intersection can appear here.
        auto declared = PossibleContents::coneType(curr->type);
        auto intersection = PossibleContents::coneType(castType);
        intersection.intersect(declared);
        if (intersection.isConeType()) {
          auto intersectionType = intersection.getType();
          if (intersectionType != curr->type) {
            // We inferred a more refined type.
            info.inferences[curr] = intersection;
          }
        } else {
          // Otherwise, the intersection can be a null (if the heap types are
          // incompatible, but a null is allowed), or empty. We can apply
          // either.
          assert(intersection.isNull() || intersection.isNone());
          info.inferences[curr] = intersection;
        }
      }

      auto* next = Properties::getImmediateFallthrough(curr, options, wasm);
      if (next == curr) {
        // No fallthrough, we're done with this param.
        break;
      }

      // There is a fallthrough. Check for a control flow transfer.
      if (blockIndexes.get(next) != callBlockIndex) {
        // Control flow might transfer; stop. We also cannot look at any further
        // operands (if a child of this operand is in another basic block from
        // the call, so are previous operands), so return from the entire
        // function.
        return;
      }

      // Continue to the fallthrough.
      curr = next;
    }
  }
}

// Main logic for building data for the flow analysis and then performing that
// analysis.
struct Flower {
  Module& wasm;
  const PassOptions& options;

  Flower(Module& wasm, const PassOptions& options);

  // Each LocationIndex will have one LocationInfo that contains the relevant
  // information we need for each location.
  struct LocationInfo {
    // The location at this index.
    Location location;

    // The possible contents in that location.
    PossibleContents contents;

    // A list of the target locations to which this location sends content.
    // TODO: benchmark SmallVector<1> here, as commonly there may be a single
    //       target (an expression has one parent)
    std::vector<LocationIndex> targets;

    LocationInfo(Location location) : location(location) {}
  };

  // Maps location indexes to the info stored there, as just described above.
  std::vector<LocationInfo> locations;

  // Reverse mapping of locations to their indexes.
  std::unordered_map<Location, LocationIndex> locationIndexes;

  const Location& getLocation(LocationIndex index) {
    assert(index < locations.size());
    return locations[index].location;
  }

  PossibleContents& getContents(LocationIndex index) {
    assert(index < locations.size());
    return locations[index].contents;
  }

  // Check what we know about the type of an expression, using static
  // information from a TrapsNeverHappen oracle (see TNHOracle), if we have one.
  PossibleContents getTNHContents(Expression* curr) {
    if (!tnhOracle) {
      // No oracle; just use the type in the IR.
      return PossibleContents::coneType(curr->type);
    }
    return tnhOracle->getContents(curr);
  }

private:
  std::unique_ptr<TNHOracle> tnhOracle;

  std::vector<LocationIndex>& getTargets(LocationIndex index) {
    assert(index < locations.size());
    return locations[index].targets;
  }

  // Convert the data into the efficient LocationIndex form we will use during
  // the flow analysis. This method returns the index of a location, allocating
  // one if this is the first time we see it.
  LocationIndex getIndex(const Location& location) {
    auto iter = locationIndexes.find(location);
    if (iter != locationIndexes.end()) {
      return iter->second;
    }

    // Allocate a new index here.
    size_t index = locations.size();
#if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
    std::cout << "  new index " << index << " for ";
    dump(location);
#endif
    if (index >= std::numeric_limits<LocationIndex>::max()) {
      // 32 bits should be enough since each location takes at least one byte
      // in the binary, and we don't have 4GB wasm binaries yet... do we?
      Fatal() << "Too many locations for 32 bits";
    }
    locations.emplace_back(location);
    locationIndexes[location] = index;

    return index;
  }

  bool hasIndex(const Location& location) {
    return locationIndexes.find(location) != locationIndexes.end();
  }

  IndexLink getIndexes(const LocationLink& link) {
    return {getIndex(link.from), getIndex(link.to)};
  }

  // See the comment on CollectedFuncInfo::childParents. This is the merged info
  // from all the functions and the global scope.
  std::unordered_map<LocationIndex, LocationIndex> childParents;

  // The work remaining to do during the flow: locations that we need to flow
  // content from, after new content reached them.
  //
  // Using a set here is efficient as multiple updates may arrive to a location
  // before we get to processing it.
  //
  // The items here could be {location, newContents}, but it is more efficient
  // to have already written the new contents to the main data structure. That
  // avoids larger data here, and also, updating the contents as early as
  // possible is helpful as anything reading them meanwhile (before we get to
  // their work item in the queue) will see the newer value, possibly avoiding
  // flowing an old value that would later be overwritten.
  //
  // This must be ordered to avoid nondeterminism. The problem is that our
  // operations are imprecise and so the transitive property does not hold:
  // (AvB)vC may differ from Av(BvC). Likewise (AvB)^C may differ from
  // (A^C)v(B^C). An example of the latter is if a location is sent a null func
  // and an i31, and the location can only contain funcref. If the null func
  // arrives first, then later we'd merge null func + i31 which ends up as Many,
  // and then we filter that to funcref and get funcref. But if the i31 arrived
  // first, we'd filter it into nothing, and then the null func that arrives
  // later would be the final result. This would not happen if our operations
  // were precise, but we only make approximations here to avoid unacceptable
  // overhead, such as cone types but not arbitrary unions, etc.
  InsertOrderedSet<LocationIndex> workQueue;

  // All existing links in the graph. We keep this to know when a link we want
  // to add is new or not.
  std::unordered_set<IndexLink> links;

  // Update a location with new contents that are added to everything already
  // present there. If the update changes the contents at that location (if
  // there was anything new) then we also need to flow from there, which we will
  // do by adding the location to the work queue, and eventually flowAfterUpdate
  // will be called on this location.
  //
  // Returns whether it is worth sending new contents to this location in the
  // future. If we return false, the sending location never needs to do that
  // ever again.
  bool updateContents(LocationIndex locationIndex,
                      PossibleContents newContents);

  // Slow helper that converts a Location to a LocationIndex. This should be
  // avoided. TODO: remove the remaining uses of this.
  bool updateContents(const Location& location,
                      const PossibleContents& newContents) {
    return updateContents(getIndex(location), newContents);
  }

  // Flow contents from a location where a change occurred. This sends the new
  // contents to all the normal targets of this location (using
  // flowToTargetsAfterUpdate), and also handles special cases of flow after.
  void flowAfterUpdate(LocationIndex locationIndex);

  // Internal part of flowAfterUpdate that handles sending new values to the
  // given location index's normal targets (that is, the ones listed in the
  // |targets| vector).
  void flowToTargetsAfterUpdate(LocationIndex locationIndex,
                                const PossibleContents& contents);

  // Add a new connection while the flow is happening. If the link already
  // exists it is not added.
  void connectDuringFlow(Location from, Location to);

  // Contents sent to certain locations can be filtered in a special way during
  // the flow, which is handled in these helpers. These may update
  // |worthSendingMore| which is whether it is worth sending any more content to
  // this location in the future.
  void filterExpressionContents(PossibleContents& contents,
                                const ExpressionLocation& exprLoc,
                                bool& worthSendingMore);
  void filterGlobalContents(PossibleContents& contents,
                            const GlobalLocation& globalLoc);
  void filterDataContents(PossibleContents& contents,
                          const DataLocation& dataLoc);
  void filterPackedDataReads(PossibleContents& contents,
                             const ExpressionLocation& exprLoc);

  // Reads from GC data: a struct.get or array.get. This is given the type of
  // the read operation, the field that is read on that type, the known contents
  // in the reference the read receives, and the read instruction itself. We
  // compute where we need to read from based on the type and the ref contents
  // and get that data, adding new links in the graph as needed.
  void readFromData(Type declaredType,
                    Index fieldIndex,
                    const PossibleContents& refContents,
                    Expression* read);

  // Similar to readFromData, but does a write for a struct.set or array.set.
  void writeToData(Expression* ref, Expression* value, Index fieldIndex);

  // A write with given contents.
  void writeToData(Expression* ref,
                   const PossibleContents& valueContents,
                   Index fieldIndex);

  // We will need subtypes during the flow, so compute them once ahead of time.
  std::unique_ptr<SubTypes> subTypes;

  // The depth of children for each type. This is 0 if the type has no
  // subtypes, 1 if it has subtypes but none of those have subtypes themselves,
  // and so forth.
  std::unordered_map<HeapType, Index> maxDepths;

  // Given a ConeType, return the normalized depth, that is, the canonical depth
  // given the actual children it has. If this is a full cone, then we can
  // always pick the actual maximal depth and use that instead of FullDepth==-1.
  // For a non-full cone, we also reduce the depth as much as possible, so it is
  // equal to the maximum depth of an existing subtype.
  Index getNormalizedConeDepth(Type type, Index depth) {
    auto iter = maxDepths.find(type.getHeapType());
    // A max depth must be in the map (otherwise we would use the default 0,
    // making it exact, almost certainly incorrectly).
    assert(iter != maxDepths.end());
    return std::min(depth, iter->second);
  }

  void normalizeConeType(PossibleContents& cone) {
    assert(cone.isConeType());
    auto type = cone.getType();
    auto before = cone.getCone().depth;
    auto normalized = getNormalizedConeDepth(type, before);
    if (normalized != before) {
      cone = PossibleContents::coneType(type, normalized);
    }
  }

#if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
  // Dump out a location for debug purposes.
  void dump(Location location);
#endif
};

Flower::Flower(Module& wasm, const PassOptions& options)
  : wasm(wasm), options(options) {

  // If traps never happen, create a TNH oracle.
  //
  // Atm this oracle only helps on GC content, so disable it without GC.
  if (options.trapsNeverHappen && wasm.features.hasGC()) {
#if POSSIBLE_CONTENTS_DEBUG
    std::cout << "tnh phase\n";
    Timer timer;
#endif
    tnhOracle = std::make_unique<TNHOracle>(wasm, options);
#if POSSIBLE_CONTENTS_DEBUG
    std::cout << "... " << timer.lastElapsed() << "\n";
#endif
  }

#if POSSIBLE_CONTENTS_DEBUG
  std::cout << "subtypes phase\n";
  Timer timer;
#endif

  subTypes = std::make_unique<SubTypes>(wasm);
  maxDepths = subTypes->getMaxDepths();

#if POSSIBLE_CONTENTS_DEBUG
  std::cout << "... " << timer.lastElapsed() << "\n";
  std::cout << "parallel phase\n";
#endif

  // Compute shared info that we need for the main pass over each function, such
  // as the imported/exported tables.
  SharedInfo shared(*subTypes);

  for (auto& table : wasm.tables) {
    if (table->imported()) {
      shared.publicTables.insert(table->name);
    }
  }

  for (auto& ex : wasm.exports) {
    if (ex->kind == ExternalKind::Table) {
      shared.publicTables.insert(*ex->getInternalName());
    }
  }

  // Collect information from each function.
  ModuleUtils::ParallelFunctionAnalysis<CollectedFuncInfo> analysis(
    wasm, [&](Function* func, CollectedFuncInfo& info) {
      InfoCollector finder(shared, info, options);

      if (func->imported()) {
        // Imports return unknown values.
        auto results = func->getResults();
        for (Index i = 0; i < results.size(); i++) {
          finder.addRoot(ResultLocation{func, i},
                         PossibleContents::fromType(results[i]));
        }
        return;
      }

      finder.walkFunctionInModule(func, &wasm);
    });

#if POSSIBLE_CONTENTS_DEBUG
  std::cout << "... " << timer.lastElapsed() << "\n";
  std::cout << "single phase\n";
#endif

  // Also walk the global module code (for simplicity, also add it to the
  // function map, using a "function" key of nullptr).
  auto& globalInfo = analysis.map[nullptr];
  InfoCollector finder(shared, globalInfo, options);
  finder.walkModuleCode(&wasm);

#if POSSIBLE_CONTENTS_DEBUG
  std::cout << "... " << timer.lastElapsed() << "\n";
  std::cout << "global init phase\n";
#endif

  // Connect global init values (which we've just processed, as part of the
  // module code) to the globals they initialize.
  for (auto& global : wasm.globals) {
    if (global->imported()) {
      // Imports are unknown values.
      finder.addRoot(GlobalLocation{global->name},
                     PossibleContents::fromType(global->type));
      continue;
    }
    auto* init = global->init;
    if (finder.isRelevant(init->type)) {
      globalInfo.links.push_back(
        {ExpressionLocation{init, 0}, GlobalLocation{global->name}});
    }
  }

  // Merge the function information into a single large graph that represents
  // the entire program all at once, indexing and deduplicating everything as we
  // go.

#if POSSIBLE_CONTENTS_DEBUG
  std::cout << "... " << timer.lastElapsed() << "\n";
  std::cout << "merging+indexing phase\n";
#endif

  // The merged roots. (Note that all other forms of merged data are declared at
  // the class level, since we need them during the flow, but the roots are only
  // needed to start the flow, so we can declare them here.)
  //
  // This must be insert-ordered for the same reason as |workQueue| is, see
  // above.
  InsertOrderedMap<LocationIndex, PossibleContents> roots;

  // Any function that may be called from the outside, like an export, is a
  // root, since they can be called with unknown parameters. Collect all such
  // functions.
  std::unordered_set<Name> calledFromOutside;

  for (auto& [func, info] : analysis.map) {
    for (auto& link : info.links) {
      links.insert(getIndexes(link));
    }
    for (auto& [root, value] : info.roots) {
      roots[getIndex(root)] = value;

      // Ensure an index even for a root with no links to it - everything needs
      // an index.
      getIndex(root);
    }
    for (auto [child, parent] : info.childParents) {
      // In practice we do not have any childParent connections with a tuple;
      // assert on that just to be safe.
      assert(!child->type.isTuple());
      childParents[getIndex(ExpressionLocation{child, 0})] =
        getIndex(ExpressionLocation{parent, 0});
    }

    for (auto func : info.calledFromOutside) {
      calledFromOutside.insert(func);
    }
  }

  // We no longer need the function-level info.
  analysis.map.clear();

#if POSSIBLE_CONTENTS_DEBUG
  std::cout << "... " << timer.lastElapsed() << "\n";
  std::cout << "external phase\n";
#endif

  // Exports can be modified from the outside.
  for (auto& ex : wasm.exports) {
    if (ex->kind == ExternalKind::Function) {
      calledFromOutside.insert(*ex->getInternalName());
    } else if (ex->kind == ExternalKind::Table) {
      // If any table is exported, assume any function in any table (including
      // other tables) can be called from the outside.
      // TODO: This could be more precise about which tables are exported and
      //       which are not: perhaps one table is exported but we can optimize
      //       the functions in another table, which is not exported. However,
      //       it is simpler to treat them all the same, and this handles the
      //       common case of no tables being exported at all.
      // TODO: This does not handle table.get/table.set, or call_ref, for which
      //       we'd need to see which references are used and which escape etc.
      //       For now, assume a closed world for such such advanced use cases /
      //       assume this pass won't be run in them anyhow.
      // TODO: do this only once if multiple tables are exported
      for (auto& elementSegment : wasm.elementSegments) {
        for (auto* curr : elementSegment->data) {
          if (auto* refFunc = curr->dynCast<RefFunc>()) {
            calledFromOutside.insert(refFunc->func);
          }
        }
      }
    } else if (ex->kind == ExternalKind::Global) {
      // Exported mutable globals are roots, since the outside may write any
      // value to them.
      auto name = *ex->getInternalName();
      auto* global = wasm.getGlobal(name);
      if (global->mutable_) {
        roots[getIndex(GlobalLocation{name})] =
          PossibleContents::fromType(global->type);
      }
    }
  }

  // JS-called functions are called from outside the module, as if exported.
  for (auto func : Intrinsics(wasm).getJSCalledFunctions()) {
    calledFromOutside.insert(func);
  }

  // Apply changes to all functions called from outside.
  for (auto funcName : calledFromOutside) {
    auto* func = wasm.getFunction(funcName);
    auto params = func->getParams();
    for (Index i = 0; i < func->getParams().size(); i++) {
      roots[getIndex(ParamLocation{func, i})] =
        PossibleContents::fromType(params[i]);
    }
  }

  // Exported/imported tags are modifiable from the outside. TODO: should that
  // not be possible in closed world?
  std::unordered_set<Name> publicTags;
  for (auto& tag : wasm.tags) {
    if (tag->imported()) {
      publicTags.insert(tag->name);
    }
  }
  for (auto& ex : wasm.exports) {
    if (ex->kind == ExternalKind::Tag) {
      publicTags.insert(*ex->getInternalName());
    }
  }
  for (auto tag : publicTags) {
    auto params = wasm.getTag(tag)->params();
    for (Index i = 0; i < params.size(); i++) {
      roots[getIndex(TagLocation{tag, i})] =
        PossibleContents::fromType(params[i]);
    }
  }

  // In open world, public heap types may be written to from the outside.
  if (options.worldMode == WorldMode::Open) {
    for (auto type : ModuleUtils::getPublicHeapTypes(wasm, options.worldMode)) {
      if (type.isStruct()) {
        auto& fields = type.getStruct().fields;
        for (Index i = 0; i < fields.size(); i++) {
          roots[getIndex(DataLocation{type, i})] =
            PossibleContents::fromType(fields[i].type);
        }
        if (auto desc = type.getDescriptorType()) {
          auto descType = Type(*desc, Nullable, Inexact);
          roots[getIndex(DataLocation{type, DataLocation::DescriptorIndex})] =
            PossibleContents::fromType(descType);
        }
      } else if (type.isArray()) {
        roots[getIndex(DataLocation{type, 0})] =
          PossibleContents::fromType(type.getArray().element.type);
      } else if (type.isSignature()) {
        auto sig = type.getSignature();
        for (Index i = 0; i < sig.results.size(); i++) {
          roots[getIndex(SignatureResultLocation{type, i})] =
            PossibleContents::fromType(sig.results[i]);
        }
      }
    }
  }

#if POSSIBLE_CONTENTS_DEBUG
  std::cout << "... " << timer.lastElapsed() << "\n";
  std::cout << "function subtyping phase\n";
#endif

  // Link function subtyping params. When a function of type B has a supertype
  // A, then we may call B using A's type. That means the parameters to
  // (indirect) calls to B must look at supertypes, which is the opposite of the
  // logic for results, readFromData(), etc. For now, we just connect these
  // types directly, which does not fully optimize exact types. TODO: Add a new
  // mechanism to optimize here.
  for (auto type : subTypes->types) {
    if (!type.isFunction()) {
      continue;
    }
    auto super = type.getSuperType();
    if (!super) {
      continue;
    }
    auto params = type.getSignature().params;
    for (Index i = 0; i < params.size(); i++) {
      links.insert(getIndexes(LocationLink{SignatureParamLocation{*super, i},
                                           SignatureParamLocation{type, i}}));
    }
  }

#if POSSIBLE_CONTENTS_DEBUG
  std::cout << "... " << timer.lastElapsed() << "\n";
  std::cout << "Link-targets phase\n";
#endif

  // Add all links to the targets vectors of the source locations, which we will
  // use during the flow.
  for (auto& link : links) {
    getTargets(link.from).push_back(link.to);
  }

#ifndef NDEBUG
  // Each vector of targets (which is a vector for efficiency) must have no
  // duplicates.
  for (auto& info : locations) {
    disallowDuplicates(info.targets);
  }
#endif

#if POSSIBLE_CONTENTS_DEBUG
  std::cout << "... " << timer.lastElapsed() << "\n";
  std::cout << "roots phase\n";
#endif

  // Set up the roots, which are the starting state for the flow analysis: send
  // their initial content to them to start the flow.
  for (const auto& [location, value] : roots) {
#if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
    std::cout << "  init root\n";
    dump(getLocation(location));
    value.dump(std::cout, &wasm);
    std::cout << '\n';
#endif

    updateContents(location, value);
  }

#if POSSIBLE_CONTENTS_DEBUG
  std::cout << "... " << timer.lastElapsed() << "\n";
  std::cout << "flow phase\n";
  size_t iters = 0;
#endif

  // Flow the data while there is still stuff flowing.
  while (!workQueue.empty()) {
#if POSSIBLE_CONTENTS_DEBUG
    iters++;
    if ((iters & 255) == 0) {
      std::cout << iters++ << " iters, work left: " << workQueue.size() << '\n';
    }
#endif

    auto iter = workQueue.begin();
    auto locationIndex = *iter;
    workQueue.erase(iter);

    flowAfterUpdate(locationIndex);
  }

#if POSSIBLE_CONTENTS_DEBUG
  std::cout << "... " << timer.lastElapsed() << "\n";
#endif

  // TODO: Add analysis and retrieval logic for fields of immutable globals,
  //       including multiple levels of depth (necessary for itables in j2wasm).
}

bool Flower::updateContents(LocationIndex locationIndex,
                            PossibleContents newContents) {
  auto& contents = getContents(locationIndex);
  auto oldContents = contents;

#if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
  std::cout << "\nupdateContents\n";
  dump(getLocation(locationIndex));
  contents.dump(std::cout, &wasm);
  std::cout << "\n with new contents \n";
  newContents.dump(std::cout, &wasm);
  std::cout << '\n';
#endif

  auto location = getLocation(locationIndex);

  // Handle special cases: Some locations can only contain certain contents, so
  // filter accordingly. For example, if anyref arrives to a non-nullable
  // location, we know it must be (ref any). As a result, each time we update
  // the contents at a location we are both merging in the new contents, and
  // filtering based on what we know of the location.
  //
  // The operation of merging in new content and also filtering is *not*
  // commutative. Set intersection and union of course is, but the shapes we
  // work with here are limited, e.g. we have cones which include all children
  // up to a fixed depth (and not specific children or each with a different
  // depth). For example, if we start e.g. with a ref.func literal, and a
  // ref.null arrives, then merging results in a cone that allows null, as that
  // is the best shape we have that includes both. If the location is non-
  // nullable then the cone becomes non-nullable, so we ended up with something
  // worse than the original ref.func literal. In contrast, if we filtered the
  // new contents first, the null would vanish (as no null is possible in the
  // non-nullable location), so that order ends up better.
  //
  // For those reasons we filter the new contents arriving and also the merged
  // contents afterwards, to try to get the best results. This also avoids some
  // nondeterminism hazards with different orders. TODO: This does not avoid
  // them all, in principle, due to lack of commutativity. Using a deterministic
  // order (like abstract interpretation) would fix that.
  if (auto* dataLoc = std::get_if<DataLocation>(&location)) {
    // Filtering data contents is especially important to do before, and not
    // necessary afterwards. For example, imagine a location that contains an
    // i8 which is sent a 0 and then 0x100. If we filter only after, then we'd
    // combine 0 and 0x100 first and get "unknown integer"; only by filtering
    // 0x100 to 0 beforehand (since 0x100 & 0xff => 0) will we combine 0 and 0
    // and not change anything, which is best.
    filterDataContents(newContents, *dataLoc);
#if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
    std::cout << "  pre-filtered data contents:\n";
    newContents.dump(std::cout, &wasm);
    std::cout << '\n';
#endif
  } else if (auto* exprLoc = std::get_if<ExpressionLocation>(&location)) {
    if (exprLoc->expr->is<StructGet>() || exprLoc->expr->is<ArrayGet>()) {
      // As mentioned above, data locations can have packed reads, which require
      // filtering before. Note that there is no need to filter atomic RMW
      // operations here because they always do unsigned reads.
      filterPackedDataReads(newContents, *exprLoc);
#if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
      std::cout << "  pre-filtered packed read contents:\n";
      newContents.dump(std::cout, &wasm);
      std::cout << '\n';
#endif
    }

    // Generic filtering. We do this both before and after.
    //
    // The outcome of this filtering does not affect whether it is worth sending
    // more later (we compute that at the end), so use a temp out var for that.
    bool worthSendingMoreTemp = true;
    filterExpressionContents(newContents, *exprLoc, worthSendingMoreTemp);

#if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
    std::cout << "  post-filtered exprLoc:\n";
    newContents.dump(std::cout, &wasm);
    std::cout << '\n';
#endif
  } else if (auto* globalLoc = std::get_if<GlobalLocation>(&location)) {
    // Generic filtering. We do this both before and after.
    filterGlobalContents(newContents, *globalLoc);
  }

  // After filtering newContents, combine it onto the existing contents.
  contents.combine(newContents);

  if (contents.isNone()) {
    // There is still nothing here. There is nothing more to do here but to
    // return that it is worth sending more.
    return true;
  }

  // It is not worth sending any more to this location if we are now in the
  // worst possible case, as no future value could cause any change.
  bool worthSendingMore = true;
  if (contents.isConeType()) {
    if (!contents.getType().isRef()) {
      // A cone type of a non-reference is the worst case, since subtyping is
      // not relevant there, and so if we only know something about the type
      // then we already know nothing beyond what the type in the wasm tells us
      // (and from there we can only go to Many).
      worthSendingMore = false;
    } else {
      // Normalize all reference cones. There is never a point to flow around
      // anything non-normalized, which might lead to extra work. For example,
      // if A has no subtypes, then a full cone for A is really the same as one
      // with depth 0 (an exact type). And we don't want to see the full cone
      // arrive and think it was an improvement over the one with depth 0 and do
      // more flowing based on that.
      normalizeConeType(contents);
    }
  }

  // Check if anything changed.
  if (contents == oldContents) {
    // Nothing actually changed, so just return.
    return worthSendingMore;
  }

  // Handle filtering (see comment earlier, this is the later filtering stage).
  bool filtered = false;
  if (auto* exprLoc = std::get_if<ExpressionLocation>(&location)) {
    // TODO: Replace this with specific filterFoo or flowBar methods like we
    //       have for filterGlobalContents. That could save a little wasted work
    //       here. Might be best to do that after the spec is fully stable.
    filterExpressionContents(contents, *exprLoc, worthSendingMore);
    filtered = true;
  } else if (auto* globalLoc = std::get_if<GlobalLocation>(&location)) {
    filterGlobalContents(contents, *globalLoc);
    filtered = true;
  } else if (auto* dataLoc = std::get_if<DataLocation>(&location)) {
    // Multibyte array stores with differing widths can merge to Many, so
    // filter again afterwards to fall back to the declared type limit.
    filterDataContents(contents, *dataLoc);
    filtered = true;
  }

  // Check if anything changed after filtering, if we did so.
  if (filtered) {
#if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
    std::cout << "  filtered contents:\n";
    contents.dump(std::cout, &wasm);
    std::cout << '\n';
#endif

    if (contents == oldContents) {
      return worthSendingMore;
    }
  }

#if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
  std::cout << "  updateContents has something new\n";
  contents.dump(std::cout, &wasm);
  std::cout << '\n';
#endif

  // After filtering we should always have more precise information than "many"
  // - in the worst case, we can have the type declared in the wasm.
  assert(!contents.isMany());

  // Add a work item if there isn't already.
  workQueue.insert(locationIndex);

  return worthSendingMore;
}

void Flower::flowAfterUpdate(LocationIndex locationIndex) {
  const auto location = getLocation(locationIndex);
  auto& contents = getContents(locationIndex);

  // We are called after a change at a location. A change means that some
  // content has arrived, since we never send empty values around. Assert on
  // that.
  assert(!contents.isNone());

#if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
  std::cout << "\nflowAfterUpdate to:\n";
  dump(location);
  std::cout << "  arriving:\n";
  contents.dump(std::cout, &wasm);
  std::cout << '\n';
#endif

  // Flow the contents to the normal targets of this location.
  flowToTargetsAfterUpdate(locationIndex, contents);

  // We are mostly done, except for handling interesting/special cases in the
  // flow, additional operations that we need to do aside from sending the new
  // contents to the normal (statically linked) targets.

  if (auto* exprLoc = std::get_if<ExpressionLocation>(&location)) {
    auto iter = childParents.find(locationIndex);
    if (iter == childParents.end()) {
      return;
    }

    // This is indeed one of the special cases where it is the child of a
    // parent, and we need to do some special handling because of that child-
    // parent connection.
    [[maybe_unused]] auto* child = exprLoc->expr;
    auto parentIndex = iter->second;
    auto* parent = std::get<ExpressionLocation>(getLocation(parentIndex)).expr;

#if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
    std::cout << "  special, parent:\n" << *parent << '\n';
#endif

    if (auto* get = parent->dynCast<StructGet>()) {
      // |child| is the reference child of a struct.get.
      assert(get->ref == child);
      readFromData(get->ref->type, get->index, contents, get);
    } else if (auto* set = parent->dynCast<StructSet>()) {
      // |child| is either the reference or the value child of a struct.set.
      assert(set->ref == child || set->value == child);
      writeToData(set->ref, set->value, set->index);
    } else if (auto* set = parent->dynCast<StructRMW>()) {
      assert(set->ref == child || set->value == child);
      // TODO: model the stored value, depending on the actual operation.
      writeToData(
        set->ref, PossibleContents::fromType(set->value->type), set->index);
    } else if (auto* set = parent->dynCast<StructCmpxchg>()) {
      assert(set->ref == child || set->expected == child ||
             set->replacement == child);
      // TODO: model the stored value, depending on the actual operation.
      writeToData(set->ref,
                  PossibleContents::fromType(set->replacement->type),
                  set->index);
    } else if (auto* get = parent->dynCast<ArrayGet>()) {
      assert(get->ref == child);
      readFromData(get->ref->type, 0, contents, get);
    } else if (auto* set = parent->dynCast<ArraySet>()) {
      assert(set->ref == child || set->value == child);
      writeToData(set->ref, set->value, 0);
    } else if (auto* load = parent->dynCast<ArrayLoad>()) {
      assert(load->ref == child);
      readFromData(load->ref->type, 0, contents, load);
    } else if (auto* store = parent->dynCast<ArrayStore>()) {
      assert(store->ref == child || store->value == child);
      // TODO: model the stored value, and handle different but equal values in
      //       type, e.g. writing i16 0x1212 is the same as i8 0x12.
      writeToData(
        store->ref, PossibleContents::fromType(store->value->type), 0);
    } else if (auto* set = parent->dynCast<ArrayRMW>()) {
      assert(set->ref == child || set->value == child);
      // TODO: model the stored value, depending on the actual operation.
      writeToData(set->ref, PossibleContents::fromType(set->value->type), 0);
    } else if (auto* set = parent->dynCast<ArrayCmpxchg>()) {
      assert(set->ref == child || set->expected == child ||
             set->replacement == child);
      // TODO: model the stored value, depending on the actual operation.
      writeToData(
        set->ref, PossibleContents::fromType(set->replacement->type), 0);
    } else if (auto* get = parent->dynCast<RefGetDesc>()) {
      assert(get->ref == child);
      readFromData(
        get->ref->type, DataLocation::DescriptorIndex, contents, get);
    } else {
      // TODO: ref.test and all other casts can be optimized (see the cast
      //       helper code used in OptimizeInstructions and RemoveUnusedBrs)
      WASM_UNREACHABLE("bad childParents content");
    }
  }
}

void Flower::flowToTargetsAfterUpdate(LocationIndex locationIndex,
                                      const PossibleContents& contents) {
  // Send the new contents to all the targets of this location. As we do so,
  // prune any targets that we do not need to bother sending content to in the
  // future, to save space and work later.
  auto& targets = getTargets(locationIndex);
  targets.erase(std::remove_if(targets.begin(),
                               targets.end(),
                               [&](LocationIndex targetIndex) {
#if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
                                 std::cout << "  send to target\n";
                                 dump(getLocation(targetIndex));
#endif
                                 return !updateContents(targetIndex, contents);
                               }),
                targets.end());

  if (contents.isMany()) {
    // We contain Many, and just called updateContents on our targets to send
    // that value to them. We'll never need to send anything from here ever
    // again, since we sent the worst case possible already, so we can just
    // clear our targets vector. But we should have already removed all the
    // targets in the above remove_if operation, since they should have all
    // notified us that we do not need to send them any more updates.
    assert(targets.empty());
  }
}

void Flower::connectDuringFlow(Location from, Location to) {
  auto newLink = LocationLink{from, to};
  auto newIndexLink = getIndexes(newLink);
  if (!links.contains(newIndexLink)) {
    // This is a new link. Add it to the known links.
    links.insert(newIndexLink);

    // Add it to the |targets| vector.
    auto& targets = getTargets(newIndexLink.from);
    targets.push_back(newIndexLink.to);
#ifndef NDEBUG
    disallowDuplicates(targets);
#endif

    // In addition to adding the link, which will ensure new contents appearing
    // later will be sent along, we also update with the current contents.
    updateContents(to, getContents(getIndex(from)));
  }
}

void Flower::filterExpressionContents(PossibleContents& contents,
                                      const ExpressionLocation& exprLoc,
                                      bool& worthSendingMore) {
  auto type = exprLoc.expr->type;

  if (type.isTuple()) {
    // TODO: Optimize tuples here as well. We would need to take into account
    //       exprLoc.tupleIndex for that in all the below.
    return;
  }

  // The caller cannot know of a situation where it might not be worth sending
  // more to a reference - all that logic is in here. That is, the rest of this
  // function is the only place we can mark |worthSendingMore| as false for a
  // reference.
  bool isRef = type.isRef();
  assert(!isRef || worthSendingMore);

  // The TNH oracle informs us of the maximal contents possible here.
  auto maximalContents = getTNHContents(exprLoc.expr);
#if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
  std::cout << "TNHOracle informs us that " << *exprLoc.expr << " contains "
            << maximalContents << "\n";
#endif

  if (exprLoc.expr->is<ArrayLoad>()) {
    // ArrayLoad cannot filter, as we can have writes of different sizes than
    // the type of the location (e.g. write i32, do an i64.load). If there is
    // any content, just report the maximal content, basically like a Memory.
    if (!contents.isNone()) {
      contents = maximalContents;
    }
    return;
  }

  contents.intersect(maximalContents);
  if (contents.isNone()) {
    // Nothing was left here at all.
    return;
  }

  // For references we need to normalize the intersection, see below. For non-
  // references, we are done (we did all the relevant work in the intersect()
  // call).
  if (!isRef) {
    return;
  }

  // Normalize the intersection. We want to check later if any more content can
  // arrive here, and also we want to avoid flowing around anything non-
  // normalized, as explained earlier.
  //
  // Note that this normalization is necessary even though |contents| was
  // normalized before the intersection, e.g.:
  /*
  //      A
  //     / \
  //    B   C
  //        |
  //        D
  */
  // Consider the case where |maximalContents| is Cone(B, Infinity) and the
  // original |contents| was Cone(A, 2) (which is normalized). The naive
  // intersection is Cone(B, 1), since the core intersection logic makes no
  // assumptions about the rest of the types. That is then normalized to
  // Cone(B, 0) since there happens to be no subtypes for B.
  //
  // Note that the intersection may also not be a cone type, if it is a global
  // or literal. In that case we don't have anything more to do here.
  if (!contents.isConeType()) {
    return;
  }

  normalizeConeType(contents);

  // There is a chance that the intersection is equal to the maximal contents,
  // which would mean nothing more can arrive here.
  normalizeConeType(maximalContents);

  if (contents == maximalContents) {
    // We already contain everything possible, so this is the worst case.
    worthSendingMore = false;
  }
}

void Flower::filterGlobalContents(PossibleContents& contents,
                                  const GlobalLocation& globalLoc) {
  auto* global = wasm.getGlobal(globalLoc.name);
  if (global->mutable_ == Immutable) {
    // This is an immutable global. We never need to consider this value as
    // "Many", since in the worst case we can just use the immutable value. That
    // is, we can always replace this value with (global.get $name) which will
    // get the right value. Likewise, using the immutable global value is often
    // better than a cone type (even an exact one), but TODO: we could note both
    // a cone/exact type *and* that something is equal to a global, in some
    // cases. See https://github.com/WebAssembly/binaryen/pull/5083
    if (contents.isMany() || contents.isConeType()) {
      contents = PossibleContents::global(
        global->name, ExternalKind::Global, global->type);

      // TODO: We could do better here, to set global->init->type instead of
      //       global->type, or even the contents.getType() - either of those
      //       may be more refined. But other passes will handle that in
      //       general (by refining the global's type).

#if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
      std::cout << "  setting immglobal to ImmutableGlobal\n";
      contents.dump(std::cout, &wasm);
      std::cout << '\n';
#endif
    }
  }
}

void Flower::filterDataContents(PossibleContents& contents,
                                const DataLocation& dataLoc) {
  if (dataLoc.index == DataLocation::DescriptorIndex) {
    // Nothing to filter (packing is not relevant for a descriptor).
    return;
  }
  auto field = GCTypeUtils::getField(dataLoc.type, dataLoc.index);
  if (!field) {
    // This is a bottom type; nothing will be written here.
    assert(dataLoc.type.isBottom());
    contents = PossibleContents::none();
    return;
  }
  if (contents.isMany()) {
    // An unknown state (e.g. from combining writes of different types like in
    // multibyte array stores) translates into the most generic bounded type.
    // TODO: We could optimize these, as e.g. a write of i16 0x1212 does not
    // actually conflict with a write of i8 0x12.
    contents = PossibleContents::fromType(field->type);
  }

  if (field->isPacked()) {
    // We must handle packed fields carefully.
    if (contents.isLiteral()) {
      // This is a constant. We can truncate it and use that value.
      auto mask = Literal(int32_t(Bits::lowBitMask(field->getByteSize() * 8)));
      contents = PossibleContents::literal(contents.getLiteral().and_(mask));
    } else {
      // This is not a constant. We can't even handle a global here, as we'd
      // need to track that this global's value must be truncated before it is
      // used, and we don't do that atm. Leave only the type.
      // TODO Consider tracking packing on GlobalInfo alongside the type.
      //      Another option is to make GUFA.cpp apply packing on the read,
      //      like CFP does - but that can only be done when replacing a
      //      StructGet of a packed field, and not anywhere else we saw that
      //      value reach.
      contents = PossibleContents::fromType(contents.getType());
    }
    // Given that the above only (1) turns an i32 into a masked i32 or (2) turns
    // anything else into an unknown i32, this is safe to run as pre-filtering,
    // that is, before we combine contents, since
    //
    //  (a) two constants are ok as masking is distributive,
    //        (x & M) U (y & M)  ==  (x U y) & M
    //  (b) if one is a constant and the other is not then
    //        (x & M) U ?  ==  ?  ==  (x U ?)  ==  (x U ?) & M
    //      (where ? is an unknown i32)
    //  (c) and if both are not constants then likewise we always end up as an
    //      unknown i32
    //
  }
}

void Flower::filterPackedDataReads(PossibleContents& contents,
                                   const ExpressionLocation& exprLoc) {
  auto* expr = exprLoc.expr;

  // Packed fields are stored as the truncated bits (see comment on
  // DataLocation; the actual truncation is done in filterDataContents), which
  // means that unsigned gets just work but signed ones need fixing (and we only
  // know how to do that here, when we reach the get and see if it is signed).
  auto signed_ = false;
  Expression* ref;
  Index index;
  unsigned bytes = 0;
  if (auto* get = expr->dynCast<StructGet>()) {
    signed_ = get->signed_;
    ref = get->ref;
    index = get->index;
  } else if (auto* get = expr->dynCast<ArrayGet>()) {
    signed_ = get->signed_;
    ref = get->ref;
    // Arrays are treated as having a single field.
    index = 0;
  } else if (auto* load = expr->dynCast<ArrayLoad>()) {
    signed_ = load->signed_;
    ref = load->ref;
    index = 0;
    bytes = load->bytes;
  } else {
    WASM_UNREACHABLE("bad packed read");
  }
  if (!signed_) {
    return;
  }

  Type resultType = expr->type;
  if (resultType == Type::unreachable) {
    // This read never executes.
    return;
  }

  // If there is no struct or array to read, no value will ever be returned.
  if (ref->type.isNull()) {
    contents = PossibleContents::none();
    return;
  }

  // We are reading data here, so the reference must be a valid struct or
  // array, otherwise we would never have gotten here.
  assert(ref->type.isRef());
  auto field = GCTypeUtils::getField(ref->type.getHeapType(), index);
  assert(field);
  if (!bytes) {
    if (!field->isPacked()) {
      return;
    }
    bytes = field->getByteSize();
  }

  if (contents.isLiteral()) {
    // This is a constant. We can sign-extend it and use that value.
    unsigned bits = resultType.getByteSize() == 8 ? 64 : 32;
    if (bits <= bytes * 8) {
      // No need to sign-extend for full size.
      return;
    }
    auto shifts = Literal(int32_t(bits - bytes * 8));
    auto lit = contents.getLiteral();
    lit = lit.shl(shifts);
    lit = lit.shrS(shifts);
    contents = PossibleContents::literal(lit);
  } else {
    // This is not a constant. As in filterDataContents, give up and leave
    // only the type, since we have no way to track the sign-extension on
    // top of whatever this is.
    contents = PossibleContents::fromType(contents.getType());
  }
}

void Flower::readFromData(Type declaredType,
                          Index fieldIndex,
                          const PossibleContents& refContents,
                          Expression* read) {
#ifndef NDEBUG
  // We must not have anything in the reference that is invalid for the wasm
  // type there.
  auto maximalContents = PossibleContents::coneType(declaredType);
  assert(PossibleContents::isSubContents(refContents, maximalContents));
#endif

  // The data that a struct.get reads depends on two things: the reference that
  // we read from, and the relevant DataLocations. The reference determines
  // which DataLocations are relevant: if it is an exact type then we have a
  // single DataLocation to read from, the one type that can be read from there.
  // Otherwise, we might read from any subtype, and so all their DataLocations
  // are relevant.
  //
  // What can be confusing is that the information about the reference is also
  // inferred during the flow. That is, we use our current information about the
  // reference to decide what to do here. But the flow is not finished yet!
  // To keep things valid, we must therefore react to changes in either the
  // reference - when we see that more types might be read from here - or the
  // DataLocations - when new things are written to the data we can read from.
  // Specifically, at every point in time we want to preserve the property that
  // we've read from all relevant types based on the current reference, and
  // we've read the very latest possible contents from those types. And then
  // since we preserve that property til the end of the flow, it is also valid
  // then. At the end of the flow, the current reference's contents are the
  // final and correct contents for that location, which means we've ended up
  // with the proper result: the struct.get reads everything it should.
  //
  // To implement what was just described, we call this function when the
  // reference is updated. This function will then set up connections in the
  // graph so that updates to the relevant DataLocations will reach us in the
  // future.

  if (refContents.isNull() || refContents.isNone()) {
    // Nothing is read here as this is either a null or unreachable code. (Note
    // that the contents must be a subtype of the wasm type, which rules out
    // other possibilities like a non-null literal such as an integer or a
    // function reference.)
    return;
  }

#if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
  std::cout << "    add special reads\n";
#endif

  // The only possibilities left are a cone type (the worst case is where the
  // cone matches the wasm type), or a global.
  //
  // TODO: The Global case may have a different cone type than the heapType,
  //       which we could use here.
  // TODO: A Global may refer to an immutable global, which we can read the
  //       field from potentially (reading it from the struct.new/array.new
  //       in the definition of it, if it is not imported; or, we could track
  //       the contents of immutable fields of allocated objects, and not just
  //       represent them as an exact type).
  //       See the test TODO with text "We optimize some of this, but stop at
  //       reading from the immutable global"
  assert(refContents.isGlobal() || refContents.isConeType());

  // Just look at the cone here, discarding information about this being a
  // global, if it was one. All that matters from now is the cone. We also
  // normalize the cone to avoid wasted work later.
  auto cone = refContents.getCone();
  auto normalizedDepth = getNormalizedConeDepth(cone.type, cone.depth);

  // We create a ConeReadLocation for the canonical cone of this type, to
  // avoid bloating the graph, see comment on ConeReadLocation().
  auto coneReadLocation =
    ConeReadLocation{cone.type.getHeapType(), normalizedDepth, fieldIndex};
  if (!hasIndex(coneReadLocation)) {
    // This is the first time we use this location, so create the links for it
    // in the graph.
    subTypes->iterSubTypes(cone.type.getHeapType(),
                           normalizedDepth,
                           [&](HeapType type, Index depth) {
                             connectDuringFlow(DataLocation{type, fieldIndex},
                                               coneReadLocation);
                             return true;
                           });

    // TODO: we can end up with redundant links here if we see one cone first
    //       and then a larger one later. But removing links is not efficient,
    //       so for now just leave that.
  }

  // Link to the canonical location.
  connectDuringFlow(coneReadLocation, ExpressionLocation{read, 0});
}

void Flower::writeToData(Expression* ref, Expression* value, Index fieldIndex) {
  // We could set up links here as we do for reads, but as we get to this code
  // in any case, we can just flow the values forward directly. This avoids
  // adding any links (edges) to the graph (and edges are what we want to avoid
  // adding, as there can be a quadratic number of them). In other words, we'll
  // loop over the places we need to send info to, which we can figure out in a
  // simple way, and by doing so we avoid materializing edges into the graph.
  //
  // Note that this is different from readFromData, above, which does add edges
  // to the graph (and works hard to add as few as possible, see the "canonical
  // cone reads" logic). The difference is because readFromData must "subscribe"
  // to get notifications from the relevant DataLocations. But when writing that
  // is not a problem: whenever a change happens in the reference or the value
  // of a struct.set then this function will get called, and those are the only
  // things we care about. And we can then just compute the values we are
  // sending (based on the current contents of the reference and the value), and
  // where we should send them to, and do that right here. (And as commented in
  // readFromData, that is guaranteed to give us the right result in the end: at
  // every point in time we send the right data, so when the flow is finished
  // we've sent information based on the final and correct information about our
  // reference and value.)

  auto valueContents = getContents(getIndex(ExpressionLocation{value, 0}));
  writeToData(ref, valueContents, fieldIndex);
}

void Flower::writeToData(Expression* ref,
                         const PossibleContents& valueContents,
                         Index fieldIndex) {
#if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
  std::cout << "    add special writes\n";
#endif

  auto refContents = getContents(getIndex(ExpressionLocation{ref, 0}));

#ifndef NDEBUG
  // We must not have anything in the reference that is invalid for the wasm
  // type there.
  auto maximalContents = PossibleContents::coneType(ref->type);
  assert(PossibleContents::isSubContents(refContents, maximalContents));
#endif

  // See the related comment in readFromData() as to why these are the only
  // things we need to check, and why the assertion afterwards contains the only
  // things possible.
  if (refContents.isNone() || refContents.isNull()) {
    return;
  }
  assert(refContents.isGlobal() || refContents.isConeType());

  // As in readFromData, normalize to the proper cone.
  auto cone = refContents.getCone();
  auto normalizedDepth = getNormalizedConeDepth(cone.type, cone.depth);

  subTypes->iterSubTypes(
    cone.type.getHeapType(), normalizedDepth, [&](HeapType type, Index depth) {
      auto heapLoc = DataLocation{type, fieldIndex};
      updateContents(heapLoc, valueContents);
      return true;
    });
}

#if defined(POSSIBLE_CONTENTS_DEBUG) && POSSIBLE_CONTENTS_DEBUG >= 2
void Flower::dump(Location location) {
  if (auto* loc = std::get_if<ExpressionLocation>(&location)) {
    std::cout << "  exprloc \n"
              << *loc->expr << " : " << loc->tupleIndex << '\n';
  } else if (auto* loc = std::get_if<DataLocation>(&location)) {
    std::cout << "  dataloc ";
    if (wasm.typeNames.contains(loc->type)) {
      std::cout << '$' << wasm.typeNames[loc->type].name;
    } else {
      std::cout << loc->type << '\n';
    }
    std::cout << " : " << loc->index << '\n';
  } else if (auto* loc = std::get_if<TagLocation>(&location)) {
    std::cout << "  tagloc " << loc->tag << " : " << loc->tupleIndex << '\n';
  } else if (auto* loc = std::get_if<ParamLocation>(&location)) {
    std::cout << "  paramloc " << loc->func->name << " : " << loc->index
              << '\n';
  } else if (auto* loc = std::get_if<LocalLocation>(&location)) {
    std::cout << "  localloc " << loc->func->name << " : " << loc->index
              << '\n';
  } else if (auto* loc = std::get_if<ResultLocation>(&location)) {
    std::cout << "  resultloc $" << loc->func->name << " : " << loc->index
              << '\n';
  } else if (auto* loc = std::get_if<GlobalLocation>(&location)) {
    std::cout << "  globalloc " << loc->name << '\n';
  } else if (std::get_if<SignatureParamLocation>(&location)) {
    std::cout << "  sigparamloc " << '\n';
  } else if (auto* loc = std::get_if<SignatureResultLocation>(&location)) {
    std::cout << "  sigresultloc " << loc->type << " : " << loc->index << '\n';
  } else {
    std::cout << "  (other)\n";
  }
}
#endif

} // anonymous namespace

void ContentOracle::analyze() {
  Flower flower(wasm, options);
  for (LocationIndex i = 0; i < flower.locations.size(); i++) {
    locationContents[flower.getLocation(i)] = flower.getContents(i);
  }
}

} // namespace wasm
