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

//
// Loads wasm plus a list of functions that are global ctors, i.e.,
// are to be executed. It then executes as many of them as it can,
// applying their changes to memory etc as needed, then writes it. In
// other words, this executes code at compile time to speed up
// startup later.
//

#include <memory>

#include "asmjs/shared-constants.h"
#include "ir/find_all.h"
#include "ir/gc-type-utils.h"
#include "ir/global-utils.h"
#include "ir/import-utils.h"
#include "ir/literal-utils.h"
#include "ir/memory-utils.h"
#include "ir/names.h"
#include "pass.h"
#include "shell-interface.h"
#include "support/colors.h"
#include "support/file.h"
#include "support/insert_ordered.h"
#include "support/small_set.h"
#include "support/string.h"
#include "support/topological_sort.h"
#include "tool-options.h"
#include "wasm-builder.h"
#include "wasm-interpreter.h"
#include "wasm-io.h"
#include "wasm-validator.h"

using namespace wasm;

namespace {

struct FailToEvalException {
  std::string why;
  FailToEvalException(std::string why) : why(why) {}
};

// Check whether a field is both nullable and mutable. This is a useful
// property for breaking cycles of GC data, see below.
bool isNullableAndMutable(Expression* ref, Index fieldIndex) {
  // Find the field for the given reference, and check its properties.
  auto field = GCTypeUtils::getField(ref->type, fieldIndex);
  assert(field);
  return field->type.isNullable() && field->mutable_ == Mutable;
}

// The prefix for a recommendation, so it is aligned properly with the rest of
// the output.
#define RECOMMENDATION "\n       recommendation: "

class EvallingImportResolver : public ImportResolver {
public:
  EvallingImportResolver() : stubLiteral({Literal(0)}) {};

  // Return an unused stub value. We throw FailToEvalException on reading any
  // imported globals. We ignore the type and return an i32 literal since some
  // types can't be created anyway (e.g. ref none).
  Literals* getGlobalOrNull(ImportNames name, Type type) const override {
    return &stubLiteral;
  }

  RuntimeTable* getTableOrNull(ImportNames name,
                               const Table& type) const override {
    throw FailToEvalException{"Imported table access."};
  }

  // We assume that each tag import is distinct. This is wrong if the same tag
  // instantiation is imported twice with different import names.
  Tag* getTagOrNull(ImportNames name,
                    const Signature& signature) const override {
    auto [it, inserted] = importedTags.try_emplace(name, Tag{});
    if (inserted) {
      auto& tag = it->second;
      tag.type = HeapType(signature);
    }

    return &it->second;
  }

private:
  mutable Literals stubLiteral;
  mutable std::unordered_map<ImportNames, Tag> importedTags;
};

class EvallingRuntimeTable : public RuntimeTable {
public:
  // TODO: putting EvallingModuleRunner into its own header would allow us to
  // take an EvallingModuleRunner as input here instead of passing functions.
  EvallingRuntimeTable(Table table,
                       const bool& instanceInitialized,
                       const Module& wasm,
                       std::function<Literal(Name, Type)> makeFuncData)
    : RuntimeTable(table), instanceInitialized(instanceInitialized), wasm(wasm),
      makeFuncData(std::move(makeFuncData)) {}

  void set(std::size_t i, Literal l) override {
    if (instanceInitialized) {
      throw FailToEvalException("tableStore after init: TODO");
    }
  }

  Literal get(std::size_t index) const override {
    // Look through the segments and find the value. Segments can overlap,
    // so we want the last one.
    Expression* value = nullptr;
    for (auto& segment : wasm.elementSegments) {
      if (segment->table != tableDefinition.name) {
        continue;
      }

      Index start;
      // look for the index in this segment. if it has a constant offset, we
      // look in the proper range. if it instead gets a global, we rely on the
      // fact that when not dynamically linking then the table is loaded at
      // offset 0.
      // TODO: This is an Emscripten-specific assumption. We can add an
      // Emscripten-only mode and only make the assumption in that case.
      if (auto* c = segment->offset->dynCast<Const>()) {
        start = c->value.getInteger();
      } else if (segment->offset->is<GlobalGet>()) {
        start = 0;
      } else {
        // TODO: Handle extended consts.
        // wasm spec only allows const and global.get there
        WASM_UNREACHABLE("invalid expr type");
      }
      auto end = start + segment->data.size();
      if (start <= index && index < end) {
        value = segment->data[index - start];
      }
    }

    if (!value) {
      // No segment had a value for this.
      // TODO: Handle non-function tables.
      return Literal::makeNull(HeapTypes::func);
    }
    if (!Properties::isConstantExpression(value)) {
      throw FailToEvalException("tableLoad of non-literal");
    }
    if (auto* r = value->dynCast<RefFunc>()) {
      return makeFuncData(r->func, r->type);
    }
    return Properties::getLiteral(value);
  }

  [[nodiscard]] virtual std::optional<std::size_t> grow(std::size_t delta,
                                                        Literal fill) override {
    throw FailToEvalException("grow table");
  }

  std::size_t size() const override {
    // See set() above, we assume the table is not modified FIXME
    return tableDefinition.initial;
  }

private:
  const bool& instanceInitialized;
  const Module& wasm;
  const std::function<Literal(Name, Type)> makeFuncData;
};

class EvallingModuleRunner : public ModuleRunnerBase<EvallingModuleRunner> {
public:
  EvallingModuleRunner(
    Module& wasm,
    ExternalInterface* externalInterface,
    const bool& instanceInitialized,
    std::map<Name, std::shared_ptr<EvallingModuleRunner>> linkedInstances_ = {})
    : ModuleRunnerBase(
        wasm,
        externalInterface,
        std::make_shared<EvallingImportResolver>(),
        linkedInstances_,
        // TODO: Only use EvallingRuntimeTable for table imports. We can use
        // RealRuntimeTable for non-imported tables.
        [this, &instanceInitialized](Literal initial, Table table) {
          return std::make_unique<EvallingRuntimeTable>(
            table,
            instanceInitialized,
            this->wasm,
            [this](Name name, Type type) { return makeFuncData(name, type); });
        }) {}

  Flow visitGlobalGet(GlobalGet* curr) {
    // Error on reads of imported globals.
    auto* global = wasm.getGlobal(curr->name);
    if (global->imported()) {
      throw FailToEvalException(std::string("read from imported global ") +
                                global->module.toString() + "." +
                                global->base.toString());
    }

    return ModuleRunnerBase<EvallingModuleRunner>::visitGlobalGet(curr);
  }

  Flow visitTableGet(TableGet* curr) {
    // We support tableLoad, below, so that call_indirect works (it calls it
    // internally), but we want to disable table.get for now.
    throw FailToEvalException("TODO: table.get");
  }

  bool allowContNew = true;

  Flow visitContNew(ContNew* curr) {
    if (!allowContNew) {
      throw FailToEvalException("cont.new disallowed");
    }
    return ModuleRunnerBase<EvallingModuleRunner>::visitContNew(curr);
  }

  // This needs to be duplicated from ModuleRunner, unfortunately.
  Literal makeFuncData(Name name, Type type) {
    auto allocation =
      std::make_shared<FuncData>(name, this, [this, name](Literals arguments) {
        return callFunction(name, arguments);
      });
#if __has_feature(leak_sanitizer) || __has_feature(address_sanitizer)
    __lsan_ignore_object(allocation.get());
#endif
    return Literal(allocation, type);
  }
};

// Build an artificial `env` module based on a module's imports, so that the
// interpreter can use correct object instances. It initializes usable global
// imports, and fills the rest with fake values since those are dangerous to
// use. we will fail if dangerous globals are used.
std::unique_ptr<Module> buildEnvModule(Module& wasm) {
  auto env = std::make_unique<Module>();
  env->name = "env";

  // create empty functions with similar signature
  ModuleUtils::iterImportedFunctions(wasm, [&](Function* func) {
    if (func->module == env->name) {
      Builder builder(*env);
      auto* copied = ModuleUtils::copyFunction(func, *env);
      copied->module = Name();
      copied->base = Name();
      copied->body = builder.makeUnreachable();
      env->addExport(
        builder.makeExport(func->base, copied->name, ExternalKind::Function));
    }
  });

  // create an exported memory with the same initial and max size
  ModuleUtils::iterImportedMemories(wasm, [&](Memory* memory) {
    if (memory->module == env->name) {
      auto* copied = ModuleUtils::copyMemory(memory, *env);
      copied->module = Name();
      copied->base = Name();
      env->addExport(Builder(*env).makeExport(
        memory->base, copied->name, ExternalKind::Memory));
    }
  });

  return env;
}

// Whether to ignore external input to the program as it runs. If set, we will
// assume that stdin is empty, that any env vars we try to read are not set,
// that there are not arguments passed to main, etc.
static bool ignoreExternalInput = false;

struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface {
  Module* wasm;
  EvallingModuleRunner* instance;
  std::map<Name, std::shared_ptr<EvallingModuleRunner>> linkedInstances;

  // A representation of the contents of wasm memory as we execute.
  std::unordered_map<Name, std::vector<char>> memories;

  // All the names of globals we've seen in the module. We cannot reuse these.
  // We must track these manually as we will be adding more, and as we do so we
  // also reorder them, so we remove and re-add globals, which means the module
  // itself is not aware of all the globals that belong to it (those that have
  // not yet been re-added are a blind spot for it).
  std::unordered_set<Name> usedGlobalNames;

  // Set to true after we create the instance.
  bool instanceInitialized = false;

  CtorEvalExternalInterface(
    std::map<Name, std::shared_ptr<EvallingModuleRunner>> linkedInstances_ =
      {}) {
    linkedInstances.swap(linkedInstances_);
  }

  // Called when we want to apply the current state of execution to the Module.
  // Until this is called the Module is never changed.
  void applyToModule() {
    clearApplyState();

    // If nothing was ever written to memories then there is nothing to update.
    if (!memories.empty()) {
      applyMemoryToModule();
    }

    applyGlobalsToModule();
  }

  void init(Module& wasm_, EvallingModuleRunner& instance_) override {
    wasm = &wasm_;
    instance = &instance_;
    for (auto& memory : wasm->memories) {
      if (!memory->imported()) {
        std::vector<char> data;
        memories[memory->name] = data;
      }
    }

    for (auto& global : wasm->globals) {
      usedGlobalNames.insert(global->name);
    }
  }

  Literal getImportedFunction(Function* import) override {
    auto f = [import, this](const Literals& arguments) -> Flow {
      Name WASI("wasi_snapshot_preview1");

      if (ignoreExternalInput) {
        if (import->module == WASI) {
          if (import->base == "environ_sizes_get") {
            if (arguments.size() != 2 || arguments[0].type != Type::i32 ||
                import->getResults() != Type::i32) {
              throw FailToEvalException("wasi environ_sizes_get has wrong sig");
            }

            // Write out a count of i32(0) and return __WASI_ERRNO_SUCCESS
            // (0).
            store32(arguments[0].geti32(), 0, wasm->memories[0]->name);
            return {Literal(int32_t(0))};
          }

          if (import->base == "environ_get") {
            if (arguments.size() != 2 || arguments[0].type != Type::i32 ||
                import->getResults() != Type::i32) {
              throw FailToEvalException("wasi environ_get has wrong sig");
            }

            // Just return __WASI_ERRNO_SUCCESS (0).
            return {Literal(int32_t(0))};
          }

          if (import->base == "args_sizes_get") {
            if (arguments.size() != 2 || arguments[0].type != Type::i32 ||
                import->getResults() != Type::i32) {
              throw FailToEvalException("wasi args_sizes_get has wrong sig");
            }

            // Write out an argc of i32(0) and return a __WASI_ERRNO_SUCCESS
            // (0).
            store32(arguments[0].geti32(), 0, wasm->memories[0]->name);
            return {Literal(int32_t(0))};
          }

          if (import->base == "args_get") {
            if (arguments.size() != 2 || arguments[0].type != Type::i32 ||
                import->getResults() != Type::i32) {
              throw FailToEvalException("wasi args_get has wrong sig");
            }

            // Just return __WASI_ERRNO_SUCCESS (0).
            return {Literal(int32_t(0))};
          }

          // Otherwise, we don't recognize this import; continue normally to
          // error.
        }
      }

      std::string extra;
      if (import->module == ENV && import->base == "___cxa_atexit") {
        extra = RECOMMENDATION "build with -s NO_EXIT_RUNTIME=1 so that calls "
                               "to atexit are not emitted";
      } else if (import->module == WASI && !ignoreExternalInput) {
        extra = RECOMMENDATION "consider --ignore-external-input";
      }
      throw FailToEvalException(std::string("call import: ") +
                                import->module.toString() + "." +
                                import->base.toString() + extra);
    };
    // Use a null instance because these are either host functions or imported
    // from unknown sources.
    // TODO: Be more precise about the types we allow these imports to have.
    return Literal(std::make_shared<FuncData>(import->name, nullptr, f),
                   import->type);
  }

  int8_t load8s(Address addr, Name memoryName) override {
    return doLoad<int8_t>(addr, memoryName);
  }
  uint8_t load8u(Address addr, Name memoryName) override {
    return doLoad<uint8_t>(addr, memoryName);
  }
  int16_t load16s(Address addr, Name memoryName) override {
    return doLoad<int16_t>(addr, memoryName);
  }
  uint16_t load16u(Address addr, Name memoryName) override {
    return doLoad<uint16_t>(addr, memoryName);
  }
  int32_t load32s(Address addr, Name memoryName) override {
    return doLoad<int32_t>(addr, memoryName);
  }
  uint32_t load32u(Address addr, Name memoryName) override {
    return doLoad<uint32_t>(addr, memoryName);
  }
  int64_t load64s(Address addr, Name memoryName) override {
    return doLoad<int64_t>(addr, memoryName);
  }
  uint64_t load64u(Address addr, Name memoryName) override {
    return doLoad<uint64_t>(addr, memoryName);
  }
  std::array<uint8_t, 16> load128(Address addr, Name memoryName) override {
    return doLoad<std::array<uint8_t, 16>>(addr, memoryName);
  }

  void store8(Address addr, int8_t value, Name memoryName) override {
    doStore<int8_t>(addr, value, memoryName);
  }
  void store16(Address addr, int16_t value, Name memoryName) override {
    doStore<int16_t>(addr, value, memoryName);
  }
  void store32(Address addr, int32_t value, Name memoryName) override {
    doStore<int32_t>(addr, value, memoryName);
  }
  void store64(Address addr, int64_t value, Name memoryName) override {
    doStore<int64_t>(addr, value, memoryName);
  }
  void store128(Address addr,
                const std::array<uint8_t, 16>& value,
                Name memoryName) override {
    doStore<std::array<uint8_t, 16>>(addr, value, memoryName);
  }

  bool growMemory(Name memoryName,
                  Address /*oldSize*/,
                  Address /*newSize*/) override {
    throw FailToEvalException("grow memory");
  }

  void trap(std::string_view why) override {
    throw FailToEvalException(std::string("trap: ") + std::string(why));
  }

  void hostLimit(std::string_view why) override {
    throw FailToEvalException(std::string("trap: ") + std::string(why));
  }

  void throwException(const WasmException& exn) override {
    std::stringstream ss;
    ss << "exception thrown: " << exn;
    throw FailToEvalException(ss.str());
  }

private:
  // We limit the size of memory to some reasonable amount. We handle memory in
  // a linear/dense manner, so when we see a write to address X we allocate X
  // memory to represent that, and so very high addresses can lead to OOM. In
  // practice, ctor-eval should only run on low addresses anyhow, since static
  // memory tends to be reasonably-sized and mallocs start at the start of the
  // heap, so it's simpler to add an arbitrary limit here to avoid OOMs for now.
  const size_t MaximumMemory = 100 * 1024 * 1024;

  // TODO: handle unaligned too, see shell-interface
  void* getMemory(Address address, Name memoryName, size_t size) {
    auto it = memories.find(memoryName);
    assert(it != memories.end());
    auto& memory = it->second;
    // resize the memory buffer as needed.
    auto max = address + size;
    if (max > memory.size()) {
      if (max > MaximumMemory) {
        throw FailToEvalException("excessively high memory address accessed");
      }
      memory.resize(max);
    }
    return &memory[address];
  }

  template<typename T> void doStore(Address address, T value, Name memoryName) {
    // Use memcpy to avoid UB if unaligned.
    memcpy(getMemory(address, memoryName, sizeof(T)), &value, sizeof(T));
  }

  template<typename T> T doLoad(Address address, Name memoryName) {
    // Use memcpy to avoid UB if unaligned.
    T ret;
    memcpy(&ret, getMemory(address, memoryName, sizeof(T)), sizeof(T));
    return ret;
  }

  // Clear the state of the operation of applying the interpreter's runtime
  // information into the module.
  //
  // This happens each time we apply contents to the module, which is basically
  // once per ctor function, but can be more fine-grained also if we execute a
  // line at a time.
  void clearApplyState() {
    // The process of allocating "defining globals" begins here, from scratch
    // each time (things live before may no longer be).
    definingGlobals.clear();

    // Clear any startup operations as well (which may apply to globals that
    // become no longer live; we'll create new start operations as we need
    // them).
    clearStartBlock();
  }

  void applyMemoryToModule() {
    // Memory must have already been flattened into the standard form: one
    // segment at offset 0, or none.
    auto& memory = wasm->memories[0];
    if (wasm->dataSegments.empty()) {
      Builder builder(*wasm);
      auto curr = builder.makeDataSegment();
      curr->offset =
        builder.makeConst(Literal::makeFromInt32(0, memory->addressType));
      curr->setName(Name::fromInt(0), false);
      curr->memory = memory->name;
      wasm->addDataSegment(std::move(curr));
    }
    auto& segment = wasm->dataSegments[0];
    assert(segment->offset->cast<Const>()->value.getInteger() == 0);

    // Copy the current memory contents after execution into the Module's
    // memory.
    segment->data = memories[memory->name];
  }

  // Serializing GC data requires more work than linear memory, because
  // allocations have an identity, and they are created using struct.new /
  // array.new, which we must emit in a proper location in the wasm. This
  // affects how we serialize globals, which can contain GC data, and also, we
  // use globals to store GC data, so overall the process of computing the
  // globals is where most of the GC logic ends up.
  //
  // The general idea for handling GC data is as follows: After evaluating the
  // code, we end up with some live allocations in the interpreter, which we
  // need to somehow serialize into the wasm module. We will put each such live
  // GC data item into its own "defining global", a global whose purpose is to
  // create and store that data. Each such global is immutable, and has the
  // exact type of the data, for simplicity. Every other reference to that GC
  // data in the interpreter's memory can then be serialized by simply emitting
  // a global.get of that defining global.
  void applyGlobalsToModule() {
    if (!wasm->features.hasGC()) {
      // Without GC, we can simply serialize the globals in place as they are.
      for (const auto& [name, values] : instance->allGlobals) {
        wasm->getGlobal(name)->init = getSerialization(*values);
      }
      return;
    }

    // We need to emit the "defining globals" of GC data before the existing
    // globals, as the normal ones may refer to them. We do this by removing all
    // the existing globals, and then adding them one by one, during which time
    // we call getSerialization() for their init expressions. If their init
    // refes to GC data, then we will allocate a defining global for that data,
    // and refer to it. Put another way, we place the existing globals back into
    // the module one at a time, adding their dependencies as we go.
    auto oldGlobals = std::move(wasm->globals);
    // After clearing the globals vector, clear the map as well.
    wasm->updateMaps();

    for (auto& oldGlobal : oldGlobals) {
      if (oldGlobal->imported()) {
        continue;
      }
      // Serialize the global's value. While doing so, pass in the name of this
      // global, as we may be able to reuse the global as the defining global
      // for the value. See getSerialization() for more details.
      Name name;
      if (!oldGlobal->mutable_ && oldGlobal->type == oldGlobal->init->type) {
        // This has the properties we need of a defining global - immutable and
        // of the precise type - so use it as such.
        name = oldGlobal->name;
      }

      // If the instance has an evalled value here, compute the serialization
      // for it. (If there is no value, then this is a new global we've added
      // during execution, for whom we've already set up a proper serialized
      // value when we created it.)
      auto iter = instance->allGlobals.find(oldGlobal->name);
      if (iter != instance->allGlobals.end()) {
        oldGlobal->init = getSerialization(*iter->second, name);
      }

      // Add the global back to the module.
      wasm->addGlobal(std::move(oldGlobal));
    }

    // Finally, we need to fix up cycles. The serialization we just emitted
    // ignores them, so we can end up with things like this:
    //
    //  (global $a (struct.new $A (global.get $a)))
    //
    // That global refers to an object that should have a self-reference, and
    // the serialization logic simply emits global.gets for all references, so
    // we end up with a situation like this where a global.get refers to a
    // global before it is valid to do so. To fix this up, we can reorder
    // globals as needed, and break up cycles by writing a null in the initial
    // struct.new in the global's definition, and later in the start function we
    // can perform additional struct.sets that cause cycles to form.
    //
    // The existing algorithm here is rather simple: we find things that
    // definitely force a certain order and sort according to them. Then in that
    // order we break forward references with fixups as described above. This is
    // not always the best, as there may be a more optimal order, and we may end
    // up doing more fixups than are absolutely necessary, but this algorithm is
    // simple and works in linear time (or nlogn including the sort). The
    // general problem here is NP-hard (the maximum acyclic subgraph problem),
    // but there are probably greedy algorithms we could consider if we need to
    // do better.

    Builder builder(*wasm);

    // First, find what constraints we have on the ordering of the globals. We
    // will build up a map of each global to the globals it must be before.
    using MustBeBefore = InsertOrderedMap<Name, InsertOrderedSet<Name>>;
    MustBeBefore mustBeBefore;

    for (auto& global : wasm->globals) {
      if (!global->init) {
        continue;
      }

      struct InitScanner : PostWalker<InitScanner> {
        // All the global.gets that we can't fix up by replacing the value with
        // a null and adding a set in the start function. These will be hard
        // constraints on our sorting (if we could fix things up with a null +
        // set then we would not need to reorder).
        InsertOrderedSet<GlobalGet*> unfixableGets;

        void visitGlobalGet(GlobalGet* curr) {
          // Assume this is unfixable, unless we reach the parent and see that
          // it is.
          unfixableGets.insert(curr);
        }

        // Checks if a child is a global.get that we need to handle, and if we
        // can fix it if so. The index is the position of the child in the
        // parent (which is 0 for all array children, as their position does not
        // matter, they all have the same field info).
        void handleChild(Expression* child,
                         Expression* parent,
                         Index fieldIndex = 0) {
          if (!child) {
            return;
          }

          if (auto* get = child->dynCast<GlobalGet>()) {
            if (isNullableAndMutable(parent, fieldIndex)) {
              // We can replace the child with a null, and set the value later
              // (in the start function), so this is not a constraint on our
              // sorting - we'll just fix it up later, and the order won't be
              // an issue.
              unfixableGets.erase(get);
            }
          }
        }

        void visitStructNew(StructNew* curr) {
          Index i = 0;
          for (auto* child : curr->operands) {
            handleChild(child, curr, i++);
          }
        }
        void visitArrayNew(ArrayNew* curr) { handleChild(curr->init, curr); }
        void visitArrayNewFixed(ArrayNewFixed* curr) {
          for (auto* child : curr->values) {
            handleChild(child, curr);
          }
        }
      };

      InitScanner scanner;
      scanner.walk(global->init);

      // Any global.gets that cannot be fixed up are constraints.
      for (auto* get : scanner.unfixableGets) {
        mustBeBefore[global->name];
        mustBeBefore[get->name].insert(global->name);
      }
    }

    if (!mustBeBefore.empty()) {
      auto oldGlobals = std::move(wasm->globals);
      // After clearing the globals vector, clear the map as well.
      wasm->updateMaps();

      std::unordered_map<Name, Index> globalIndexes;
      for (Index i = 0; i < oldGlobals.size(); i++) {
        globalIndexes[oldGlobals[i]->name] = i;
      }
      // Add the globals that had an important ordering, in the right order.
      for (auto global :
           TopologicalSort::sortOf(mustBeBefore.begin(), mustBeBefore.end())) {
        wasm->addGlobal(std::move(oldGlobals[globalIndexes[global]]));
      }
      // Add all other globals after them.
      for (auto& global : oldGlobals) {
        if (global) {
          wasm->addGlobal(std::move(global));
        }
      }
    }

    // After sorting (*), perform the fixups that we need, that is, replace the
    // relevant fields in cycles with a null and prepare a set in the start
    // function.
    //
    // We'll track the set of readable globals as we go (which are the globals
    // we've seen already, and fully finished processing).
    //
    // (*) Note that we may need these fixups even if we didn't need to do any
    //     sorting. There may be a single global with a cycle in it, for
    //     example.
    std::unordered_set<Name> readableGlobals;

    for (auto& global : wasm->globals) {
      if (!global->init) {
        continue;
      }

      struct InitFixer : PostWalker<InitFixer> {
        CtorEvalExternalInterface& evaller;
        std::unique_ptr<Global>& global;
        std::unordered_set<Name>& readableGlobals;

        InitFixer(CtorEvalExternalInterface& evaller,
                  std::unique_ptr<Global>& global,
                  std::unordered_set<Name>& readableGlobals)
          : evaller(evaller), global(global), readableGlobals(readableGlobals) {
        }

        // Handles a child by fixing things up if needed. Returns true if we
        // did in fact fix things up.
        bool handleChild(Expression*& child,
                         Expression* parent,
                         Index fieldIndex = 0) {
          if (!child) {
            return false;
          }

          if (auto* get = child->dynCast<GlobalGet>()) {
            if (!readableGlobals.count(get->name)) {
              // This get cannot be read - it is a global that appears after
              // us - and so we must fix it up, using the method mentioned
              // before (setting it to null now, and later in the start
              // function writing to it).
              assert(isNullableAndMutable(parent, fieldIndex));
              evaller.addStartFixup(
                {global->name, global->type}, fieldIndex, get);
              child =
                Builder(*getModule()).makeRefNull(get->type.getHeapType());
              return true;
            }
          }

          return false;
        }

        // This code will need to be updated for all new GC-creating
        // instructions that we use when serializing GC data, that is, things we
        // put in defining globals. (All other instructions, even constant ones
        // in globals, will simply end up referring to them using a global.get,
        // but will not be referred to. That is, cycles will only appear in
        // defining globals.)

        void visitStructNew(StructNew* curr) {
          Index i = 0;
          for (auto*& child : curr->operands) {
            handleChild(child, curr, i++);
          }
        }
        void visitArrayNew(ArrayNew* curr) {
          if (handleChild(curr->init, curr)) {
            // Handling array.new is tricky as the number of items may be
            // unknown at compile time, so we'd need to loop at runtime. But,
            // in practice we emit an array.new_fixed anyhow, so this should
            // not be needed for now.
            WASM_UNREACHABLE("TODO: ArrayNew in ctor-eval cycles");
          }
        }
        void visitArrayNewFixed(ArrayNewFixed* curr) {
          Index i = 0;
          for (auto*& child : curr->values) {
            handleChild(child, curr, i++);
          }
        }
      };

      InitFixer fixer(*this, global, readableGlobals);
      fixer.setModule(wasm);
      fixer.walk(global->init);

      // Only after we've fully processed this global is it ok to be read from
      // by later globals.
      readableGlobals.insert(global->name);
    }
  }

public:
  // Maps each GC data in the interpreter to its defining global: the global in
  // which it is created, and then all other users of it can just global.get
  // that. For each such global we track its name and type.
  struct DefiningGlobalInfo {
    Name name;
    Type type;
  };
  std::unordered_map<GCData*, DefiningGlobalInfo> definingGlobals;

  // If |possibleDefiningGlobal| is provided, it is the name of a global that we
  // are in the init expression of, and which can be reused as defining global,
  // if the other conditions are suitable.
  //
  // Returns nullptr if we cannot serialize.
  Expression* getSerialization(Literal value,
                               Name possibleDefiningGlobal = Name()) {
    if (value.isContinuation()) {
      return nullptr;
    }

    Builder builder(*wasm);

    // If this is externalized then we want to inspect the inner data, handle
    // that, and emit a ref.externalize around it as needed. To simplify the
    // logic here, we save the original (possible externalized) value, and then
    // look at the internals from here on out.
    Literal original = value;
    if (value.type.isRef() &&
        value.type.getHeapType().isMaybeShared(HeapType::ext)) {
      value = value.internalize();

      // We cannot serialize truly external things, only data and i31s.
      assert(value.isData() ||
             value.type.getHeapType().isMaybeShared(HeapType::i31));
    }

    // GC data (structs and arrays) must be handled with the special global-
    // creating logic later down. But MVP types as well as i31s (even
    // externalized i31s) can be handled by the general makeConstantExpression
    // logic (which knows how to handle externalization, for i31s; and it also
    // can handle string constants).
    if (!value.isData() || value.isString()) {
      return builder.makeConstantExpression(original);
    }

    // This is GC data, which we must handle in a more careful way.
    auto* data = value.getGCData().get();
    assert(data);

    auto type = value.type;
    Name definingGlobalName;

    if (auto it = definingGlobals.find(data); it != definingGlobals.end()) {
      // Use the existing defining global.
      definingGlobalName = it->second.name;
    } else {
      // This is the first usage of this data. Generate a struct.new /
      // array.new for it.
      auto& values = data->values;
      std::vector<Expression*> args;

      // The initial values for this allocation may themselves be GC
      // allocations. Recurse and add globals as necessary. First, pick the
      // global name (note that we must do so first, as we may need to read from
      // definingGlobals to find where this global will be, in the case of a
      // cycle; see below).
      if (possibleDefiningGlobal.is()) {
        // No need to allocate a new global, as we are in the definition of
        // one, which will be the defining global.
        definingGlobals[data] =
          DefiningGlobalInfo{possibleDefiningGlobal, type};
        definingGlobalName = possibleDefiningGlobal;
      } else {
        // Allocate a new defining global.
        definingGlobalName =
          Names::getValidNameGivenExisting("ctor-eval$global", usedGlobalNames);
        usedGlobalNames.insert(definingGlobalName);
        definingGlobals[data] = DefiningGlobalInfo{definingGlobalName, type};
      }

      for (auto& value : values) {
        auto* serialized = getSerialization(value);
        if (!serialized) {
          return nullptr;
        }
        args.push_back(serialized);
      }

      Expression* desc = nullptr;
      if (data->desc.getGCData()) {
        desc = getSerialization(data->desc);
        if (!desc) {
          return nullptr;
        }
      }

      Expression* init;
      auto heapType = type.getHeapType();
      if (heapType.isStruct()) {
        init = builder.makeStructNew(heapType, args, desc);
      } else if (heapType.isArray()) {
        // TODO: for repeated identical values, can use ArrayNew
        init = builder.makeArrayNewFixed(heapType, args);
      } else {
        WASM_UNREACHABLE("bad gc type");
      }

      if (possibleDefiningGlobal.is()) {
        // We didn't need to allocate a new global, as we are in the definition
        // of one, so just return the initialization expression, which will be
        // placed in that global's |init| field.
        return init;
      }

      // There is no existing defining global, so we must allocate a new one.
      //
      // We set the global's init to null temporarily, and we'll fix it up
      // later down after we create the init expression.
      wasm->addGlobal(
        builder.makeGlobal(definingGlobalName, type, init, Builder::Immutable));
    }

    // Refer to this GC allocation by reading from the global that is
    // designated to contain it.
    Expression* ret = builder.makeGlobalGet(definingGlobalName, value.type);
    if (original != value) {
      // The original is externalized.
      assert(original.type.getHeapType().isMaybeShared(HeapType::ext));
      ret = builder.makeRefAs(ExternConvertAny, ret);
    }
    return ret;
  }

  Expression* getSerialization(const Literals& values,
                               Name possibleDefiningGlobal = Name()) {
    if (values.size() > 1) {
      // We do not support multivalues in defining globals, which store GC refs.
      assert(possibleDefiningGlobal.isNull());
      std::vector<Expression*> children;
      for (const auto& value : values) {
        auto* serialized = getSerialization(value);
        if (!serialized) {
          return nullptr;
        }
        children.push_back(serialized);
      }
      return Builder(*wasm).makeTupleMake(children);
    }
    assert(values.size() == 1);
    return getSerialization(values[0], possibleDefiningGlobal);
  }

  // This is called when we hit a cycle in setting up defining globals. For
  // example, if the data we want to emit is
  //
  //    global globalA = new A{ field = &A }; // A has a reference to itself
  //
  // then we'll emit
  //
  //    global globalA = new A{ field = null };
  //
  // and put this in the start function:
  //
  //   globalA.field = globalA;
  //
  // The parameters here are a global and a field index to that global, and the
  // global we want to assign to it, that is, our goal is to have
  //
  //  global[index] = valueGlobal
  //
  // run during the start function.
  void addStartFixup(DefiningGlobalInfo global, Index index, GlobalGet* value) {
    if (!startBlock) {
      createStartBlock();
    }

    Builder builder(*wasm);
    auto* getGlobal = builder.makeGlobalGet(global.name, global.type);

    Expression* set;
    if (global.type.isStruct()) {
      set =
        builder.makeStructSet(index, getGlobal, value, MemoryOrder::Unordered);
    } else {
      set = builder.makeArraySet(getGlobal,
                                 builder.makeConst(int32_t(index)),
                                 value,
                                 MemoryOrder::Unordered);
    }

    (*startBlock)->list.push_back(set);
  }

  // A block in the start function where we put the operations we need to occur
  // during startup.
  std::optional<Block*> startBlock;

  void createStartBlock() {
    Builder builder(*wasm);
    startBlock = builder.makeBlock();
    if (wasm->start.is()) {
      // Put our block before any user start code.
      auto* existingStart = wasm->getFunction(wasm->start);
      existingStart->body =
        builder.makeSequence(*startBlock, existingStart->body);
    } else {
      // Make a new start function.
      wasm->start = Names::getValidFunctionName(*wasm, "start");
      wasm->addFunction(builder.makeFunction(
        wasm->start, Signature{Type::none, Type::none}, {}, *startBlock));
    }
  }

  void clearStartBlock() {
    if (startBlock) {
      (*startBlock)->list.clear();
    }
  }
};

// Whether to emit informative logging to stdout about the eval process.
static bool quiet = false;

// The outcome of evalling a ctor is one of three states:
//
// 1. We failed to eval it completely (but perhaps we succeeded partially). In
//    that case the std::optional here contains nothing.
// 2. We evalled it completely, and it is a function with no return value, so
//    it contains an empty Literals.
// 3. We evalled it completely, and it is a function with a return value, so
//    it contains Literals with those results.
using EvalCtorOutcome = std::optional<Literals>;

// Eval a single ctor function. Returns whether we succeeded to completely
// evaluate the ctor (which means that the caller can proceed to try to eval
// further ctors if there are any), and if we did, the results if the function
// returns any.
EvalCtorOutcome evalCtor(EvallingModuleRunner& instance,
                         CtorEvalExternalInterface& interface,
                         Name funcName,
                         Name exportName) {
  auto& wasm = instance.wasm;
  auto* func = wasm.getFunction(funcName);
  if (func->imported()) {
    // We cannot evaluate an import.
    if (!quiet) {
      std::cout << "  ...stopping since could not eval: call import: "
                << func->module.toString() << "." << func->base.toString()
                << '\n';
    }
    return EvalCtorOutcome();
  }

  // We don't know the values of parameters, so give up if there are any, unless
  // we are ignoring them.
  if (func->getNumParams() > 0 && !ignoreExternalInput) {
    if (!quiet) {
      std::cout << "  ...stopping due to params\n";
      std::cout << RECOMMENDATION "consider --ignore-external-input";
    }
    return EvalCtorOutcome();
  }

  // If there are params, we are ignoring them (or we would have quit earlier);
  // set those up with zeros.
  // TODO: Have a safer option here, either
  //        1. Statically or dynamically stop evalling when a param is actually
  //           used, or
  //        2. Split out --ignore-external-input into separate flags.
  Literals params;
  for (Index i = 0; i < func->getNumParams(); i++) {
    auto type = func->getLocalType(i);
    if (!LiteralUtils::canMakeZero(type)) {
      if (!quiet) {
        std::cout << "  ...stopping due to non-zeroable param\n";
      }
      return EvalCtorOutcome();
    }
    params.push_back(Literal::makeZero(type));
  }

  // After we successfully eval a line we will store the operations to set up
  // the locals here. That is, we need to save the local state in the function,
  // which we do by setting up at the entry. We update this list of expressions
  // at the same time as applyToModule() - we must only do it after an entire
  // atomic "chunk" has been processed succesfully, we do not want partial
  // updates from an item in the block that we only partially evalled. When we
  // construct the (partially) evalled function, we will create local.sets of
  // these expressions at the beginning.
  std::vector<Expression*> localExprs;

  // We might have to evaluate multiple functions due to return calls.
start_eval:
  while (true) {
    // We want to handle the form of the global constructor function in LLVM.
    // That looks like this:
    //
    //    (func $__wasm_call_ctors
    //      (call $ctor.1)
    //      (call $ctor.2)
    //      (call $ctor.3)
    //    )
    //
    // Some of those ctors may be inlined, however, which would mean that the
    // function could have locals, control flow, etc. However, we assume for now
    // that it does not have parameters at least (whose values we can't tell).
    // And for now we look for a toplevel block and process its children one at
    // a time. This allows us to eval some of the $ctor.* functions (or their
    // inlined contents) even if not all.
    //
    // TODO: Support complete partial evalling, that is, evaluate parts of an
    //       arbitrary function, and not just a sequence in a single toplevel
    //       block.
    Builder builder(wasm);
    auto* block = builder.blockify(func->body);

    // Go through the items in the block and try to execute them. We do all this
    // in a single function scope for all the executions.
    EvallingModuleRunner::FunctionScope scope(func, params, instance);

    Literals results;
    Index successes = 0;

    for (auto* curr : block->list) {
      Flow flow;
      try {
        flow = instance.visit(curr);
      } catch (FailToEvalException& fail) {
        if (!quiet) {
          if (successes == 0) {
            std::cout << "  ...stopping (in block) since could not eval: "
                      << fail.why << "\n";
          } else {
            std::cout << "  ...partial evalling successful, but stopping since "
                         "could not eval: "
                      << fail.why << "\n";
          }
        }
        break;
      } catch (NonconstantException& fail) {
        if (!quiet) {
          std::cout << "  ...stopping due to non-constant func\n";
        }
        break;
      }

      if (flow.breakTo == NONCONSTANT_FLOW) {
        if (!quiet) {
          std::cout << "  ...stopping due to non-constant flow\n";
        }
        break;
      }

      if (flow.breakTo == RETURN_CALL_FLOW) {
        // The return-called function is stored in the last value.
        func = wasm.getFunction(flow.values.back().getFunc());
        flow.values.pop_back();
        params = std::move(flow.values);

        // Serialize the arguments for the new function and save the module
        // state in case we fail to eval the new function.
        localExprs.clear();
        for (auto& param : params) {
          auto* serialized = interface.getSerialization(param);
          if (!serialized) {
            break;
          }
          localExprs.push_back(serialized);
        }
        if (localExprs.size() < params.size()) {
          if (!quiet) {
            std::cout << "  ...stopping due to non-serializable param\n";
          }
          break;
        }
        interface.applyToModule();
        goto start_eval;
      }

      // So far so good! Serialize the values of locals, and apply to the
      // module. Note that we must serialize the locals now as doing so may
      // cause changes that must be applied to the module (e.g. GC data may
      // cause globals to be added). And we must apply to the module now, and
      // not later, as we must do so right after a successfull partial eval
      // (after any failure to eval, the global state is no long valid to be
      // applied to the module, as incomplete changes may have occurred).
      //
      // Note that we make no effort to optimize locals: we just write out all
      // of them, and leave it to the optimizer to remove redundant or
      // unnecessary operations. We just recompute the entire local
      // serialization sets from scratch each time here, for all locals.
      localExprs.clear();
      for (Index i = 0; i < func->getNumLocals(); i++) {
        auto* serialized = interface.getSerialization(scope.locals[i]);
        if (!serialized) {
          break;
        }
        localExprs.push_back(serialized);
      }
      if (localExprs.size() < func->getNumLocals()) {
        if (!quiet) {
          std::cout << "  ...stopping due to non-serializable local\n";
        }
        break;
      }
      interface.applyToModule();
      successes++;

      // Note the values here, if any. If we are exiting the function now then
      // these will be returned.
      results = flow.values;

      if (flow.breaking()) {
        if (flow.suspendTag) {
          // A suspend reached the exit of the function, so it is unhandled in
          // it. TODO: We could support the case of the calling function
          // handling it.
          if (!quiet) {
            std::cout << "  ...stopping due to unhandled suspend\n";
          }
          return EvalCtorOutcome();
        }

        // We are returning out of the function (either via a return, or via a
        // break to |block|, which has the same outcome. That means we don't
        // need to execute any more lines, and can consider them to be
        // executed.
        if (!quiet) {
          std::cout << "  ...stopping in block due to break\n";
        }

        // Mark us as having succeeded on the entire block, since we have: we
        // are skipping the rest, which means there is no problem there. We
        // must set this here so that lower down we realize that we've evalled
        // everything.
        successes = block->list.size();
        break;
      }
    }

    // If we have not fully evaluated the current function, but we have
    // evaluated part of it, have return-called to a different function, or have
    // precomputed values for the current return-called function, then we can
    // replace the export with a new function that does less work than the
    // original.
    if ((func->imported() || successes < block->list.size()) &&
        (successes > 0 || func->name != funcName ||
         (localExprs.size() && func->getParams() != Type::none))) {
      auto originalFuncType = wasm.getFunction(funcName)->type;
      auto copyName = Names::getValidFunctionName(wasm, funcName);
      *wasm.getExport(exportName)->getInternalName() = copyName;

      if (func->imported()) {
        // We must have return-called this imported function. Generate a new
        // function that return-calls the import with the arguments we have
        // evalled.
        auto copyFunc = builder.makeFunction(
          copyName,
          originalFuncType,
          {},
          builder.makeCall(func->name, localExprs, func->getResults(), true));
        wasm.addFunction(std::move(copyFunc));
        return EvalCtorOutcome();
      }

      // We may have managed to eval some but not all. That means we can't just
      // remove the entire function, but need to keep parts of it - the parts we
      // have not evalled - around. To do so, we create a copy of the function
      // with the partially-evalled contents and make the export use that (as
      // the function may be used in other places than the export, which we do
      // not want to affect).
      auto* copyBody =
        builder.blockify(ExpressionManipulator::copy(func->body, wasm));

      // Remove the items we've evalled.
      for (Index i = 0; i < successes; i++) {
        copyBody->list[i] = builder.makeNop();
      }

      // Put the local sets at the front of the function body.
      auto* setsBlock = builder.makeBlock();
      for (Index i = 0; i < localExprs.size(); ++i) {
        setsBlock->list.push_back(builder.makeLocalSet(i, localExprs[i]));
      }
      copyBody = builder.makeSequence(setsBlock, copyBody, copyBody->type);

      // We may have return-called into a function with different parameter
      // types, but we ultimately need to export a function with the original
      // signature. If there is a mismatch, shift the local indices to make room
      // for the unused parameters.
      std::vector<Type> localTypes;
      auto originalParams =
        originalFuncType.getHeapType().getSignature().params;
      if (originalParams != func->getParams()) {
        // Add locals for the body to use instead of using the params.
        for (auto type : func->getParams()) {
          localTypes.push_back(type);
        }

        // Shift indices in the body so they will refer to the new locals.
        auto localShift = originalParams.size();
        if (localShift != 0) {
          for (auto* get : FindAll<LocalGet>(copyBody).list) {
            get->index += localShift;
          }
          for (auto* set : FindAll<LocalSet>(copyBody).list) {
            set->index += localShift;
          }
        }
      }

      // Add vars from current function.
      localTypes.insert(localTypes.end(), func->vars.begin(), func->vars.end());

      // Create and add the new function.
      auto* copyFunc = wasm.addFunction(builder.makeFunction(
        copyName, originalFuncType, std::move(localTypes), copyBody));

      // Interesting optimizations may be possible both due to removing some but
      // not all of the code, and due to the locals we just added.
      PassRunner passRunner(&wasm,
                            PassOptions::getWithDefaultOptimizationOptions());
      passRunner.addDefaultFunctionOptimizationPasses();
      passRunner.runOnFunction(copyFunc);
    }

    // Return true if we evalled the entire block. Otherwise, even if we evalled
    // some of it, the caller must stop trying to eval further things.
    if (successes == block->list.size()) {
      return EvalCtorOutcome(results);
    } else {
      return EvalCtorOutcome();
    }
  }
}

// This is set when we find a situation we cannot handle in the middle of our
// work. In that case we give up, throwing away the invalid state in memory.
// TODO: Handle all those situations more gracefully, if that becomes useful
//       enough at some point.
static bool invalidState = false;

// Eval all ctors in a module.
void evalCtors(Module& wasm,
               std::vector<std::string>& ctors,
               std::vector<std::string>& keptExports) {
  std::unordered_set<std::string> keptExportsSet(keptExports.begin(),
                                                 keptExports.end());

  std::map<Name, std::shared_ptr<EvallingModuleRunner>> linkedInstances;

  // build and link the env module
  auto envModule = buildEnvModule(wasm);
  CtorEvalExternalInterface envInterface;
  auto envInstance = std::make_shared<EvallingModuleRunner>(
    *envModule, &envInterface, envInterface.instanceInitialized);
  linkedInstances[envModule->name] = envInstance;

  CtorEvalExternalInterface interface(linkedInstances);
  try {
    // create an instance for evalling
    EvallingModuleRunner instance(
      wasm, &interface, interface.instanceInitialized, linkedInstances);
    instance.instantiate();
    interface.instanceInitialized = true;
    // go one by one, in order, until we fail
    // TODO: if we knew priorities, we could reorder?
    for (auto& ctor : ctors) {
      if (!quiet) {
        std::cout << "trying to eval " << ctor << '\n';
      }
      Export* ex = wasm.getExportOrNull(ctor);
      if (!ex || ex->kind != ExternalKind::Function) {
        Fatal() << "export not found: " << ctor;
      }

      auto* func = wasm.getFunction(*ex->getInternalName());

      // Disallow cont.new when we are keeping the export. The problem is that
      // we may end up with a serialization problem later:
      //
      //  (func $foo (export "foo") (result (ref $cont))
      //    (global.set ..) ;; side effect
      //    (cont.new ..)
      //  )
      //
      // We will fail to serialize the result of the function here. But
      // noticing that when we handle keeping of the export is too late, as we
      // will have already applied global effects to the module (in the example
      // above, the global.set will have run). That means we cannot just keep
      // the export by serializing the result and using that as the body (or
      // part of the body), as serialization fails. We would need to go back in
      // time and undo any side effects here. Instead, if we will need the
      // export, disallow things that can block serialization, if we may end up
      // needing to serialize.
      bool keeping = keptExportsSet.count(ctor);
      if (!keeping) {
        instance.allowContNew = true;
      } else {
        // Any reference type might refer to a continuation (indirectly, that
        // is, it might refer to something with a continuation field), so
        // disallow refs too.
        auto features = func->getResults().getFeatures();
        instance.allowContNew =
          !features.hasStackSwitching() && !features.hasReferenceTypes();
      }

      auto outcome = evalCtor(instance, interface, func->name, ctor);
      if (!outcome) {
        if (!quiet) {
          std::cout << "  ...stopping\n";
        }
        return;
      }

      // Success! And we can continue to try more.
      if (!quiet) {
        std::cout << "  ...success on " << ctor << ".\n";
      }

      // Remove the export if we should.
      auto* exp = wasm.getExport(ctor);
      if (!keeping) {
        wasm.removeExport(exp->name);
      } else {
        // We are keeping around the export, which should now refer to an
        // empty function since calling the export should do nothing.
        auto copyName = Names::getValidFunctionName(wasm, func->name);
        auto copyFunc =
          ModuleUtils::copyFunctionWithoutAdd(func, wasm, copyName);
        if (func->getResults() == Type::none) {
          copyFunc->body = Builder(wasm).makeNop();
        } else {
          copyFunc->body = interface.getSerialization(*outcome);
          // We have ruled out serialization problems earlier.
          assert(copyFunc->body);
        }
        wasm.addFunction(std::move(copyFunc));
        *wasm.getExport(exp->name)->getInternalName() = copyName;
      }
    }
  } catch (FailToEvalException& fail) {
    // that's it, we failed to even create the instance
    if (!quiet) {
      std::cout << "  ...stopping since could not create module instance: "
                << fail.why << "\n";
    }
  } catch (TopologicalSort::CycleException e) {
    // We use a topological sort for GC globals. If there is a non-breakable
    // cycle there, we will hit an error (we can break cycles in nullable and
    // mutable fields by setting a null and filling in the value later, but
    // other situations are a problem).
    if (!quiet) {
      std::cout << "  ...stopping since global sorting hit a cycle\n";
    }

    // We found the cycle during the processing of globals, making wasm->globals
    // invalid. Rather than refactor the code heavily to handle this very rare
    // case, just give up entirely, and avoid writing out the current state.
    invalidState = true;
  }
}

static bool canEval(Module& wasm) {
  // Check if we can flatten memory. We need to do so currently because of how
  // we assume memory is simple and flat. TODO
  if (!MemoryUtils::flatten(wasm)) {
    if (!quiet) {
      std::cout << "  ...stopping since could not flatten memory\n";
    }
    return false;
  }
  return true;
}

} // anonymous namespace

//
// main
//

int main(int argc, const char* argv[]) {
  Name entry;
  std::vector<std::string> passes;
  bool emitBinary = true;
  bool debugInfo = false;
  String::Split ctors;
  String::Split keptExports;

  const std::string WasmCtorEvalOption = "wasm-ctor-eval options";

  ToolOptions options("wasm-ctor-eval", "Execute code at compile time");
  options
    .add("--output",
         "-o",
         "Output file",
         WasmCtorEvalOption,
         Options::Arguments::One,
         [](Options* o, const std::string& argument) {
           o->extra["output"] = argument;
           Colors::setEnabled(false);
         })
    .add("--emit-text",
         "-S",
         "Emit text instead of binary for the output file",
         WasmCtorEvalOption,
         Options::Arguments::Zero,
         [&](Options* o, const std::string& argument) { emitBinary = false; })
    .add("--debuginfo",
         "-g",
         "Emit names section and debug info",
         WasmCtorEvalOption,
         Options::Arguments::Zero,
         [&](Options* o, const std::string& arguments) { debugInfo = true; })
    .add("--ctors",
         "-c",
         "Comma-separated list of global constructor functions to evaluate",
         WasmCtorEvalOption,
         Options::Arguments::One,
         [&](Options* o, const std::string& argument) {
           ctors = String::Split(argument, ",");
         })
    .add(
      "--kept-exports",
      "-ke",
      "Comma-separated list of ctors whose exports we keep around even if we "
      "eval those ctors",
      WasmCtorEvalOption,
      Options::Arguments::One,
      [&](Options* o, const std::string& argument) {
        keptExports = String::Split(argument, ",");
      })
    .add("--ignore-external-input",
         "-ipi",
         "Assumes no env vars are to be read, stdin is empty, etc.",
         WasmCtorEvalOption,
         Options::Arguments::Zero,
         [&](Options* o, const std::string& argument) {
           ignoreExternalInput = true;
         })
    .add("--quiet",
         "-q",
         "Do not emit verbose logging about the eval process",
         WasmCtorEvalOption,
         Options::Arguments::Zero,
         [&](Options* o, const std::string& argument) { quiet = true; })
    .add_positional("INFILE",
                    Options::Arguments::One,
                    [](Options* o, const std::string& argument) {
                      o->extra["infile"] = argument;
                    });
  options.parse(argc, argv);

  Module wasm;
  options.applyOptionsBeforeParse(wasm);

  {
    if (options.debug) {
      std::cout << "reading...\n";
    }
    ModuleReader reader;
    try {
      reader.read(options.extra["infile"], wasm);
    } catch (ParseException& p) {
      p.dump(std::cout);
      Fatal() << "error in parsing input";
    }
  }

  options.applyOptionsAfterParse(wasm);

  if (!WasmValidator().validate(wasm)) {
    std::cout << wasm << '\n';
    Fatal() << "error in validating input";
  }

  if (canEval(wasm)) {
    evalCtors(wasm, ctors, keptExports);

    if (invalidState) {
      // We ended up in a state that cannot be written out. Forget about all of
      // it, by re-reading the input and continuing from there (with nothing at
      // all evalled, effectively).
      auto features = wasm.features;
      ModuleUtils::clearModule(wasm);
      wasm.features = features;
      ModuleReader reader;
      reader.read(options.extra["infile"], wasm);
    }

    if (!WasmValidator().validate(wasm)) {
      std::cout << wasm << '\n';
      Fatal() << "error in validating output";
    }

    // Do some useful optimizations after the evalling
    {
      PassRunner passRunner(&wasm);
      passRunner.add("memory-packing"); // we flattened it, so re-optimize
      // TODO: just do -Os for the one function
      passRunner.add("remove-unused-names");
      passRunner.add("dce");
      passRunner.add("merge-blocks");
      passRunner.add("vacuum");
      passRunner.add("remove-unused-module-elements");
      passRunner.run();
    }
  }

  if (options.extra.count("output") > 0) {
    if (options.debug) {
      std::cout << "writing..." << std::endl;
    }
    ModuleWriter writer(options.passOptions);
    writer.setBinary(emitBinary);
    writer.setDebugInfo(debugInfo);
    writer.write(wasm, options.extra["output"]);
  }

  flush_and_quick_exit(0);
}
