/*
 * 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/import-utils.h"
#include "ir/literal-utils.h"
#include "ir/memory-utils.h"
#include "ir/names.h"
#include "pass.h"
#include "support/colors.h"
#include "support/file.h"
#include "support/insert_ordered.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, bool mut) 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(Address i, Literal l) override {
    if (instanceInitialized) {
      throw FailToEvalException("tableStore after init: TODO");
    }
  }

  Literal get(Address 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<Address> grow(Address delta,
                                                    Literal fill) override {
    throw FailToEvalException("grow table");
  }

  Address 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()) {
        wasm->addGlobal(std::move(oldGlobal));
        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);
}
