/*
 * 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 "module-utils.h"
#include "ir/intrinsics.h"
#include "ir/manipulation.h"
#include "ir/metadata.h"
#include "ir/subtypes.h"
#include "pass.h"
#include "support/insert_ordered.h"
#include "support/topological_sort.h"
#include "support/utilities.h"
#include "wasm-builder.h"

namespace wasm::ModuleUtils {

// Update the file name indices when moving a set of debug locations from one
// module to another.
static void updateLocation(std::optional<Function::DebugLocation>& location,
                           std::vector<Index>& fileIndexMap) {
  if (location) {
    location->fileIndex = fileIndexMap[location->fileIndex];
  }
}

// Update the symbol name indices when moving a set of debug locations from one
// module to another.
static void updateSymbol(std::optional<Function::DebugLocation>& location,
                         std::vector<Index>& symbolIndexMap) {
  if (location && location->symbolNameIndex) {
    location->symbolNameIndex = symbolIndexMap[*location->symbolNameIndex];
  }
}

// Copies a function into a module. If newName is provided it is used as the
// name of the function (otherwise the original name is copied). If fileIndexMap
// is specified, it is used to rename source map filename indices when copying
// the function from one module to another one. If symbolNameIndexMap is
// specified, it is used to rename source map symbol name indices when copying
// the function from one module to another one.
Function* copyFunction(Function* func,
                       Module& out,
                       Name newName,
                       std::optional<std::vector<Index>> fileIndexMap,
                       std::optional<std::vector<Index>> symbolNameIndexMap) {
  auto ret = copyFunctionWithoutAdd(
    func, out, newName, fileIndexMap, symbolNameIndexMap);
  return out.addFunction(std::move(ret));
}

std::unique_ptr<Function>
copyFunctionWithoutAdd(Function* func,
                       Module& out,
                       Name newName,
                       std::optional<std::vector<Index>> fileIndexMap,
                       std::optional<std::vector<Index>> symbolNameIndexMap) {
  auto ret = std::make_unique<Function>();
  ret->name = newName.is() ? newName : func->name;
  ret->hasExplicitName = func->hasExplicitName;
  ret->type = func->type;
  ret->vars = func->vars;
  ret->localNames = func->localNames;
  ret->localIndices = func->localIndices;
  ret->body = ExpressionManipulator::copy(func->body, out);
  metadata::copyBetweenFunctions(func->body, ret->body, func, ret.get());
  ret->funcAnnotations = func->funcAnnotations;
  ret->prologLocation = func->prologLocation;
  ret->epilogLocation = func->epilogLocation;
  // Update file indices if needed
  if (fileIndexMap) {
    for (auto& iter : ret->debugLocations) {
      if (iter.second) {
        iter.second->fileIndex = (*fileIndexMap)[iter.second->fileIndex];
      }
    }
    updateLocation(ret->prologLocation, *fileIndexMap);
    updateLocation(ret->epilogLocation, *fileIndexMap);
  }
  if (symbolNameIndexMap) {
    for (auto& iter : ret->debugLocations) {
      if (iter.second) {
        if (iter.second->symbolNameIndex.has_value()) {
          iter.second->symbolNameIndex =
            (*symbolNameIndexMap)[*(iter.second->symbolNameIndex)];
        }
      }
    }
    updateSymbol(ret->prologLocation, *symbolNameIndexMap);
    updateSymbol(ret->epilogLocation, *symbolNameIndexMap);
  }
  ret->module = func->module;
  ret->base = func->base;
  ret->noFullInline = func->noFullInline;
  ret->noPartialInline = func->noPartialInline;
  return ret;
}

Global* copyGlobal(Global* global, Module& out) {
  auto* ret = new Global();
  ret->name = global->name;
  ret->hasExplicitName = global->hasExplicitName;
  ret->type = global->type;
  ret->mutable_ = global->mutable_;
  ret->module = global->module;
  ret->base = global->base;
  if (global->imported()) {
    ret->init = nullptr;
  } else {
    ret->init = ExpressionManipulator::copy(global->init, out);
  }
  out.addGlobal(ret);
  return ret;
}

Tag* copyTag(Tag* tag, Module& out) {
  auto* ret = new Tag();
  ret->name = tag->name;
  ret->hasExplicitName = tag->hasExplicitName;
  ret->type = tag->type;
  ret->module = tag->module;
  ret->base = tag->base;
  out.addTag(ret);
  return ret;
}

ElementSegment* copyElementSegment(const ElementSegment* segment, Module& out) {
  auto copy = [&](std::unique_ptr<ElementSegment>&& ret) {
    ret->name = segment->name;
    ret->hasExplicitName = segment->hasExplicitName;
    ret->type = segment->type;
    ret->data.reserve(segment->data.size());
    for (auto* item : segment->data) {
      ret->data.push_back(ExpressionManipulator::copy(item, out));
    }

    return out.addElementSegment(std::move(ret));
  };

  if (segment->isPassive()) {
    return copy(std::make_unique<ElementSegment>());
  } else {
    auto offset = ExpressionManipulator::copy(segment->offset, out);
    return copy(std::make_unique<ElementSegment>(segment->table, offset));
  }
}

Table* copyTable(const Table* table, Module& out) {
  auto ret = std::make_unique<Table>();
  ret->name = table->name;
  ret->hasExplicitName = table->hasExplicitName;
  ret->type = table->type;
  ret->module = table->module;
  ret->base = table->base;

  ret->initial = table->initial;
  ret->max = table->max;
  ret->addressType = table->addressType;
  if (table->init) {
    ret->init = ExpressionManipulator::copy(table->init, out);
  }

  return out.addTable(std::move(ret));
}

Memory* copyMemory(const Memory* memory, Module& out) {
  auto ret = Builder::makeMemory(memory->name);
  ret->hasExplicitName = memory->hasExplicitName;
  ret->initial = memory->initial;
  ret->max = memory->max;
  ret->pageSizeLog2 = memory->pageSizeLog2;
  ret->shared = memory->shared;
  ret->addressType = memory->addressType;
  ret->module = memory->module;
  ret->base = memory->base;

  return out.addMemory(std::move(ret));
}

DataSegment* copyDataSegment(const DataSegment* segment, Module& out) {
  auto ret = Builder::makeDataSegment();
  ret->name = segment->name;
  ret->hasExplicitName = segment->hasExplicitName;
  ret->memory = segment->memory;
  if (segment->isActive()) {
    auto offset = ExpressionManipulator::copy(segment->offset, out);
    ret->offset = offset;
  }
  ret->data = segment->data;

  return out.addDataSegment(std::move(ret));
}

// Copies named toplevel module items (things of kind ModuleItemKind). See
// copyModule() for something that also copies exports, the start function, etc.
void copyModuleItems(const Module& in, Module& out) {
  // If the source module has some debug information, we first compute how
  // to map file name indices from this modules to file name indices in
  // the target module.
  std::optional<std::vector<Index>> fileIndexMap;
  if (!in.debugInfoFileNames.empty()) {
    std::unordered_map<std::string, Index> debugInfoFileIndices;
    for (Index i = 0; i < out.debugInfoFileNames.size(); i++) {
      debugInfoFileIndices[out.debugInfoFileNames[i]] = i;
    }
    fileIndexMap.emplace();
    for (Index i = 0; i < in.debugInfoFileNames.size(); i++) {
      std::string file = in.debugInfoFileNames[i];
      auto iter = debugInfoFileIndices.find(file);
      if (iter == debugInfoFileIndices.end()) {
        Index index = out.debugInfoFileNames.size();
        out.debugInfoFileNames.push_back(file);
        debugInfoFileIndices[file] = index;
      }
      fileIndexMap->push_back(debugInfoFileIndices[file]);
    }
  }

  std::optional<std::vector<Index>> symbolNameIndexMap;
  if (!in.debugInfoSymbolNames.empty()) {
    std::unordered_map<std::string, Index> debugInfoSymbolNameIndices;
    for (Index i = 0; i < out.debugInfoSymbolNames.size(); i++) {
      debugInfoSymbolNameIndices[out.debugInfoSymbolNames[i]] = i;
    }
    symbolNameIndexMap.emplace();
    for (Index i = 0; i < in.debugInfoSymbolNames.size(); i++) {
      std::string file = in.debugInfoSymbolNames[i];
      auto iter = debugInfoSymbolNameIndices.find(file);
      if (iter == debugInfoSymbolNameIndices.end()) {
        Index index = out.debugInfoSymbolNames.size();
        out.debugInfoSymbolNames.push_back(file);
        debugInfoSymbolNameIndices[file] = index;
      }
      symbolNameIndexMap->push_back(debugInfoSymbolNameIndices[file]);
    }
  }

  for (auto& curr : in.functions) {
    copyFunction(curr.get(), out, Name(), fileIndexMap, symbolNameIndexMap);
  }
  for (auto& curr : in.globals) {
    copyGlobal(curr.get(), out);
  }
  for (auto& curr : in.tags) {
    copyTag(curr.get(), out);
  }
  for (auto& curr : in.elementSegments) {
    copyElementSegment(curr.get(), out);
  }
  for (auto& curr : in.tables) {
    copyTable(curr.get(), out);
  }
  for (auto& curr : in.memories) {
    copyMemory(curr.get(), out);
  }
  for (auto& curr : in.dataSegments) {
    copyDataSegment(curr.get(), out);
  }

  for (auto& [type, names] : in.typeNames) {
    if (!out.typeNames.contains(type)) {
      out.typeNames[type] = names;
    }
  }
}

// TODO: merge this with copyModuleItems, and add options for copying
// exports and other things that are currently different between them,
// if we still need those differences.
void copyModule(const Module& in, Module& out) {
  // we use names throughout, not raw pointers, so simple copying is fine
  // for everything *but* expressions
  for (auto& curr : in.exports) {
    out.addExport(std::make_unique<Export>(*curr));
  }
  copyModuleItems(in, out);
  out.start = in.start;
  out.customSections = in.customSections;
  out.debugInfoFileNames = in.debugInfoFileNames;
  out.debugInfoSymbolNames = in.debugInfoSymbolNames;
  out.features = in.features;
}

void clearModule(Module& wasm) {
  wasm.~Module();
  new (&wasm) Module;
}

// Renaming

// Rename functions along with all their uses.
// Note that for this to work the functions themselves don't necessarily need
// to exist.  For example, it is possible to remove a given function and then
// call this to redirect all of its uses.
template<typename T> void renameFunctions(Module& wasm, T& map) {
  // Update the function itself.
  for (auto& [oldName, newName] : map) {
    if (Function* func = wasm.getFunctionOrNull(oldName)) {
      assert(!wasm.getFunctionOrNull(newName) || func->name == newName);
      func->name = newName;
    }
  }
  wasm.updateMaps();

  // Update all references to it.
  struct Updater : public WalkerPass<PostWalker<Updater>> {
    bool isFunctionParallel() override { return true; }

    T& map;

    void maybeUpdate(Name& name) {
      if (auto iter = map.find(name); iter != map.end()) {
        name = iter->second;
      }
    }

    Updater(T& map) : map(map) {}

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

    void visitCall(Call* curr) { maybeUpdate(curr->target); }

    void visitRefFunc(RefFunc* curr) { maybeUpdate(curr->func); }
  };

  Updater updater(map);
  updater.maybeUpdate(wasm.start);
  PassRunner runner(&wasm);
  updater.run(&runner, &wasm);
  updater.runOnModuleCode(&runner, &wasm);
}

void renameFunction(Module& wasm, Name oldName, Name newName) {
  std::map<Name, Name> map;
  map[oldName] = newName;
  renameFunctions(wasm, map);
}

namespace {

// Helper for collecting HeapTypes and their frequencies.
struct TypeInfos {
  InsertOrderedMap<HeapType, HeapTypeInfo> info;

  // Multivalue control flow structures need a function type, but the identity
  // of the function type (i.e. what recursion group it is in or whether it is
  // final) doesn't matter. Save them for the end to see if we can re-use an
  // existing function type with the necessary signature.
  InsertOrderedMap<Signature, size_t> controlFlowSignatures;

  void note(HeapType type) {
    if (!type.isBasic()) {
      ++info[type].useCount;
    }
  }
  void note(Type type) {
    // Handle the common case of a ref directly, to avoid a scan of children.
    if (type.isRef()) {
      note(type.getHeapType());
      return;
    }
    if (type.isTuple()) {
      for (HeapType ht : type.getHeapTypeChildren()) {
        note(ht);
      }
    }
  }
  // Ensure a type is included without increasing its count.
  void include(HeapType type) {
    if (!type.isBasic()) {
      info[type];
    }
  }
  void include(Type type) {
    if (type.isRef()) {
      include(type.getHeapType());
      return;
    }
    if (type.isTuple()) {
      for (HeapType ht : type.getHeapTypeChildren()) {
        include(ht);
      }
    }
  }
  void noteControlFlow(Signature sig) {
    // TODO: support control flow input parameters.
    assert(sig.params.size() == 0);
    if (sig.results.isTuple()) {
      // We have to use a function type.
      ++controlFlowSignatures[sig];
    } else if (sig.results != Type::none) {
      // The result type can be emitted directly instead of using a function
      // type.
      note(sig.results);
    }
  }
  bool contains(HeapType type) { return info.contains(type); }
};

using ReferencedFuncs = std::unordered_map<Name, std::atomic<bool>>;

struct CodeScanner : PostWalker<CodeScanner> {
  TypeInfos& info;
  ReferencedFuncs& referencedFuncs;

  CodeScanner(Module& wasm, TypeInfos& info, ReferencedFuncs& referencedFuncs)
    : info(info), referencedFuncs(referencedFuncs) {
    setModule(&wasm);
  }

  void visitCallIndirect(CallIndirect* curr) { info.note(curr->heapType); }
  void visitCallRef(CallRef* curr) { info.note(curr->target->type); }
  void visitRefNull(RefNull* curr) { info.note(curr->type); }
  void visitSelect(Select* curr) {
    if (curr->type.isRef()) {
      // This select will be annotated in the binary, so note it.
      info.note(curr->type);
    }
  }
  void visitStructNew(StructNew* curr) { info.note(curr->type); }
  void visitArrayNew(ArrayNew* curr) { info.note(curr->type); }
  void visitArrayNewData(ArrayNewData* curr) { info.note(curr->type); }
  void visitArrayNewElem(ArrayNewElem* curr) { info.note(curr->type); }
  void visitArrayNewFixed(ArrayNewFixed* curr) { info.note(curr->type); }
  void visitArrayCopy(ArrayCopy* curr) {
    info.note(curr->destRef->type);
    info.note(curr->srcRef->type);
  }
  void visitArrayFill(ArrayFill* curr) { info.note(curr->ref->type); }
  void visitArrayInitData(ArrayInitData* curr) { info.note(curr->ref->type); }
  void visitArrayInitElem(ArrayInitElem* curr) { info.note(curr->ref->type); }
  void visitRefCast(RefCast* curr) { info.note(curr->type); }
  void visitRefTest(RefTest* curr) { info.note(curr->castType); }
  void visitBrOn(BrOn* curr) {
    if (curr->op == BrOnCast || curr->op == BrOnCastFail) {
      info.note(curr->ref->type);
      info.note(curr->castType);
    }
  }
  void visitStructGet(StructGet* curr) { info.note(curr->ref->type); }
  void visitStructSet(StructSet* curr) { info.note(curr->ref->type); }
  void visitStructWait(StructWait* curr) { info.note(curr->ref->type); }
  void visitArrayGet(ArrayGet* curr) { info.note(curr->ref->type); }
  void visitArraySet(ArraySet* curr) { info.note(curr->ref->type); }
  void visitContBind(ContBind* curr) {
    info.note(curr->cont->type);
    info.note(curr->type);
  }
  void visitContNew(ContNew* curr) { info.note(curr->type); }
  void visitResume(Resume* curr) {
    info.note(curr->cont->type);
    info.note(curr->type);
  }
  void visitResumeThrow(ResumeThrow* curr) {
    info.note(curr->cont->type);
    info.note(curr->type);
  }
  void visitStackSwitch(StackSwitch* curr) {
    info.note(curr->cont->type);
    info.note(curr->type);
  }
  void visitBlock(Block* curr) {
    info.noteControlFlow(Signature(Type::none, curr->type));
  }
  void visitIf(If* curr) {
    info.noteControlFlow(Signature(Type::none, curr->type));
  }
  void visitLoop(Loop* curr) {
    info.noteControlFlow(Signature(Type::none, curr->type));
  }
  void visitTry(Try* curr) {
    info.noteControlFlow(Signature(Type::none, curr->type));
  }
  void visitTryTable(TryTable* curr) {
    info.noteControlFlow(Signature(Type::none, curr->type));
  }
  void visitRefFunc(RefFunc* curr) { referencedFuncs.at(curr->func) = true; }
};

void classifyTypeVisibility(Module& wasm,
                            InsertOrderedMap<HeapType, HeapTypeInfo>& types,
                            const ReferencedFuncs& referencedFuncs,
                            WorldMode worldMode);

} // anonymous namespace

InsertOrderedMap<HeapType, HeapTypeInfo>
collectHeapTypeInfo(Module& wasm,
                    WorldMode worldMode,
                    TypeInclusion inclusion,
                    VisibilityHandling visibility) {
  // Collect module-level info.
  TypeInfos info;
  ReferencedFuncs referencedFuncs;
  for (const auto& func : wasm.functions) {
    referencedFuncs.emplace(func->name, false);
  }
  CodeScanner(wasm, info, referencedFuncs).walkModuleCode(&wasm);
  for (const auto& curr : wasm.globals) {
    info.note(curr->type);
  }
  for (const auto& curr : wasm.tags) {
    info.note(curr->type);
  }
  for (const auto& curr : wasm.tables) {
    info.note(curr->type);
  }
  for (const auto& curr : wasm.elementSegments) {
    info.note(curr->type);
  }

  // Collect info from functions in parallel.
  ModuleUtils::ParallelFunctionAnalysis<TypeInfos, Immutable, InsertOrderedMap>
    analysis(wasm, [&](Function* func, TypeInfos& info) {
      info.note(func->type);
      for (auto type : func->vars) {
        info.note(type);
      }
      // Don't just use `func->imported()` here because we also might be
      // printing an error message on a partially parsed module whose declared
      // function bodies have not all been parsed yet.
      if (func->body) {
        CodeScanner(wasm, info, referencedFuncs).walk(func->body);
      }
    });

  // Combine the function info with the module info.
  for (const auto& [func, functionInfo] : analysis.map) {
    for (const auto& [type, typeInfo] : functionInfo.info) {
      info.info[type].useCount += typeInfo.useCount;
    }
    for (const auto& [sig, count] : functionInfo.controlFlowSignatures) {
      info.controlFlowSignatures[sig] += count;
    }
    if (!referencedFuncs.at(func->name)) {
      auto funcType = func->type.getHeapType();
      ++info.info[funcType].unreferencedFuncUseCount;
    }
  }

  // Recursively traverse each reference type, which may have a child type that
  // is itself a reference type. This reflects an appearance in the binary
  // format that is in the type section itself. As we do this we may find more
  // and more types, as nested children of previous ones. Each such type will
  // appear in the type section once, so we just need to visit it once. Also
  // track which recursion groups we've already processed to avoid quadratic
  // behavior when there is a single large group.
  // TODO: Use a vector here, since we never try to add the same type twice.
  UniqueNonrepeatingDeferredQueue<HeapType> newTypes;
  std::unordered_map<Signature, HeapType> seenSigs;
  auto noteNewType = [&](HeapType type) {
    newTypes.push(type);
    if (type.isSignature()) {
      seenSigs.insert({type.getSignature(), type});
    }
  };
  for (const auto& [type, _] : info.info) {
    noteNewType(type);
  }
  auto controlFlowIt = info.controlFlowSignatures.begin();
  std::unordered_set<RecGroup> includedGroups;
  while (!newTypes.empty()) {
    while (!newTypes.empty()) {
      auto ht = newTypes.pop();
      for (HeapType child : ht.getReferencedHeapTypes()) {
        if (!child.isBasic()) {
          if (!info.contains(child)) {
            noteNewType(child);
          }
          info.note(child);
        }
      }

      // Make sure we've noted the complete recursion group of each type as
      // well.
      if (inclusion != TypeInclusion::UsedIRTypes) {
        auto recGroup = ht.getRecGroup();
        if (includedGroups.insert(recGroup).second) {
          for (auto type : recGroup) {
            if (!info.contains(type)) {
              noteNewType(type);
              info.include(type);
            }
          }
        }
      }
    }

    // We've found all the types there are to find without considering more
    // control flow types. Consider one more control flow type and repeat.
    while (controlFlowIt != info.controlFlowSignatures.end()) {
      auto& [sig, count] = *controlFlowIt++;
      HeapTypeInfo* sigInfo = nullptr;
      bool newType = false;
      if (auto it = seenSigs.find(sig); it != seenSigs.end()) {
        sigInfo = &info.info.at(it->second);
      } else {
        // We've never seen this signature before, so add a type for it.
        HeapType type(sig);
        noteNewType(type);
        newType = true;
        sigInfo = &info.info[type];
      }
      sigInfo->useCount += count;
      sigInfo->controlFlowUseCount += count;
      if (newType) {
        break;
      }
    }
  }

  if (visibility == VisibilityHandling::FindVisibility) {
    classifyTypeVisibility(wasm, info.info, referencedFuncs, worldMode);
  }

  return std::move(info.info);
}

namespace {

// Collects all defined heap types transitively reachable from a root set of
// types.
std::vector<HeapType>
getTransitivelyReachable(const std::vector<HeapType>& roots) {
  std::vector<HeapType> result;
  std::vector<HeapType> worklist;
  std::unordered_set<RecGroup> seenRecGroups;

  auto note = [&](HeapType type) {
    if (type.isBasic()) {
      return;
    }

    auto group = type.getRecGroup();
    if (seenRecGroups.insert(group).second) {
      for (auto member : group) {
        result.push_back(member);
        worklist.push_back(member);
      }
    }
  };

  for (auto type : roots) {
    note(type);
  }

  while (!worklist.empty()) {
    auto curr = worklist.back();
    worklist.pop_back();
    for (auto t : curr.getReferencedHeapTypes()) {
      note(t);
    }
  }

  return result;
}

// Computes the visibility of all types in the module.
//
// ## Closed World Mode
// Every type reachable from imports/exports and all of their rec group siblings
// are marked public. This preserves the structural type identity of the imports
// and exports.
//
// ## Open World Mode
// In an open world, the outside environment may cast a publicized type down
// to any of its subtypes. Thus, subtypes of exposed types must also remain
// public to preserve their structural identities.
void classifyTypeVisibility(Module& wasm,
                            InsertOrderedMap<HeapType, HeapTypeInfo>& types,
                            const ReferencedFuncs& referencedFuncs,
                            WorldMode worldMode) {
  if (worldMode == WorldMode::Closed) {
    // In closed world mode, the public types are simply the exposed types and
    // all types reachable from their definitions.
    for (auto type : getPublicHeapTypes(wasm, WorldMode::Closed)) {
      if (auto it = types.find(type); it != types.end()) {
        it->second.visibility = Visibility::Public;
      }
    }
    for (auto& [_, info] : types) {
      if (info.visibility != Visibility::Public) {
        info.visibility = Visibility::Private;
      }
    }
    return;
  }

  // Open world public types have different levels of exposure that change
  // whether their related types must be public or not.
  enum Exposure {
    // Types that never cross the module boundary (i.e. are "not exposed"), but
    // must have stable structural identities so some other public type can have
    // a stable identity.
    NotExposed,
    // Types that may cross the module boundary only via exact references.
    ExposedExactly,
    // Types that may cross the module boundary via inexact references, meaning
    // their subtypes may cross the module boundary as well.
    Exposed
  };

  std::unordered_map<HeapType, Exposure> exposures;
  std::vector<HeapType> worklist;

  // Insert or upgrade a type's exposure in the `visited` map. If a type's
  // exposure is upgraded, we re-push it to the worklist to update the
  // propagation to related types.
  auto markPublic = [&](HeapType type, Exposure state) {
    auto [it, inserted] = exposures.try_emplace(type, state);
    if (inserted || state > it->second) {
      it->second = state;
      worklist.push_back(type);
    }
  };

  // When `func` is exposed, we naively would have to make every function type
  // public. However, we can be more precise and keep function types that are
  // only used for non-referenced functions and control flow private.
  std::unordered_set<HeapType> privateFunctionTypes;
  for (const auto& [type, info] : types) {
    if (type.isSignature() &&
        info.useCount ==
          info.controlFlowUseCount + info.unreferencedFuncUseCount) {
      privateFunctionTypes.insert(type);
    }
  }

  // Build the subtype hierarchy.
  std::vector<HeapType> heapTypes;
  heapTypes.reserve(types.size());
  for (const auto& [type, _] : types) {
    heapTypes.push_back(type);
  }
  SubTypes subTypes(heapTypes);

  // Initialize with directly exposed types.
  for (const auto& [type, exact] : getExposedPublicHeapTypes(wasm)) {
    markPublic(type,
               exact == Exact ? Exposure::ExposedExactly : Exposure::Exposed);
  }

  while (!worklist.empty()) {
    auto curr = worklist.back();
    worklist.pop_back();

    auto state = exposures.at(curr);

    // Propagate exposed status to subtypes.
    if (state == Exposure::Exposed) {
      // `func` gets special treatment because we do not mark function types
      // only used in unreferenced function declarations or control flow public.
      // Other kinds of heap types cannot be inhabited without having reference
      // values.
      if (curr.isMaybeShared(HeapType::func)) {
        for (const auto& [definedType, _] : types) {
          if (HeapType::isSubType(definedType, curr) &&
              !privateFunctionTypes.contains(definedType)) {
            markPublic(definedType, Exposure::Exposed);
          }
        }
      } else if (curr.isBasic()) {
        for (const auto& [definedType, _] : types) {
          if (HeapType::isSubType(definedType, curr)) {
            markPublic(definedType, Exposure::Exposed);
          }
        }
      } else {
        for (auto sub : subTypes.getImmediateSubTypes(curr)) {
          markPublic(sub, Exposure::Exposed);
        }
      }
    }

    if (curr.isBasic()) {
      continue;
    }

    // Rec group members must also be public, but do not necessarily cross the
    // module boundary.
    for (auto member : curr.getRecGroup()) {
      markPublic(member, Exposure::NotExposed);
    }

    // Types reachable from this public type (e.g. params, results, fields) must
    // be public. If the current type is not exposed, the other reachable types
    // are not necessarily exposed either. If the current type is exposed
    // (whether exactly or not), the reachable types are exposed with exactness
    // depending on the reference type.
    for (auto child : curr.getTypeChildren()) {
      if (child.isRef()) {
        auto exposure = state == NotExposed ? NotExposed
                        : child.isExact()   ? ExposedExactly
                                            : Exposed;
        markPublic(child.getHeapType(), exposure);
      }
    }

    // Public continuation types require their function types to be public, but
    // a continuation reference does not make any function reference available.
    if (curr.isContinuation()) {
      markPublic(curr.getContinuation().type, NotExposed);
    }

    // Descriptor types are like type children, except that they are exposed
    // exactly iff the current type is exposed exactly.
    if (auto desc = curr.getDescriptorType()) {
      markPublic(*desc, state);
    }

    // Supertypes need to be public, but only to keep structural identity the
    // same. Other types related to the supertypes are not necessarily exposed.
    if (auto super = curr.getDeclaredSuperType()) {
      markPublic(*super, Exposure::NotExposed);
    }

    // Similarly, described types also need to be kept public, but they are not
    // necessarily exposed just because their descriptor is exposed.
    if (auto described = curr.getDescribedType()) {
      markPublic(*described, Exposure::NotExposed);
    }
  }

  // Mark visibility for all defined types
  for (auto& [type, typeInfo] : types) {
    if (exposures.contains(type)) {
      typeInfo.visibility = Visibility::Public;
    } else {
      typeInfo.visibility = Visibility::Private;
    }
  }
}

void setIndices(IndexedHeapTypes& indexedTypes) {
  for (Index i = 0; i < indexedTypes.types.size(); i++) {
    indexedTypes.indices[indexedTypes.types[i]] = i;
  }
}

} // anonymous namespace

std::vector<HeapType> collectHeapTypes(Module& wasm) {
  auto info = collectHeapTypeInfo(wasm, WorldMode::Open);
  std::vector<HeapType> types;
  types.reserve(info.size());
  for (const auto& [type, _] : info) {
    types.push_back(type);
  }
  return types;
}

std::vector<std::pair<HeapType, Exactness>>
getExposedPublicHeapTypes(Module& wasm) {
  InsertOrderedMap<HeapType, Exactness> seenTypes;

  auto notePublic = [&](HeapType type, Exactness exact) {
    auto [it, inserted] = seenTypes.insert({type, exact});
    if (!inserted) {
      if (it->second == Exact && exact == Inexact) {
        it->second = Inexact;
      }
    }
  };

  ModuleUtils::iterImportedTags(
    wasm, [&](Tag* tag) { notePublic(tag->type, Inexact); });
  ModuleUtils::iterImportedTables(wasm, [&](Table* table) {
    assert(table->type.isRef());
    notePublic(table->type.getHeapType(), table->type.getExactness());
  });
  ModuleUtils::iterImportedGlobals(wasm, [&](Global* global) {
    if (global->type.isRef()) {
      notePublic(global->type.getHeapType(), global->type.getExactness());
    }
  });
  ModuleUtils::iterImportedFunctions(wasm, [&](Function* func) {
    if (!Intrinsics(wasm).isCallWithoutEffects(func)) {
      notePublic(func->type.getHeapType(), Inexact);
    }
  });
  for (auto& ex : wasm.exports) {
    switch (ex->kind) {
      case ExternalKind::Function: {
        auto* func = wasm.getFunction(*ex->getInternalName());
        notePublic(func->type.getHeapType(), Inexact);
        continue;
      }
      case ExternalKind::Table: {
        auto* table = wasm.getTable(*ex->getInternalName());
        assert(table->type.isRef());
        notePublic(table->type.getHeapType(), table->type.getExactness());
        continue;
      }
      case ExternalKind::Memory:
        continue;
      case ExternalKind::Global: {
        auto* global = wasm.getGlobal(*ex->getInternalName());
        if (global->type.isRef()) {
          notePublic(global->type.getHeapType(), global->type.getExactness());
        }
        continue;
      }
      case ExternalKind::Tag:
        notePublic(wasm.getTag(*ex->getInternalName())->type, Inexact);
        continue;
      case ExternalKind::Invalid:
        break;
    }
    WASM_UNREACHABLE("unexpected export kind");
  }

  for (auto type : getIgnorablePublicTypes()) {
    notePublic(type, Inexact);
  }

  return std::vector<std::pair<HeapType, Exactness>>(seenTypes.begin(),
                                                     seenTypes.end());
}

std::vector<HeapType> getPublicHeapTypes(Module& wasm, WorldMode worldMode) {
  if (worldMode == WorldMode::Closed) {
    // Find all the types reachable from the directly exposed types. There's no
    // need to traverse the entire module to find all the subtypes, etc.
    auto exposedPairs = getExposedPublicHeapTypes(wasm);
    std::vector<HeapType> directlyExposed;
    directlyExposed.reserve(exposedPairs.size());
    for (const auto& [type, _] : exposedPairs) {
      directlyExposed.push_back(type);
    }
    return getTransitivelyReachable(directlyExposed);
  }

  // In open-world mode we need to find all the types so we can include
  // subtypes.
  auto typeInfo = collectHeapTypeInfo(wasm,
                                      worldMode,
                                      TypeInclusion::AllTypes,
                                      VisibilityHandling::FindVisibility);
  std::vector<HeapType> publicTypes;
  for (const auto& [type, info] : typeInfo) {
    if (info.visibility == Visibility::Public) {
      publicTypes.push_back(type);
    }
  }
  return publicTypes;
}

std::vector<HeapType> getPrivateHeapTypes(Module& wasm, WorldMode worldMode) {
  auto info = collectHeapTypeInfo(wasm,
                                  worldMode,
                                  TypeInclusion::UsedIRTypes,
                                  VisibilityHandling::FindVisibility);
  std::vector<HeapType> types;
  types.reserve(info.size());
  for (const auto& [type, typeInfo] : info) {
    if (typeInfo.visibility == Visibility::Private) {
      types.push_back(type);
    }
  }
  return types;
}

IndexedHeapTypes getOptimizedIndexedHeapTypes(Module& wasm) {
  auto counts =
    collectHeapTypeInfo(wasm, WorldMode::Open, TypeInclusion::BinaryTypes);

  // Collect the rec groups.
  std::unordered_map<RecGroup, size_t> groupIndices;
  std::vector<RecGroup> groups;
  for (const auto& [type, _] : counts) {
    auto group = type.getRecGroup();
    if (groupIndices.insert({group, groups.size()}).second) {
      groups.push_back(group);
    }
  }

  // Collect the total use counts for each group.
  std::vector<size_t> groupCounts;
  groupCounts.reserve(groups.size());
  for (auto group : groups) {
    size_t count = 0;
    for (auto type : group) {
      count += counts.at(type).useCount;
    }
    groupCounts.push_back(count);
  }

  // Collect the reverse dependencies of each group.
  std::vector<std::unordered_set<size_t>> depSets(groups.size());
  for (size_t i = 0; i < groups.size(); ++i) {
    for (auto type : groups[i]) {
      for (auto child : type.getReferencedHeapTypes()) {
        if (child.isBasic()) {
          continue;
        }
        auto childGroup = child.getRecGroup();
        if (childGroup == groups[i]) {
          continue;
        }
        depSets[groupIndices.at(childGroup)].insert(i);
      }
    }
  }
  TopologicalSort::Graph deps;
  deps.reserve(groups.size());
  for (size_t i = 0; i < groups.size(); ++i) {
    deps.emplace_back(depSets[i].begin(), depSets[i].end());
  }

  // Experimentally determined to be pretty good for a variety of programs in
  // different languages.
  constexpr double childFactor = 0.25;

  // Each rec group's weight, adjusted for its size and incorporating the weight
  // of its users.
  std::vector<double> weights(groups.size());
  for (size_t i = 0; i < groups.size(); ++i) {
    weights[i] = double(groupCounts[i]) / groups[i].size();
  }
  auto sorted = TopologicalSort::sort(deps);
  for (auto it = sorted.rbegin(); it != sorted.rend(); ++it) {
    for (auto user : deps[*it]) {
      weights[*it] += childFactor * weights[user];
    }
  }

  // If we've preserved the input type order on the module, we have to respect
  // that first. Use the index of the first type from each group. In principle
  // we could try to do something more robust like take the minimum index of all
  // the types in the group, but if the groups haven't been preserved, then we
  // won't be able to perfectly preserve the order anyway.
  std::vector<std::optional<Index>> groupTypeIndices;
  if (wasm.typeIndices.empty()) {
    groupTypeIndices.resize(groups.size());
  } else {
    groupTypeIndices.reserve(groups.size());
    for (auto group : groups) {
      groupTypeIndices.emplace_back();
      if (auto it = wasm.typeIndices.find(group[0]);
          it != wasm.typeIndices.end()) {
        groupTypeIndices.back() = it->second;
      }
    }
  }

  auto order = TopologicalSort::minSort(deps, [&](size_t a, size_t b) {
    auto indexA = groupTypeIndices[a];
    auto indexB = groupTypeIndices[b];
    // Groups with indices must be sorted before groups without indices to
    // ensure transitivity of this comparison relation.
    if (indexA.has_value() != indexB.has_value()) {
      return indexA.has_value();
    }
    // Sort by preserved index if we can.
    if (indexA && *indexA != *indexB) {
      return *indexA < *indexB;
    }
    // Otherwise sort by weight and break ties by the arbitrary deterministic
    // order in which we've collected types.
    auto weightA = weights[a];
    auto weightB = weights[b];
    if (weightA != weightB) {
      return weightA > weightB;
    }
    return a < b;
  });

  IndexedHeapTypes indexedTypes;
  indexedTypes.types.reserve(counts.size());

  for (auto groupIndex : order) {
    for (auto type : groups[groupIndex]) {
      indexedTypes.types.push_back(type);
    }
  }
  setIndices(indexedTypes);
  return indexedTypes;
}

} // namespace wasm::ModuleUtils
