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

// The process of module splitting involves these steps:
//
//   1. Create the new secondary modules.
//
//   2. Move the deferred functions from the primary to each of the secondary
//      modules.
//
//   3. For any secondary function exported from the primary module, export in
//      its place a trampoline function that makes an indirect call to its
//      placeholder function (and eventually to the original secondary
//      function), allocating a new table slot for the placeholder if necessary.
//
//   4. Export globals, tags, tables, and memories from the primary module and
//      import them in the secondary modules. If possible, move those module
//      items instead to the secondary modules.
//
//   5. Replace all references to each secondary module's functions in the
//      primary module's and each other secondary module's table segments with
//      references to imported placeholder functions.
//
//   6. Rewrite direct calls from primary functions to secondary functions to be
//      indirect calls to their placeholder functions (and eventually to their
//      original secondary functions), allocating new table slots for the
//      placeholders if necessary.
//
//   7. For each primary function directly called from a secondary function,
//      export the primary function if it is not already exported and import it
//      into each secondary module using it.
//
//   8. For each secondary module, create new dispatch table segments in the
//      module that will replace all the placeholder function references in the
//      table with references to their corresponding secondary functions upon
//      instantiation.
//
// Functions can be used or referenced three ways in a WebAssembly module: they
// can be exported, called, or referenced with ref.func. The above procedure
// introduces a layer of indirection to each of those mechanisms that removes
// all references to secondary functions from the primary module but restores
// the original program's semantics once the secondary modules are instantiated.
//
// The code as currently written makes a couple assumptions about the module
// that is being split:
//
//   1. It assumes that mutable-globals is allowed. This could be worked around
//      by introducing wrapper functions for globals and rewriting secondary
//      code that accesses them, but now that mutable-globals is shipped on all
//      browsers, hopefully that extra complexity won't be necessary.
//
//   2. It assumes that either all table segment offsets are constants or there
//      is exactly one segment that may have a non-constant offset. It also
//      assumes that all segments are dispatch segments.
//
//   3. It assumes that if exact function references are required for validity
//      (because they are stored in a local with an exact function type, for
//      example), then custom descriptors are allowed so primary functions can
//      be imported exactly. This could be worked around by removing exactness
//      from the IR before splitting.
//
#include "ir/module-splitting.h"
#include "ir/effects.h"
#include "ir/find_all.h"
#include "ir/module-utils.h"
#include "ir/names.h"
#include "support/insert_ordered.h"
#include "support/unique_deferring_queue.h"
#include "wasm-builder.h"
#include "wasm.h"

namespace wasm::ModuleSplitting {

namespace {

template<class F> void forEachElement(Module& module, F f) {
  ModuleUtils::iterActiveElementSegments(module, [&](ElementSegment* segment) {
    Name base;
    Index offset = 0;
    if (auto* c = segment->offset->dynCast<Const>()) {
      offset = c->value.getInteger();
    } else if (auto* g = segment->offset->dynCast<GlobalGet>()) {
      base = g->name;
    }
    for (Index i = 0; i < segment->data.size(); ++i) {
      f(segment->table, base, offset + i, segment->data[i]);
    }
  });
}

struct TableSlotManager {
  struct Slot {
    Name tableName;

    // If `global` is empty, then this slot is at a statically known index.
    Name global;
    Index index = 0;

    // Generate code to compute the index of this table slot
    Expression* makeExpr(Module& module);
  };
  Module& module;
  const std::vector<std::unique_ptr<Module>>& secondaries;
  Table* dispatchTable = nullptr;
  ElementSegment* dispatchSegment = nullptr;
  Slot dispatchBase;
  std::map<Name, Slot> funcIndices;
  std::vector<ElementSegment*> dispatchTableSegments;

  TableSlotManager(Module& module,
                   const std::vector<std::unique_ptr<Module>>& secondaries);

  Table* makeTable();
  ElementSegment* makeElementSegment();

  // Returns the table index for `func`, allocating a new index if necessary.
  Slot getSlot(Name func, HeapType type);
  void addSlot(Name func, Slot slot);
};

Expression* TableSlotManager::Slot::makeExpr(Module& module) {
  Builder builder(module);
  auto* table = module.getTable(tableName);
  auto makeIndex = [&]() {
    return builder.makeConst(Literal::makeFromInt32(index, table->addressType));
  };
  if (global) {
    Expression* getBase = builder.makeGlobalGet(global, table->addressType);
    auto addOp = table->is64() ? AddInt64 : AddInt32;
    return index == 0 ? getBase
                      : builder.makeBinary(addOp, getBase, makeIndex());
  } else {
    return makeIndex();
  }
}

void TableSlotManager::addSlot(Name func, Slot slot) {
  // Ignore functions that already have slots.
  funcIndices.insert({func, slot});
}

TableSlotManager::TableSlotManager(
  Module& module, const std::vector<std::unique_ptr<Module>>& secondaries)
  : module(module), secondaries(secondaries) {
  // If possible, just create a new table to manage all primary-to-secondary
  // calls lazily. Do not re-use slots for functions that will already be in
  // existing tables, since that is not correct in the face of table mutations.
  // However, do not do this for emscripten; its loader code (and dynamic
  // loading in particular) do not support this yet.
  // TODO: Reduce overhead by creating a separate table for each function type
  // if WasmGC is enabled.
  Export* emscriptenTableExport =
    module.getExportOrNull("__indirect_function_table");
  Table* singletonTable =
    module.tables.size() == 1 ? module.tables[0].get() : nullptr;
  bool emscriptenTableImport =
    singletonTable && singletonTable->imported() &&
    singletonTable->module == "env" &&
    singletonTable->base == "__indirect_function_table";

  if (module.features.hasReferenceTypes() && !emscriptenTableExport &&
      !emscriptenTableImport) {
    return;
  }

  // TODO: Reject or handle passive element segments
  auto funcref = Type(HeapType::func, Nullable);
  auto it = std::find_if(
    module.tables.begin(),
    module.tables.end(),
    [&](std::unique_ptr<Table>& table) { return table->type == funcref; });
  if (it == module.tables.end()) {
    // There is no indirect function table, so we will create one lazily.
    return;
  }

  dispatchTable = it->get();
  ModuleUtils::iterTableSegments(
    module, dispatchTable->name, [&](ElementSegment* segment) {
      dispatchTableSegments.push_back(segment);
    });

  if (dispatchTableSegments.empty()) {
    // There are no dispatch segments, so we will lazily create one and start
    // filling it at index 0.
    dispatchBase = {dispatchTable->name, Name(), 0};
  } else if (dispatchTableSegments.size() == 1 &&
             dispatchTableSegments[0]->type == funcref &&
             !dispatchTableSegments[0]->offset->is<Const>()) {
    // If there is exactly one table segment and that segment has a non-constant
    // offset, append new items to the end of that segment. In all other cases,
    // append new items at constant offsets after all existing items at constant
    // offsets.
    assert(dispatchTableSegments[0]->offset->is<GlobalGet>() &&
           "Unexpected initializer instruction");
    dispatchSegment = dispatchTableSegments[0];
    dispatchBase = {dispatchTable->name,
                    dispatchTableSegments[0]->offset->cast<GlobalGet>()->name,
                    0};
  } else {
    // Finds the segment with the highest occupied table slot so that new items
    // can be inserted contiguously at the end of it without accidentally
    // overwriting any other items. TODO: be more clever about filling gaps in
    // the table, if that is ever useful.
    Index maxIndex = 0;
    for (auto& segment : dispatchTableSegments) {
      assert(segment->offset->is<Const>() &&
             "Unexpected non-const segment offset with multiple segments");
      Index segmentBase = segment->offset->cast<Const>()->value.getInteger();
      if (segmentBase + segment->data.size() >= maxIndex) {
        maxIndex = segmentBase + segment->data.size();
        dispatchSegment = segment;
        dispatchBase = {dispatchTable->name, Name(), segmentBase};
      }
    }
  }

  // Initialize funcIndices with the functions already in the table.
  forEachElement(module,
                 [&](Name table, Name base, Index offset, Expression* elem) {
                   if (auto* func = elem->dynCast<RefFunc>()) {
                     addSlot(func->func, {table, base, offset});
                   }
                 });
}

Table* TableSlotManager::makeTable() {
  // Because the dispatch table will be imported in secondary modules, its name
  // should not collide with any existing tables in primary and secondary
  // modules.
  std::unordered_set<Name> secondaryTableNames;
  for (auto& secondary : secondaries) {
    for (auto& table : secondary->tables) {
      secondaryTableNames.insert(table->name);
    }
  }
  Name name = Names::getValidName("0", [&](Name test) {
    if (module.getTableOrNull(test)) {
      return false;
    }
    if (secondaryTableNames.contains(test)) {
      return false;
    }
    return true;
  });
  return module.addTable(Builder::makeTable(name));
}

ElementSegment* TableSlotManager::makeElementSegment() {
  Builder builder(module);
  Expression* offset =
    builder.makeConst(Literal::makeFromInt32(0, dispatchTable->addressType));
  return module.addElementSegment(Builder::makeElementSegment(
    Names::getValidElementSegmentName(module, Name::fromInt(0)),
    dispatchTable->name,
    offset));
}

TableSlotManager::Slot TableSlotManager::getSlot(Name func, HeapType type) {
  auto slotIt = funcIndices.find(func);
  if (slotIt != funcIndices.end()) {
    return slotIt->second;
  }

  // If there are no segments yet, allocate one.
  if (dispatchSegment == nullptr) {
    if (dispatchTable == nullptr) {
      dispatchTable = makeTable();
      dispatchBase = {dispatchTable->name, Name(), 0};
    }

    // None of the existing segments should refer to the dispatch table
    assert(std::all_of(module.elementSegments.begin(),
                       module.elementSegments.end(),
                       [&](std::unique_ptr<ElementSegment>& segment) {
                         return segment->table != dispatchTable->name;
                       }));

    dispatchSegment = makeElementSegment();
  }

  Slot newSlot = {dispatchBase.tableName,
                  dispatchBase.global,
                  dispatchBase.index + Index(dispatchSegment->data.size())};

  Builder builder(module);
  auto funcType = Type(type, NonNullable, Inexact);
  dispatchSegment->data.push_back(builder.makeRefFunc(func, funcType));

  addSlot(func, newSlot);
  if (dispatchTable->initial <= newSlot.index) {
    dispatchTable->initial = newSlot.index + 1;
    // TODO: handle the dispatch table not being the dylink table (#3823)
    if (module.dylinkSection) {
      module.dylinkSection->tableSize = dispatchTable->initial;
    }
  }
  if (dispatchTable->max <= newSlot.index) {
    dispatchTable->max = newSlot.index + 1;
  }
  return newSlot;
}

struct ModuleSplitter {
  const Config& config;
  std::vector<std::unique_ptr<Module>> secondaries;

  Module& primary;

  std::unordered_set<Name> primaryFuncs;
  std::unordered_set<Name> allSecondaryFuncs;
  std::unordered_map<Name, Index> funcToSecondaryIndex;

  TableSlotManager tableManager;

  Names::MinifiedNameGenerator minified;

  // Map from internal function names to (one of) their corresponding export
  // names.
  std::unordered_map<Name, Name> exportedPrimaryFuncs;

  // Map from <Kind, InternalName> to their corresponding export names for
  // non-function items.
  std::unordered_map<std::pair<ExternalKind, Name>, Name> exportedPrimaryItems;

  // For each table, map placeholder indices to the names of the functions they
  // replace.
  std::unordered_map<Name, std::map<size_t, Name>> placeholderMap;

  // Map from original secondary function name to its trampoline
  std::unordered_map<Name, Name> trampolineMap;

  void shareDispatchTable(Module* secondary);

  // Initialization helpers
  static std::unique_ptr<Module> initSecondary(const Module& primary);
  static std::unordered_map<Name, Name>
  initExportedPrimaryFuncs(const Module& primary);
  static std::unordered_map<std::pair<ExternalKind, Name>, Name>
  initExportedPrimaryItems(const Module& primary);

  // Other helpers
  void exportImportFunction(Name func, const std::set<Module*>& modules);
  void makeImportExport(Importable& primaryItem,
                        Importable& secondaryItem,
                        const std::string& genericExportName,
                        ExternalKind kind);
  Name getTrampoline(Name funcName);

  // Main splitting steps
  void classifyFunctions();
  void moveSecondaryFunctions();
  void thunkExportedSecondaryFunctions();
  void shareImportableItems();
  void indirectReferencesToSecondaryFunctions();
  void indirectCallsToSecondaryFunctions();
  void exportImportCalledPrimaryFunctions();
  void setupTablePatching();

  ModuleSplitter(Module& primary, const Config& config)
    : config(config), primary(primary), tableManager(primary, secondaries),
      exportedPrimaryFuncs(initExportedPrimaryFuncs(primary)),
      exportedPrimaryItems(initExportedPrimaryItems(primary)) {
    classifyFunctions();
    moveSecondaryFunctions();
    thunkExportedSecondaryFunctions();
    shareImportableItems();
    indirectReferencesToSecondaryFunctions();
    indirectCallsToSecondaryFunctions();
    exportImportCalledPrimaryFunctions();
    setupTablePatching();
  }
};

std::unique_ptr<Module> ModuleSplitter::initSecondary(const Module& primary) {
  // Create the secondary module and copy trivial properties.
  auto secondary = std::make_unique<Module>();
  secondary->features = primary.features;
  secondary->hasFeaturesSection = primary.hasFeaturesSection;
  return secondary;
}

void ModuleSplitter::classifyFunctions() {
  // Find functions that refer to data or element segments. These functions must
  // remain in the primary module because segments cannot be exported to be
  // accessed from the secondary module.
  //
  // TODO: Investigate other options, such as moving the segments to the
  // secondary module or replacing the segment-using instructions in the
  // secondary module with calls to imports.
  ModuleUtils::ParallelFunctionAnalysis<std::vector<Name>>
    segmentReferrerCollector(
      primary, [&](Function* func, std::vector<Name>& segmentReferrers) {
        if (func->imported()) {
          return;
        }

        struct SegmentReferrerCollector
          : PostWalker<SegmentReferrerCollector,
                       UnifiedExpressionVisitor<SegmentReferrerCollector>> {
          bool hasSegmentReference = false;

          void visitExpression(Expression* curr) {

#define DELEGATE_ID curr->_id

#define DELEGATE_START(id) [[maybe_unused]] auto* cast = curr->cast<id>();
#define DELEGATE_GET_FIELD(id, field) cast->field
#define DELEGATE_FIELD_TYPE(id, field)
#define DELEGATE_FIELD_HEAPTYPE(id, field)
#define DELEGATE_FIELD_CHILD(id, field)
#define DELEGATE_FIELD_OPTIONAL_CHILD(id, field)
#define DELEGATE_FIELD_INT(id, field)
#define DELEGATE_FIELD_LITERAL(id, field)
#define DELEGATE_FIELD_NAME(id, field)
#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, field)
#define DELEGATE_FIELD_SCOPE_NAME_USE(id, field)
#define DELEGATE_FIELD_ADDRESS(id, field)

#define DELEGATE_FIELD_NAME_KIND(id, field, kind)                              \
  if (kind == ModuleItemKind::DataSegment ||                                   \
      kind == ModuleItemKind::ElementSegment) {                                \
    hasSegmentReference = true;                                                \
  }

#include "wasm-delegations-fields.def"
          }
        };
        SegmentReferrerCollector collector;
        collector.walkFunction(func);
        if (collector.hasSegmentReference) {
          segmentReferrers.push_back(func->name);
        }
      });

  std::unordered_set<Name> segmentReferrers;
  for (auto& [_, referrers] : segmentReferrerCollector.map) {
    segmentReferrers.insert(referrers.begin(), referrers.end());
  }

  std::unordered_set<Name> configSecondaryFuncs;
  for (auto& funcs : config.secondaryFuncs) {
    configSecondaryFuncs.insert(funcs.begin(), funcs.end());
  }
  for (auto& func : primary.functions) {
    if (func->imported() || !configSecondaryFuncs.contains(func->name) ||
        segmentReferrers.contains(func->name)) {
      primaryFuncs.insert(func->name);
    } else {
      assert(func->name != primary.start && "The start function must be kept");
      allSecondaryFuncs.insert(func->name);
    }
  }
}

std::unordered_map<Name, Name>
ModuleSplitter::initExportedPrimaryFuncs(const Module& primary) {
  std::unordered_map<Name, Name> functionExportNames;
  for (auto& ex : primary.exports) {
    if (ex->kind == ExternalKind::Function) {
      functionExportNames[*ex->getInternalName()] = ex->name;
    }
  }
  return functionExportNames;
}

std::unordered_map<std::pair<ExternalKind, Name>, Name>
ModuleSplitter::initExportedPrimaryItems(const Module& primary) {
  std::unordered_map<std::pair<ExternalKind, Name>, Name> exports;
  for (auto& ex : primary.exports) {
    if (ex->kind != ExternalKind::Function) {
      if (auto* name = ex->getInternalName()) {
        exports[std::make_pair(ex->kind, *name)] = ex->name;
      }
    }
  }
  return exports;
}

void ModuleSplitter::makeImportExport(Importable& primaryItem,
                                      Importable& secondaryItem,
                                      const std::string& genericExportName,
                                      ExternalKind kind) {
  secondaryItem.name = primaryItem.name;
  secondaryItem.hasExplicitName = primaryItem.hasExplicitName;
  secondaryItem.module = config.importNamespace;
  auto exportIt = exportedPrimaryItems.find({kind, primaryItem.name});
  if (exportIt != exportedPrimaryItems.end()) {
    secondaryItem.base = exportIt->second;
  } else {
    std::string baseName =
      config.newExportPrefix +
      (config.minimizeNewExportNames ? minified.getName() : genericExportName);
    Name exportName = Names::getValidExportName(primary, baseName);
    primary.addExport(
      std::make_unique<Export>(exportName, kind, primaryItem.name));
    secondaryItem.base = exportName;
    exportedPrimaryItems[{kind, primaryItem.name}] = exportName;
  }
}

void ModuleSplitter::exportImportFunction(Name funcName,
                                          const std::set<Module*>& modules) {
  Name exportName;
  // If the function is already exported, use the existing export name.
  // Otherwise, create a new export for it.
  auto exportIt = exportedPrimaryFuncs.find(funcName);
  if (exportIt != exportedPrimaryFuncs.end()) {
    exportName = exportIt->second;
  } else {
    if (config.minimizeNewExportNames) {
      do {
        exportName = config.newExportPrefix + minified.getName();
      } while (primary.getExportOrNull(exportName) != nullptr);
    } else {
      exportName = Names::getValidExportName(
        primary, config.newExportPrefix + funcName.toString());
    }
    primary.addExport(
      Builder::makeExport(exportName, funcName, ExternalKind::Function));
    exportedPrimaryFuncs[funcName] = exportName;
  }
  // Import the function if it is not already imported into the secondary
  // module.
  for (auto* secondary : modules) {
    if (secondary->getFunctionOrNull(funcName) == nullptr) {
      auto primaryFunc = primary.getFunction(funcName);
      auto func = Builder::makeFunction(funcName, primaryFunc->type, {});
      func->hasExplicitName = primaryFunc->hasExplicitName;
      func->module = config.importNamespace;
      func->base = exportName;
      func->type = func->type.withInexactIfNoCustomDescs(secondary->features);
      secondary->addFunction(std::move(func));
    }
  }
}

void ModuleSplitter::moveSecondaryFunctions() {
  // Move the specified functions from the primary to the secondary modules.
  for (auto& funcNames : config.secondaryFuncs) {
    auto secondary = initSecondary(primary);
    for (auto funcName : funcNames) {
      if (allSecondaryFuncs.contains(funcName)) {
        auto* func = primary.getFunction(funcName);
        ModuleUtils::copyFunction(func, *secondary);
        primary.removeFunction(funcName);
        funcToSecondaryIndex[funcName] = secondaries.size();
      }
    }
    secondaries.push_back(std::move(secondary));
  }
}

Name ModuleSplitter::getTrampoline(Name funcName) {
  auto [it, inserted] = trampolineMap.insert({funcName, Name()});
  if (!inserted) {
    return it->second;
  }

  Builder builder(primary);
  Module& secondary = *secondaries.at(funcToSecondaryIndex.at(funcName));
  auto* oldFunc = secondary.getFunction(funcName);
  auto trampoline = Names::getValidFunctionName(
    primary, std::string("trampoline_") + funcName.toString());
  it->second = trampoline;

  // Generate the call and the function. We generate a direct call here, but
  // this will be converted to a call_indirect in
  // indirectCallsToSecondaryFunctions.
  std::vector<Expression*> args;
  for (Index i = 0; i < oldFunc->getNumParams(); i++) {
    args.push_back(builder.makeLocalGet(i, oldFunc->getLocalType(i)));
  }
  auto* call = builder.makeCall(funcName, args, oldFunc->getResults());

  auto func = builder.makeFunction(trampoline, oldFunc->type, {}, call);
  func->hasExplicitName = oldFunc->hasExplicitName;
  primary.addFunction(std::move(func));
  primaryFuncs.insert(trampoline);
  return trampoline;
}

void ModuleSplitter::shareDispatchTable(Module* secondary) {
  assert(tableManager.dispatchTable);
  auto secondaryTable =
    secondary->getTableOrNull(tableManager.dispatchTable->name);
  if (secondaryTable) {
    // In case it's already in the secondary module, sync the initial/max
    secondaryTable->initial = tableManager.dispatchTable->initial;
    secondaryTable->max = tableManager.dispatchTable->max;
  } else {
    secondaryTable =
      ModuleUtils::copyTable(tableManager.dispatchTable, *secondary);
    makeImportExport(*tableManager.dispatchTable,
                     *secondaryTable,
                     "table",
                     ExternalKind::Table);
  }
  if (tableManager.dispatchBase.global) {
    auto* primaryGlobal = primary.getGlobal(tableManager.dispatchBase.global);
    auto* secondaryGlobal =
      secondary->getGlobalOrNull(tableManager.dispatchBase.global);
    if (!secondaryGlobal) {
      secondaryGlobal = ModuleUtils::copyGlobal(primaryGlobal, *secondary);
      makeImportExport(
        *primaryGlobal, *secondaryGlobal, "global", ExternalKind::Global);
    }
  }
}

void ModuleSplitter::thunkExportedSecondaryFunctions() {
  // Update exports of secondary functions in the primary module to export
  // wrapper functions that indirectly call the secondary functions. We are
  // adding secondary function names to the primary table here, but they will be
  // replaced with placeholder functions later along with any references to
  // secondary functions that were already in the table.
  Builder builder(primary);
  for (auto& ex : primary.exports) {
    if (ex->kind != ExternalKind::Function ||
        !allSecondaryFuncs.contains(*ex->getInternalName())) {
      continue;
    }
    Name trampoline = getTrampoline(*ex->getInternalName());
    ex->setInternalName(trampoline);
  }
}

void ModuleSplitter::shareImportableItems() {

  struct UsedNames {
    std::unordered_set<Name> globals;
    std::unordered_set<Name> memories;
    std::unordered_set<Name> tables;
    std::unordered_set<Name> tags;
  };

  auto walkSegments = [](auto& walker, Module* module) {
    walker.setModule(module);
    for (auto& curr : module->elementSegments) {
      if (curr->offset) {
        walker.walk(curr->offset);
      }
      for (auto* item : curr->data) {
        walker.walk(item);
      }
    }
    for (auto& curr : module->dataSegments) {
      if (curr->offset) {
        walker.walk(curr->offset);
      }
    }
  };

  struct NameCollector
    : public PostWalker<NameCollector,
                        UnifiedExpressionVisitor<NameCollector>> {
    UsedNames& used;
    NameCollector(UsedNames& used) : used(used) {}

    void visitExpression(Expression* curr) {
#define DELEGATE_ID curr->_id
#define DELEGATE_START(id) [[maybe_unused]] auto* cast = curr->cast<id>();
#define DELEGATE_GET_FIELD(id, field) cast->field
#define DELEGATE_FIELD_TYPE(id, field)
#define DELEGATE_FIELD_HEAPTYPE(id, field)
#define DELEGATE_FIELD_CHILD(id, field)
#define DELEGATE_FIELD_INT(id, field)
#define DELEGATE_FIELD_LITERAL(id, field)
#define DELEGATE_FIELD_NAME(id, field)
#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, field)
#define DELEGATE_FIELD_SCOPE_NAME_USE(id, field)
#define DELEGATE_FIELD_ADDRESS(id, field)

#define DELEGATE_FIELD_NAME_KIND(id, field, kind)                              \
  if (cast->field.is()) {                                                      \
    switch (kind) {                                                            \
      case ModuleItemKind::Table:                                              \
        used.tables.insert(cast->field);                                       \
        break;                                                                 \
      case ModuleItemKind::Memory:                                             \
        used.memories.insert(cast->field);                                     \
        break;                                                                 \
      case ModuleItemKind::Global:                                             \
        used.globals.insert(cast->field);                                      \
        break;                                                                 \
      case ModuleItemKind::Tag:                                                \
        used.tags.insert(cast->field);                                         \
        break;                                                                 \
      case ModuleItemKind::Function:                                           \
      case ModuleItemKind::DataSegment:                                        \
      case ModuleItemKind::ElementSegment:                                     \
      case ModuleItemKind::Invalid:                                            \
        break;                                                                 \
    }                                                                          \
  }

#include "wasm-delegations-fields.def"
    }
  };

  // Given a module, collect names used in the module
  auto getUsedNames = [&](Module& module) {
    UsedNames used;
    ModuleUtils::ParallelFunctionAnalysis<UsedNames> nameCollector(
      module, [&](Function* func, UsedNames& used) {
        if (!func->imported()) {
          NameCollector(used).walk(func->body);
        }
      });

    for (auto& [_, funcUsed] : nameCollector.map) {
      used.globals.insert(funcUsed.globals.begin(), funcUsed.globals.end());
      used.memories.insert(funcUsed.memories.begin(), funcUsed.memories.end());
      used.tables.insert(funcUsed.tables.begin(), funcUsed.tables.end());
      used.tags.insert(funcUsed.tags.begin(), funcUsed.tags.end());
    }

    NameCollector collector(used);
    // We shouldn't use collector.walkModuleCode here, because we don't want to
    // walk global initializers. At this point, all globals are still in the
    // primary module, so if we walk global initializers here, other globals
    // appearing in their initializers will all be marked as used in the primary
    // module, which is not what we want.
    //
    // For example, we have (global $a i32 (global.get $b)). Because $a is at
    // this point still in the primary module, $b will be marked as "used" in
    // the primary module. But $a can be moved to a secondary module later if it
    // is used exclusively by that module. Then $b can be also moved, in case it
    // doesn't have other uses. But if it is marked as "used" in the primary
    // module, it can't.
    walkSegments(collector, &module);
    for (auto& segment : module.dataSegments) {
      if (segment->isActive()) {
        used.memories.insert(segment->memory);
      }
    }
    for (auto& segment : module.elementSegments) {
      if (segment->isActive()) {
        used.tables.insert(segment->table);
      }
    }

    // If primary module has exports, they are "used" in it. Secondary modules
    // don't have exports, so this only applies to the primary module.
    for (auto& ex : module.exports) {
      switch (ex->kind) {
        case ExternalKind::Global:
          used.globals.insert(*ex->getInternalName());
          break;
        case ExternalKind::Memory:
          used.memories.insert(*ex->getInternalName());
          break;
        case ExternalKind::Table:
          used.tables.insert(*ex->getInternalName());
          break;
        case ExternalKind::Tag:
          used.tags.insert(*ex->getInternalName());
          break;
        default:
          break;
      }
    }

    // We need to assume the dispatch table and its base global are used in the
    // primary module, because we will create segments there later.
    if (&module == &primary) {
      if (tableManager.dispatchTable) {
        used.tables.insert(tableManager.dispatchTable->name);
      }
      if (tableManager.dispatchBase.global) {
        used.globals.insert(tableManager.dispatchBase.global);
      }
    }

    // Compute the transitive closure of globals referenced in other globals'
    // initializers. Since globals can reference other globals, we must ensure
    // that if a global is used in a module, all its dependencies are also
    // marked as used.
    UniqueNonrepeatingDeferredQueue<Name> worklist;
    for (auto global : used.globals) {
      worklist.push(global);
    }
    while (!worklist.empty()) {
      Name name = worklist.pop();
      // At this point all globals are still in the primary module, so this
      // exists
      auto* global = primary.getGlobal(name);
      if (!global->imported() && global->init) {
        for (auto* get : FindAll<GlobalGet>(global->init).list) {
          worklist.push(get->name);
          used.globals.insert(get->name);
        }
      }
    }
    return used;
  };

  UsedNames primaryUsed = getUsedNames(primary);
  std::vector<UsedNames> secondaryUsed;
  for (auto& secondaryPtr : secondaries) {
    secondaryUsed.push_back(getUsedNames(*secondaryPtr));
  }

  // If custom-descirptors is enabled, global initializers can trap. Trapping
  // globals should stay in the primary module to preserve the trapping behavior
  // upon instantiation.
  if (primary.features.hasCustomDescriptors()) {
    for (auto& global : primary.globals) {
      if (global->init &&
          EffectAnalyzer(config.passOptions, primary, global->init)
            .hasUnremovableSideEffects()) {
        primaryUsed.globals.insert(global->name);
      }
    }
  }

  // Given a name and module item kind, returns the list of secondary modules
  // using that name
  auto getUsingSecondaries = [&](const Name& name, auto UsedNames::* field) {
    std::vector<Module*> usingModules;
    for (size_t i = 0; i < secondaries.size(); ++i) {
      if ((secondaryUsed[i].*field).contains(name)) {
        usingModules.push_back(secondaries[i].get());
      }
    }
    return usingModules;
  };

  // Share module items with secondary modules.
  // 1. Only share an item with the modules that use it
  // 2. If an item is used by only a single secondary module, move the item to
  //    that secondary module. If an item is used by multiple modules (including
  //    the primary and secondary modules), export the item from the primary and
  //    import it from the using secondary modules.

  std::vector<Name> memoriesToRemove;
  for (auto& memory : primary.memories) {
    auto usingSecondaries =
      getUsingSecondaries(memory->name, &UsedNames::memories);
    bool inPrimary = primaryUsed.memories.contains(memory->name);

    if (!inPrimary && usingSecondaries.empty()) {
      memoriesToRemove.push_back(memory->name);
    } else if (!inPrimary && usingSecondaries.size() == 1) {
      auto* secondary = usingSecondaries[0];
      ModuleUtils::copyMemory(memory.get(), *secondary);
      memoriesToRemove.push_back(memory->name);
    } else {
      for (auto* secondary : usingSecondaries) {
        auto* secondaryMemory =
          ModuleUtils::copyMemory(memory.get(), *secondary);
        makeImportExport(
          *memory, *secondaryMemory, "memory", ExternalKind::Memory);
      }
    }
  }
  for (auto& name : memoriesToRemove) {
    primary.removeMemory(name);
  }

  std::vector<Name> tablesToRemove;
  for (auto& table : primary.tables) {
    auto usingSecondaries =
      getUsingSecondaries(table->name, &UsedNames::tables);
    bool inPrimary = primaryUsed.tables.contains(table->name);

    if (!inPrimary && usingSecondaries.empty()) {
      tablesToRemove.push_back(table->name);
    } else if (!inPrimary && usingSecondaries.size() == 1) {
      auto* secondary = usingSecondaries[0];
      assert(!secondary->getTableOrNull(table->name));
      ModuleUtils::copyTable(table.get(), *secondary);
      tablesToRemove.push_back(table->name);
    } else {
      for (auto* secondary : usingSecondaries) {
        auto* secondaryTable = ModuleUtils::copyTable(table.get(), *secondary);
        makeImportExport(*table, *secondaryTable, "table", ExternalKind::Table);
      }
    }
  }
  for (auto& name : tablesToRemove) {
    primary.removeTable(name);
  }

  std::vector<Name> globalsToRemove;
  for (auto& global : primary.globals) {
    if (global->mutable_) {
      assert(primary.features.hasMutableGlobals() &&
             "TODO: add wrapper functions for disallowed mutable globals");
    }

    auto usingSecondaries =
      getUsingSecondaries(global->name, &UsedNames::globals);
    bool inPrimary = primaryUsed.globals.contains(global->name);

    if (!inPrimary && usingSecondaries.empty()) {
      globalsToRemove.push_back(global->name);
    } else if (!inPrimary && usingSecondaries.size() == 1) {
      auto* secondary = usingSecondaries[0];
      ModuleUtils::copyGlobal(global.get(), *secondary);
      globalsToRemove.push_back(global->name);
    } else {
      for (auto* secondary : usingSecondaries) {
        auto* secondaryGlobal =
          ModuleUtils::copyGlobal(global.get(), *secondary);
        makeImportExport(
          *global, *secondaryGlobal, "global", ExternalKind::Global);
      }
    }
  }
  for (auto& name : globalsToRemove) {
    primary.removeGlobal(name);
  }

  std::vector<Name> tagsToRemove;
  for (auto& tag : primary.tags) {
    auto usingSecondaries = getUsingSecondaries(tag->name, &UsedNames::tags);
    bool inPrimary = primaryUsed.tags.contains(tag->name);

    if (!inPrimary && usingSecondaries.empty()) {
      tagsToRemove.push_back(tag->name);
    } else if (!inPrimary && usingSecondaries.size() == 1) {
      auto* secondary = usingSecondaries[0];
      ModuleUtils::copyTag(tag.get(), *secondary);
      tagsToRemove.push_back(tag->name);
    } else {
      for (auto* secondary : usingSecondaries) {
        auto* secondaryTag = ModuleUtils::copyTag(tag.get(), *secondary);
        makeImportExport(*tag, *secondaryTag, "tag", ExternalKind::Tag);
      }
    }
  }
  for (auto& name : tagsToRemove) {
    primary.removeTag(name);
  }
}

void ModuleSplitter::indirectReferencesToSecondaryFunctions() {
  // Turn references to secondary functions into references to thunks that
  // perform a direct call to the original referent. The direct calls in the
  // thunks will be handled like all other cross-module calls later, in
  // |indirectCallsToSecondaryFunctions|.
  struct Gatherer : public PostWalker<Gatherer> {
    ModuleSplitter& parent;

    Gatherer(ModuleSplitter& parent) : parent(parent) {}

    // Collect RefFuncs in a map from the function name to all RefFuncs that
    // refer to it. We only collect this for secondary funcs.
    InsertOrderedMap<Name, std::vector<RefFunc*>> map;

    void visitRefFunc(RefFunc* curr) {
      Module* currModule = getModule();
      // Add ref.func to the map when
      // 1. ref.func's target func is in one of the secondary modules and
      // 2. the current module is a different module (either the primary module
      //    or a different secondary module)
      if (parent.allSecondaryFuncs.contains(curr->func) &&
          (currModule == &parent.primary ||
           parent.secondaries.at(parent.funcToSecondaryIndex.at(curr->func))
               .get() != currModule)) {
        map[curr->func].push_back(curr);
      }
    }
  } gatherer(*this);
  gatherer.walkModule(&primary);
  for (auto& secondaryPtr : secondaries) {
    gatherer.walkModule(secondaryPtr.get());
  }

  // Ignore references to secondary functions that occur in the dispatch
  // segments that will contain the imported placeholders. Indirect calls to
  // table slots initialized by those segments will already go to the right
  // place once the secondary module has been loaded and the table has been
  // patched.
  std::unordered_set<RefFunc*> ignore;
  for (auto* segment : tableManager.dispatchTableSegments) {
    for (auto* expr : segment->data) {
      if (auto* ref = expr->dynCast<RefFunc>()) {
        ignore.insert(ref);
      }
    }
  }

  // Fix up what we found: Generate trampolines as described earlier, and apply
  // them.
  Builder builder(primary);
  // Generate the new trampoline function and add it to the module.
  for (auto& [name, refFuncs] : gatherer.map) {
    // Find the relevant (non-ignored) RefFuncs. If there are none, we can skip
    // creating a thunk entirely.
    std::vector<RefFunc*> relevantRefFuncs;
    for (auto* refFunc : refFuncs) {
      assert(refFunc->func == name);
      if (!ignore.contains(refFunc)) {
        relevantRefFuncs.push_back(refFunc);
      }
    }
    if (relevantRefFuncs.empty()) {
      continue;
    }

    Name trampoline = getTrampoline(name);
    // Update RefFuncs to refer to it.
    for (auto* refFunc : relevantRefFuncs) {
      refFunc->func = trampoline;
    }
  }
}

void ModuleSplitter::indirectCallsToSecondaryFunctions() {
  // Update direct calls of secondary functions to be indirect calls of their
  // corresponding table indices instead.
  struct CallIndirector : public PostWalker<CallIndirector> {
    ModuleSplitter& parent;
    std::unordered_set<Module*> dispatchTableUsingSecondaries;
    CallIndirector(ModuleSplitter& parent) : parent(parent) {}
    void visitCall(Call* curr) {
      // Return if the call's target is not in one of the secondary module.
      if (!parent.allSecondaryFuncs.contains(curr->target)) {
        return;
      }
      // Return if the current module is the same module as the call's target,
      // because we don't need a call_indirect within the same module.
      Module* currModule = getModule();
      Module* calleeModule =
        parent.secondaries.at(parent.funcToSecondaryIndex.at(curr->target))
          .get();
      if (currModule == calleeModule) {
        return;
      }

      Builder builder(*currModule);
      auto* func = calleeModule->getFunction(curr->target);
      auto tableSlot =
        parent.tableManager.getSlot(curr->target, func->type.getHeapType());
      replaceCurrent(
        builder.makeCallIndirect(tableSlot.tableName,
                                 tableSlot.makeExpr(parent.primary),
                                 curr->operands,
                                 func->type.getHeapType(),
                                 curr->isReturn));

      // Share the dispatch table with the current module (caller). We share the
      // dispatch table with with calleeModule later in setupTablePathing.
      if (currModule != &parent.primary) {
        dispatchTableUsingSecondaries.insert(currModule);
      }
    }
  };
  CallIndirector callIndirector(*this);
  callIndirector.walkModule(&primary);
  for (auto& secondaryPtr : secondaries) {
    callIndirector.walkModule(secondaryPtr.get());
  }

  for (auto* secondary : callIndirector.dispatchTableUsingSecondaries) {
    shareDispatchTable(secondary);
  }
}

void ModuleSplitter::exportImportCalledPrimaryFunctions() {
  // Find primary functions called/referred to from the secondary modules.
  using CalledPrimaryToModules = std::map<Name, std::set<Module*>>;
  struct CallCollector : PostWalker<CallCollector> {
    const std::unordered_set<Name>& primaryFuncs;
    CalledPrimaryToModules& calledPrimaryToModules;
    CallCollector(const std::unordered_set<Name>& primaryFuncs,
                  CalledPrimaryToModules& calledPrimaryToModules)
      : primaryFuncs(primaryFuncs),
        calledPrimaryToModules(calledPrimaryToModules) {}
    void visitCall(Call* curr) {
      if (primaryFuncs.contains(curr->target)) {
        calledPrimaryToModules[curr->target].insert(getModule());
      }
    }
    void visitRefFunc(RefFunc* curr) {
      if (primaryFuncs.contains(curr->func)) {
        calledPrimaryToModules[curr->func].insert(getModule());
      }
    }
  };

  for (auto& secondaryPtr : secondaries) {
    Module* secondary = secondaryPtr.get();
    ModuleUtils::ParallelFunctionAnalysis<CalledPrimaryToModules> callCollector(
      *secondary,
      [&](Function* func, CalledPrimaryToModules& calledPrimaryToModules) {
        CallCollector(primaryFuncs, calledPrimaryToModules)
          .walkFunctionInModule(func, secondary);
      });

    CalledPrimaryToModules calledPrimaryToModules;
    for (auto& [_, map] : callCollector.map) {
      calledPrimaryToModules.merge(map);
    }

    CallCollector collector(primaryFuncs, calledPrimaryToModules);
    collector.walkModuleCode(secondary);

    // Ensure each called primary function is exported and imported
    for (auto& [func, modules] : calledPrimaryToModules) {
      exportImportFunction(func, modules);
    }
  }
}

void ModuleSplitter::setupTablePatching() {
  if (!tableManager.dispatchTable) {
    return;
  }

  std::map<Module*, std::map<Index, Function*>> moduleToReplacedElems;
  Name fillerName;
  Type fillerType = Type(Signature(Type::none, Type::none), NonNullable, Exact);
  // Replace table references to secondary functions with an imported
  // placeholder that encodes the table index in its name:
  // `importNamespace`.`index`.
  forEachElement(
    primary, [&](Name table, Name, Index index, Expression*& elem) {
      auto* ref = elem->dynCast<RefFunc>();
      if (!ref) {
        return;
      }
      if (!allSecondaryFuncs.contains(ref->func)) {
        return;
      }
      assert(table == tableManager.dispatchTable->name);

      placeholderMap[table][index] = ref->func;
      Index secondaryIndex = funcToSecondaryIndex.at(ref->func);
      Module& secondary = *secondaries.at(secondaryIndex);
      Name secondaryName = config.secondaryNames.at(secondaryIndex);
      auto* secondaryFunc = secondary.getFunction(ref->func);
      moduleToReplacedElems[&secondary][index] = secondaryFunc;

      if (config.usePlaceholders) {
        auto placeholder = std::make_unique<Function>();
        placeholder->module = config.placeholderNamespacePrefix.toString() +
                              "." + secondaryName.toString();
        placeholder->base = std::to_string(index);
        placeholder->name = Names::getValidFunctionName(
          primary, std::string("placeholder_") + placeholder->base.toString());
        placeholder->hasExplicitName = true;
        placeholder->type = secondaryFunc->type.with(Inexact);
        elem =
          Builder(primary).makeRefFunc(placeholder->name, placeholder->type);
        primary.addFunction(std::move(placeholder));

      } else { // !config.usePlaceholders
        if (primary.features.hasReferenceTypes()) {
          // TODO: This can create dispatch element segments with lots of nulls.
          // We should optimize them like we do data segments with zeros.
          elem = Builder(primary).makeRefNull(HeapType::nofunc);
          return;
        }
        // When reference-types is not enabled, we can't use a ref.null. Put a
        // filler function that contains an unreachable.
        if (!fillerName) {
          fillerName = Names::getValidFunctionName(primary, "filler");
          auto filler = Builder::makeFunction(
            fillerName, fillerType, {}, Builder(primary).makeUnreachable());
          filler->hasExplicitName = true;
          primary.addFunction(std::move(filler));
        }
        elem = Builder(primary).makeRefFunc(fillerName, fillerType);
      }
    });

  if (moduleToReplacedElems.size() == 0) {
    // No placeholders to patch out of the table
    return;
  }

  for (auto& [secondaryPtr, replacedElems] : moduleToReplacedElems) {
    Module& secondary = *secondaryPtr;
    shareDispatchTable(&secondary);
    auto* secondaryTable = secondary.getTable(tableManager.dispatchTable->name);

    if (tableManager.dispatchBase.global) {
      assert(tableManager.dispatchTableSegments.size() == 1 &&
             "Unexpected number of segments with non-const base");
      assert(secondary.tables.size() == 1 && secondary.elementSegments.empty());
      // Since addition is not currently allowed in initializer expressions, we
      // need to start the new secondary segment where the primary segment
      // starts. The secondary segment will contain the same primary functions
      // as the primary module except in positions where it needs to overwrite a
      // placeholder function. All primary functions in the table therefore need
      // to be imported into the second module. TODO: use better strategies
      // here, such as using ref.func in the start function or standardizing
      // addition in initializer expressions.
      ElementSegment* primarySeg = tableManager.dispatchTableSegments.front();
      std::vector<Expression*> secondaryElems;
      secondaryElems.reserve(primarySeg->data.size());

      // Copy functions from the primary segment to the secondary segment,
      // replacing placeholders and creating new exports and imports as
      // necessary.
      auto replacement = replacedElems.begin();
      for (Index i = 0;
           i < primarySeg->data.size() && replacement != replacedElems.end();
           ++i) {
        if (replacement->first == i) {
          // primarySeg->data[i] is a placeholder, so use the secondary
          // function.
          auto* func = replacement->second;
          auto* ref = Builder(secondary).makeRefFunc(func->name, func->type);
          secondaryElems.push_back(ref);
          ++replacement;
        } else if (auto* get = primarySeg->data[i]->dynCast<RefFunc>()) {
          exportImportFunction(get->func, {&secondary});
          auto* copied =
            ExpressionManipulator::copy(primarySeg->data[i], secondary);
          secondaryElems.push_back(copied);
        }
      }

      auto offset = ExpressionManipulator::copy(primarySeg->offset, secondary);
      auto secondarySeg = std::make_unique<ElementSegment>(
        secondaryTable->name, offset, secondaryTable->type, secondaryElems);
      secondarySeg->setName(primarySeg->name, primarySeg->hasExplicitName);
      secondary.addElementSegment(std::move(secondarySeg));
      return;
    }

    // Create dispatch table segments in the secondary module to patch in the
    // original functions when it is instantiated.
    Index currBase = replacedElems.begin()->first;
    std::vector<Expression*> currData;
    auto finishSegment = [&]() {
      auto* offset = Builder(secondary).makeConst(
        Literal::makeFromInt32(currBase, secondaryTable->addressType));
      auto secondarySeg = std::make_unique<ElementSegment>(
        secondaryTable->name, offset, secondaryTable->type, currData);
      Name name = Names::getValidElementSegmentName(
        secondary, Name::fromInt(secondary.elementSegments.size()));
      secondarySeg->setName(name, false);
      secondary.addElementSegment(std::move(secondarySeg));
    };
    for (auto curr = replacedElems.begin(); curr != replacedElems.end();
         ++curr) {
      if (curr->first != currBase + currData.size()) {
        finishSegment();
        currBase = curr->first;
        currData.clear();
      }
      auto* func = curr->second;
      currData.push_back(
        Builder(secondary).makeRefFunc(func->name, func->type));
    }
    if (currData.size()) {
      finishSegment();
    }
  }
}

} // anonymous namespace

Results splitFunctions(Module& primary, const Config& config) {
  ModuleSplitter split(primary, config);
  return {std::move(split.secondaries), std::move(split.placeholderMap)};
}

} // namespace wasm::ModuleSplitting
