/*
 * Copyright 2021 WebAssembly Community Group participants
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "tools/fuzzing.h"
#include "ir/gc-type-utils.h"
#include "ir/glbs.h"
#include "ir/iteration.h"
#include "ir/local-structural-dominance.h"
#include "ir/module-utils.h"
#include "ir/subtype-exprs.h"
#include "ir/subtypes.h"
#include "ir/type-updating.h"
#include "support/string.h"
#include "tools/fuzzing/heap-types.h"
#include "wasm-io.h"

namespace wasm {

TranslateToFuzzReader::TranslateToFuzzReader(Module& wasm,
                                             std::vector<char>&& input,
                                             bool closedWorld)
  : wasm(wasm), closedWorld(closedWorld), builder(wasm),
    random(std::move(input), wasm.features),
    publicTypeValidator(wasm.features) {

  haveInitialFunctions = !wasm.functions.empty();

  // - funcref cannot be logged because referenced functions can be inlined or
  // removed during optimization
  // - there's no point in logging anyref because it is opaque
  // - don't bother logging tuples
  loggableTypes = {Type::i32, Type::i64, Type::f32, Type::f64};
  if (wasm.features.hasSIMD()) {
    loggableTypes.push_back(Type::v128);
  }

  // Setup params. Start with the defaults.
  globalParams = std::make_unique<FuzzParamsContext>(*this);

  // Some of the time, adjust parameters based on the size, e.g. allowing more
  // heap types in larger inputs, etc.
  if (random.oneIn(2)) {
    // A typical random wasm input from fuzz_opt.py is fairly large (to minimize
    // the process creation overhead of all the things we run from python), and
    // the defaults are tuned to that. This corresponds to INPUT_SIZE_MEAN in
    // scripts/fuzz_opt.py
    const double MEAN_SIZE = 40 * 1024;

    // As we have not read anything from the input, the remaining size is its
    // size.
    double size = random.remaining();
    auto ratio = size / MEAN_SIZE;

    auto bits = random.get();
    if (bits & 1) {
      fuzzParams->MAX_NEW_GC_TYPES *= ratio;
    }
    if (bits & 2) {
      fuzzParams->MAX_GLOBALS *= ratio;
    }
    if (bits & 4) {
      // Only adjust the limit if there is one.
      if (fuzzParams->HANG_LIMIT) {
        fuzzParams->HANG_LIMIT *= ratio;
        // There is a limit, so keep it non-zero to actually prevent hangs.
        fuzzParams->HANG_LIMIT = std::max(fuzzParams->HANG_LIMIT, 1);
      }
    }
    if (bits & 8) {
      // Only increase the number of tries. Trying fewer times does not help
      // find more interesting patterns.
      if (ratio > 1) {
        fuzzParams->TRIES *= ratio;
      }
    }
    if (bits & 16) {
      fuzzParams->MAX_ARRAY_SIZE *= ratio;
    }
  }

  // Half the time add no unreachable code so that we'll execute the most code
  // as possible with no early exits.
  allowAddingUnreachableCode = oneIn(2);
}

TranslateToFuzzReader::TranslateToFuzzReader(Module& wasm,
                                             std::string& filename,
                                             bool closedWorld)
  : TranslateToFuzzReader(wasm,
                          read_file<std::vector<char>>(filename, Flags::Binary),
                          closedWorld) {}

void TranslateToFuzzReader::pickPasses(OptimizationOptions& options) {
  // Pick random passes to further shape the wasm. This is similar to how we
  // pick random passes in fuzz_opt.py, but the goal there is to find problems
  // in the passes, while the goal here is more to shape the wasm, so that
  // translate-to-fuzz emits interesting outputs (the latter is important for
  // things like ClusterFuzz, where we are using Binaryen to fuzz other things
  // than itself). As a result, the list of passes here is different from
  // fuzz_opt.py.

  // Enclose the world, some of the time. We do this before picking any other
  // passes so that we make the initial fuzz contents more optimizable by
  // closed-world passes later. Note that we do this regardless of whether we
  // are in closed-world mode or not, as it is good to get this variety
  // regardless.
  if (oneIn(2)) {
    options.passes.push_back("enclose-world");
  }

  // Main selection of passes.
  while (options.passes.size() < 20 && !random.finished() && !oneIn(3)) {
    switch (upTo(42)) {
      case 0:
      case 1:
      case 2:
      case 3:
      case 4: {
        options.passOptions.optimizeLevel = upTo(4);
        options.passOptions.shrinkLevel = upTo(3);
        options.addDefaultOptPasses();
        break;
      }
      case 5:
        options.passes.push_back("coalesce-locals");
        break;
      case 6:
        options.passes.push_back("code-pushing");
        break;
      case 7:
        options.passes.push_back("code-folding");
        break;
      case 8:
        options.passes.push_back("dce");
        break;
      case 9:
        options.passes.push_back("duplicate-function-elimination");
        break;
      case 10:
        // Some features do not support flatten yet.
        if (!wasm.features.hasReferenceTypes() &&
            !wasm.features.hasExceptionHandling() && !wasm.features.hasGC()) {
          options.passes.push_back("flatten");
          if (oneIn(2)) {
            options.passes.push_back("rereloop");
          }
        }
        break;
      case 11:
        options.passes.push_back("inlining");
        break;
      case 12:
        options.passes.push_back("inlining-optimizing");
        break;
      case 13:
        options.passes.push_back("local-cse");
        break;
      case 14:
        options.passes.push_back("memory-packing");
        break;
      case 15:
        options.passes.push_back("merge-blocks");
        break;
      case 16:
        options.passes.push_back("optimize-instructions");
        break;
      case 17:
        options.passes.push_back("pick-load-signs");
        break;
      case 18:
        options.passes.push_back("precompute");
        break;
      case 19:
        options.passes.push_back("precompute-propagate");
        break;
      case 20:
        options.passes.push_back("remove-unused-brs");
        break;
      case 21:
        options.passes.push_back("remove-unused-module-elements");
        break;
      case 22:
        options.passes.push_back("remove-unused-names");
        break;
      case 23:
        options.passes.push_back("reorder-functions");
        break;
      case 24:
        options.passes.push_back("reorder-locals");
        break;
      case 25:
        options.passes.push_back("directize");
        break;
      case 26:
        options.passes.push_back("simplify-locals");
        break;
      case 27:
        options.passes.push_back("simplify-locals-notee");
        break;
      case 28:
        options.passes.push_back("simplify-locals-nostructure");
        break;
      case 29:
        options.passes.push_back("simplify-locals-notee-nostructure");
        break;
      case 30:
        options.passes.push_back("ssa");
        break;
      case 31:
        options.passes.push_back("vacuum");
        break;
      case 32:
        options.passes.push_back("merge-locals");
        break;
      case 33:
        options.passes.push_back("licm");
        break;
      case 34:
        options.passes.push_back("tuple-optimization");
        break;
      case 35:
        options.passes.push_back("rse");
        break;
      case 36:
        options.passes.push_back("monomorphize");
        break;
      case 37:
        options.passes.push_back("monomorphize-always");
        break;
      case 38:
      case 39:
      case 40:
      case 41:
        // GC specific passes.
        if (wasm.features.hasGC()) {
          // Most of these depend on closed world, so just set that. Set it both
          // on the global pass options, and in the internal state of this
          // TranslateToFuzzReader instance.
          options.passOptions.closedWorld = true;
          closedWorld = true;

          switch (upTo(16)) {
            case 0:
              options.passes.push_back("abstract-type-refining");
              break;
            case 1:
              options.passes.push_back("cfp");
              break;
            case 2:
              options.passes.push_back("gsi");
              break;
            case 3:
              options.passes.push_back("gto");
              break;
            case 4:
              options.passes.push_back("heap2local");
              break;
            case 5:
              options.passes.push_back("heap-store-optimization");
              break;
            case 6:
              options.passes.push_back("minimize-rec-groups");
              break;
            case 7:
              options.passes.push_back("remove-unused-types");
              break;
            case 8:
              options.passes.push_back("signature-pruning");
              break;
            case 9:
              options.passes.push_back("signature-refining");
              break;
            case 10:
              options.passes.push_back("type-finalizing");
              break;
            case 11:
              options.passes.push_back("type-refining");
              break;
            case 12:
              options.passes.push_back("type-merging");
              break;
            case 13:
              options.passes.push_back("type-ssa");
              break;
            case 14:
              options.passes.push_back("type-unfinalizing");
              break;
            case 15:
              options.passes.push_back("unsubtyping");
              break;
            default:
              WASM_UNREACHABLE("unexpected value");
          }
        }
        break;
      default:
        WASM_UNREACHABLE("unexpected value");
    }
  }

  if (oneIn(2)) {
    // We randomize these when we pick -O?, but sometimes do so even without, as
    // they affect some passes.
    options.passOptions.optimizeLevel = upTo(4);
    options.passOptions.shrinkLevel = upTo(3);
  }

  if (!options.passOptions.closedWorld && oneIn(2)) {
    options.passOptions.closedWorld = true;
  }

  // Prune things that error in JS if we call them (like SIMD), some of the
  // time. This alters the wasm/JS boundary quite a lot, so testing both forms
  // is useful. Note that we do not do this if there is an imported module,
  // because in that case legalization could alter the contract between the two
  // (that is, if the first module has an i64 param, we must call it like that,
  // and not as two i32s which we'd get after legalization).
  if (!importedModule && oneIn(2)) {
    options.passes.push_back("legalize-and-prune-js-interface");
  }

  // Usually DCE at the very end, to ensure that our binaries validate in other
  // VMs, due to how non-nullable local validation and unreachable code
  // interact. See fuzz_opt.py and
  //   https://github.com/WebAssembly/binaryen/pull/5665
  //   https://github.com/WebAssembly/binaryen/issues/5599
  if (wasm.features.hasGC() && !oneIn(10)) {
    options.passes.push_back("dce");
  }

  // TODO: We could in theory run some function-level passes on particular
  //       functions, but then we'd need to do this after generation, not
  //       before (and random data no longer remains then).
}

void TranslateToFuzzReader::build() {
  if (fuzzParams->HANG_LIMIT > 0) {
    prepareHangLimitSupport();
  }
  if (allowMemory) {
    setupMemory();
  }
  setupHeapTypes();
  setupTables();
  setupGlobals();
  useImportedGlobals();
  if (wasm.features.hasExceptionHandling()) {
    setupTags();
    addImportThrowingSupport();
  }
  if (wasm.features.hasReferenceTypes()) {
    addImportTableSupport();
  }
  addImportLoggingSupport();
  addImportCallingSupport();
  addImportSleepSupport();

  // First, modify initial functions. That includes removing imports. Then,
  // use the imported module, which are function imports that we allow.
  modifyInitialFunctions();
  useImportedFunctions();

  processFunctions();
  if (fuzzParams->HANG_LIMIT > 0) {
    addHangLimitSupport();
  }
  if (allowMemory) {
    finalizeMemory();
    addHashMemorySupport();
  }
  finalizeTable();
  shuffleExports();

  // We may turn various function imports into defined functions. Refinalize at
  // the end to update all references to them, which may become exact.
  PassRunner runner(&wasm);
  ReFinalize().run(&runner, &wasm);
  ReFinalize().walkModuleCode(&wasm);
}

void TranslateToFuzzReader::setupMemory() {
  // Add a memory, if one does not already exist.
  if (wasm.memories.empty()) {
    auto memory = Builder::makeMemory("0");
    // Add at least one page of memory.
    memory->initial = 1 + upTo(10);
    // Make the max potentially higher, or unlimited.
    if (oneIn(2)) {
      memory->max = memory->initial + upTo(4);
    } else {
      memory->max = Memory::kUnlimitedSize;
    }
    // Fuzz wasm64 when possible, sometimes.
    if (wasm.features.hasMemory64() && oneIn(2)) {
      memory->addressType = Type::i64;
    }
    wasm.addMemory(std::move(memory));
  }

  auto& memory = wasm.memories[0];
  if (wasm.features.hasBulkMemory()) {
    size_t numSegments = upTo(8);
    // need at least one segment for memory.inits
    if (wasm.dataSegments.empty() && !numSegments) {
      numSegments = 1;
    }
    size_t memCovered = 0;
    for (size_t i = 0; i < numSegments; i++) {
      auto segment = builder.makeDataSegment();
      segment->setName(Names::getValidDataSegmentName(wasm, Name::fromInt(i)),
                       false);
      segment->isPassive = bool(upTo(2));
      size_t segSize = upTo(fuzzParams->USABLE_MEMORY * 2);
      segment->data.resize(segSize);
      for (size_t j = 0; j < segSize; j++) {
        segment->data[j] = upTo(512);
      }
      if (!segment->isPassive) {
        segment->offset = builder.makeConst(
          Literal::makeFromInt32(memCovered, memory->addressType));
        memCovered += segSize;
        segment->memory = memory->name;
      }
      wasm.addDataSegment(std::move(segment));
    }
  } else {
    // init some data, especially if none exists before
    if (!oneIn(wasm.dataSegments.empty() ? 10 : 2)) {
      auto segment = builder.makeDataSegment();
      segment->memory = memory->name;
      segment->offset =
        builder.makeConst(Literal::makeFromInt32(0, memory->addressType));
      segment->setName(Names::getValidDataSegmentName(wasm, Name::fromInt(0)),
                       false);
      auto num = upTo(fuzzParams->USABLE_MEMORY * 2);
      for (size_t i = 0; i < num; i++) {
        auto value = upTo(512);
        segment->data.push_back(value >= 256 ? 0 : (value & 0xff));
      }
      wasm.addDataSegment(std::move(segment));
    }
  }
}

void TranslateToFuzzReader::setupHeapTypes() {
  // Start with any existing heap types in the module, which may exist in any
  // initial content we began with.
  auto possibleHeapTypes = ModuleUtils::collectHeapTypes(wasm);

  // Use heap types from an imported module, if present.
  if (importedModule) {
    auto importedHeapTypes = ModuleUtils::collectHeapTypes(*importedModule);
    auto rate = upTo(11);
    for (auto type : importedHeapTypes) {
      if (upTo(10) < rate) {
        possibleHeapTypes.push_back(type);
      }
    }
  }

  // Filter away uninhabitable heap types, that is, heap types that we cannot
  // construct, like a type with a non-nullable reference to itself.
  interestingHeapTypes = HeapTypeGenerator::getInhabitable(possibleHeapTypes);

  // For GC, also generate random types.
  if (wasm.features.hasGC()) {
    auto generator = HeapTypeGenerator::create(
      random, wasm.features, upTo(fuzzParams->MAX_NEW_GC_TYPES));
    auto result = generator.builder.build();
    if (auto* err = result.getError()) {
      Fatal() << "Failed to build heap types: " << err->reason << " at index "
              << err->index;
    }

    // Make the new types inhabitable. This process modifies existing types, so
    // it leaves more available compared to HeapTypeGenerator::getInhabitable.
    // We run that before on existing content, which may have instructions that
    // use the types, as editing them is not trivial, and for new types here we
    // are free to modify them so we keep as many as we can.
    auto inhabitable = HeapTypeGenerator::makeInhabitable(*result);
    for (auto type : inhabitable) {
      // Trivial types are already handled specifically in e.g.
      // getSingleConcreteType(), and we avoid adding them here as then we'd
      // need to add code to avoid uninhabitable combinations of them (like a
      // non-nullable bottom heap type).
      if (!type.isBottom() && !type.isBasic()) {
        interestingHeapTypes.push_back(type);
        if (oneIn(2)) {
          // Add a name for this type.
          wasm.typeNames[type].name =
            "generated_type$" + std::to_string(interestingHeapTypes.size());
        }
      }
    }
  }

  // Compute subtypes ahead of time. It is more efficient to do this all at once
  // now, rather than lazily later.
  SubTypes subTypes(interestingHeapTypes);
  for (auto type : interestingHeapTypes) {
    for (auto subType : subTypes.getImmediateSubTypes(type)) {
      interestingHeapSubTypes[type].push_back(subType);
    }
    // Basic types must be handled directly, since subTypes doesn't look at
    // those.
    auto share = type.getShared();
    auto struct_ = HeapTypes::struct_.getBasic(share);
    auto array = HeapTypes::array.getBasic(share);
    auto eq = HeapTypes::eq.getBasic(share);
    auto any = HeapTypes::any.getBasic(share);
    auto func = HeapTypes::func.getBasic(share);
    auto cont = HeapTypes::cont.getBasic(share);
    switch (type.getKind()) {
      case HeapTypeKind::Func:
        interestingHeapSubTypes[func].push_back(type);
        break;
      case HeapTypeKind::Struct: {
        interestingHeapSubTypes[struct_].push_back(type);
        interestingHeapSubTypes[eq].push_back(type);
        interestingHeapSubTypes[any].push_back(type);
        // Note the mutable fields.
        auto& fields = type.getStruct().fields;
        for (Index i = 0; i < fields.size(); i++) {
          if (fields[i].mutable_) {
            mutableStructFields.push_back(StructField{type, i});
          }
        }
        break;
      }
      case HeapTypeKind::Array:
        interestingHeapSubTypes[array].push_back(type);
        interestingHeapSubTypes[eq].push_back(type);
        interestingHeapSubTypes[any].push_back(type);
        if (type.getArray().element.mutable_) {
          mutableArrays.push_back(type);
        }
        break;
      case HeapTypeKind::Cont:
        interestingHeapSubTypes[cont].push_back(type);
        break;
      case HeapTypeKind::Basic:
        WASM_UNREACHABLE("unexpected kind");
    }
  }

  // Compute struct and array fields.
  for (auto type : interestingHeapTypes) {
    if (type.isStruct()) {
      auto& fields = type.getStruct().fields;
      for (Index i = 0; i < fields.size(); i++) {
        typeStructFields[fields[i].type].push_back(StructField{type, i});
      }
    } else if (type.isArray()) {
      typeArrays[type.getArray().element.type].push_back(type);
    }
  }
}

// TODO(reference-types): allow the fuzzer to create multiple tables
void TranslateToFuzzReader::setupTables() {
  // Ensure a funcref element segment and table exist. Segments with more
  // specific function types may have a smaller chance of getting functions.
  Table* table = nullptr;
  Type funcref = Type(HeapType::func, Nullable);
  auto iter = std::find_if(wasm.tables.begin(),
                           wasm.tables.end(),
                           [&](auto& table) { return table->type == funcref; });
  if (iter != wasm.tables.end()) {
    table = iter->get();
  } else {
    // Start from a potentially empty table.
    Address initial = upTo(10);
    // Make the max potentially higher, or unlimited.
    Address max;
    if (oneIn(2)) {
      max = initial + upTo(4);
    } else {
      max = Memory::kUnlimitedSize;
    }
    // Fuzz wasm64 when possible, sometimes.
    auto addressType = Type::i32;
    if (wasm.features.hasMemory64() && oneIn(2)) {
      addressType = Type::i64;
    }
    auto tablePtr =
      builder.makeTable(Names::getValidTableName(wasm, "fuzzing_table"),
                        funcref,
                        initial,
                        max,
                        addressType);
    tablePtr->hasExplicitName = true;
    table = wasm.addTable(std::move(tablePtr));
  }
  funcrefTableName = table->name;
  bool hasFuncrefElemSegment =
    std::any_of(wasm.elementSegments.begin(),
                wasm.elementSegments.end(),
                [&](auto& segment) {
                  return segment->table.is() && segment->type == funcref;
                });
  auto addressType = wasm.getTable(funcrefTableName)->addressType;
  if (!hasFuncrefElemSegment) {
    // TODO: use a random table
    auto segment = std::make_unique<ElementSegment>(
      table->name, builder.makeConst(Literal::makeFromInt32(0, addressType)));
    segment->setName(Names::getValidElementSegmentName(wasm, "elem$"), false);
    wasm.addElementSegment(std::move(segment));
  }

  // When EH is enabled, set up an exnref table.
  if (wasm.features.hasExceptionHandling()) {
    Type exnref = Type(HeapType::exn, Nullable);
    auto iter =
      std::find_if(wasm.tables.begin(), wasm.tables.end(), [&](auto& table) {
        return table->type == exnref;
      });
    if (iter != wasm.tables.end()) {
      // Use the existing one.
      exnrefTableName = iter->get()->name;
    } else {
      // Create a new exnref table.
      Address initial = upTo(10);
      Address max = oneIn(2) ? initial + upTo(4) : Memory::kUnlimitedSize;
      auto tablePtr =
        builder.makeTable(Names::getValidTableName(wasm, "exnref_table"),
                          exnref,
                          initial,
                          max,
                          Type::i32); // TODO: wasm64
      tablePtr->hasExplicitName = true;
      table = wasm.addTable(std::move(tablePtr));
      exnrefTableName = table->name;
    }
  }
}

void TranslateToFuzzReader::useGlobalLater(Global* global) {
  auto type = global->type;
  auto name = global->name;
  globalsByType[type].push_back(name);
  if (global->mutable_) {
    mutableGlobalsByType[type].push_back(name);
  } else {
    immutableGlobalsByType[type].push_back(name);
    if (global->imported()) {
      importedImmutableGlobalsByType[type].push_back(name);
    }
  }
}

void TranslateToFuzzReader::setupGlobals() {
  // If there were initial wasm contents, there may be imported globals. That
  // would be a problem in the fuzzer harness as we'd error if we do not
  // provide them (and provide the proper type, etc.).
  // Avoid that, so that all the standard fuzzing infrastructure can always
  // run the wasm.
  for (auto& global : wasm.globals) {
    if (global->imported()) {
      if (!preserveImportsAndExports) {
        // Remove import info from imported globals, and give them a simple
        // initializer.
        global->module = global->base = Name();
        global->init = makeConst(global->type);
      }
    } else {
      // If the initialization referred to an imported global, it no longer can
      // point to the same global after we make it a non-imported global unless
      // GC is enabled, since before GC, Wasm only made imported globals
      // available in constant expressions.
      if (!wasm.features.hasGC() &&
          !FindAll<GlobalGet>(global->init).list.empty()) {
        global->init = makeConst(global->type);
      }
    }
  }

  // Randomly assign some globals from initial content to be ignored for the
  // fuzzer to use. Such globals will only be used from initial content. This is
  // important to preserve some real-world patterns, like the "once" pattern in
  // which a global is used in one function only. (If we randomly emitted gets
  // and sets of such globals, we'd with very high probability end up breaking
  // that pattern, and not fuzzing it at all.)
  if (!wasm.globals.empty()) {
    unsigned percentUsedInitialGlobals = upTo(100);
    for (auto& global : wasm.globals) {
      if (upTo(100) < percentUsedInitialGlobals) {
        useGlobalLater(global.get());
      }
    }
  }

  // Create new random globals.
  for (size_t index = upTo(fuzzParams->MAX_GLOBALS); index > 0; --index) {
    auto type = getConcreteType();

    // Prefer immutable ones as they can be used in global.gets in other
    // globals, for more interesting patterns.
    auto mutability = oneIn(3) ? Builder::Mutable : Builder::Immutable;

    // We can only make something trivial (like a constant) in a global
    // initializer.
    auto* init = makeTrivial(type);

    if (type.isTuple() && !init->is<TupleMake>()) {
      // For now we disallow anything but tuple.make at the top level of tuple
      // globals (see details in wasm-binary.cpp). In the future we may allow
      // global.get or other things here.
      init = makeConst(type);
      assert(init->is<TupleMake>());
    }
    if (!FindAll<RefAs>(init).list.empty() ||
        !FindAll<ContNew>(init).list.empty()) {
      // When creating this initial value we ended up emitting a RefAs, which
      // means we had to stop in the middle of an overly-nested struct or array,
      // which we can break out of using ref.as_non_null of a nullable ref. That
      // traps in normal code, which is bad enough, but it does not even
      // validate in a global. Switch to something safe instead.
      //
      // Likewise, if we see cont.new, we must switch as well. That can happen
      // if a nested struct we create has a continuation field, for example.
      type = getMVPType();
      init = makeConst(type);
    }
    auto name = Names::getValidGlobalName(wasm, "global$");
    auto global = builder.makeGlobal(name, type, init, mutability);
    useGlobalLater(wasm.addGlobal(std::move(global)));

    // Export some globals, where we can.
    if (preserveImportsAndExports || type.isTuple() ||
        !isValidPublicType(type)) {
      continue;
    }
    if (mutability == Builder::Mutable && !wasm.features.hasMutableGlobals()) {
      continue;
    }
    if (oneIn(2)) {
      auto exportName = Names::getValidExportName(wasm, name);
      wasm.addExport(
        Builder::makeExport(exportName, name, ExternalKind::Global));
    }
  }
}

void TranslateToFuzzReader::setupTags() {
  // As in modifyInitialFunctions(), we can't allow arbitrary tag imports, which
  // would trap when the fuzzing infrastructure doesn't know what to provide.
  for (auto& tag : wasm.tags) {
    if (tag->imported() && !preserveImportsAndExports) {
      tag->module = tag->base = Name();
    }
    if (tag->results() == Type::none) {
      exceptionTags.push_back(tag.get());
    }
  }

  // Add some random tags.
  Index num = upTo(3);
  for (size_t i = 0; i < num; i++) {
    addTag();
  }

  // Add the fuzzing support tags manually sometimes.
  if (!preserveImportsAndExports && oneIn(2) && !random.finished()) {
    auto wasmTag = builder.makeTag(Names::getValidTagName(wasm, "wasmtag"),
                                   Signature(Type::i32, Type::none));
    wasmTag->module = "fuzzing-support";
    wasmTag->base = "wasmtag";
    wasm.addTag(std::move(wasmTag));

    auto externref = Type(HeapType::ext, Nullable);
    auto jsTag = builder.makeTag(Names::getValidTagName(wasm, "jstag"),
                                 Signature(externref, Type::none));
    jsTag->module = "fuzzing-support";
    jsTag->base = "jstag";
    wasm.addTag(std::move(jsTag));
  }
}

void TranslateToFuzzReader::addTag() {
  auto tag = builder.makeTag(Names::getValidTagName(wasm, "tag$"),
                             Signature(getControlFlowType(), Type::none));
  auto* tagg = wasm.addTag(std::move(tag));
  exceptionTags.push_back(tagg);
}

void TranslateToFuzzReader::finalizeMemory() {
  auto& memory = wasm.memories[0];
  for (auto& segment : wasm.dataSegments) {
    Address maxOffset = segment->data.size();
    if (!segment->isPassive) {
      if (!wasm.features.hasGC()) {
        // Using a non-imported global in a segment offset is not valid in wasm
        // unless GC is enabled. This can occur due to us adding a local
        // definition to what used to be an imported global in initial contents.
        // To fix that, replace such invalid offsets with a constant.
        for ([[maybe_unused]] auto* get :
             FindAll<GlobalGet>(segment->offset).list) {
          // No imported globals should remain.
          assert(!wasm.getGlobal(get->name)->imported());
          // TODO: It would be better to avoid segment overlap so that
          //       MemoryPacking can run.
          segment->offset =
            builder.makeConst(Literal::makeFromInt32(0, memory->addressType));
        }
      }
      if (auto* offset = segment->offset->dynCast<Const>()) {
        maxOffset = maxOffset + offset->value.getInteger();
      }
    }

    // Ensure the initial memory can fit the segment (so we don't just trap),
    // but only do so when the segment is at a reasonable offset (to avoid
    // validation errors on the initial size >= 4GB in wasm32, but also to
    // avoid OOM errors on trying to allocate too much initial memory, which is
    // annoying in the fuzzer).
    Address ONE_GB = 1024 * 1024 * 1024;
    if (maxOffset <= ONE_GB) {
      memory->initial = std::max(
        memory->initial,
        Address((maxOffset + Memory::kPageSize - 1) / Memory::kPageSize));
    }
  }
  memory->initial = std::max(memory->initial, fuzzParams->USABLE_MEMORY);
  // Avoid an unlimited memory size, which would make fuzzing very difficult
  // as different VMs will run out of system memory in different ways.
  if (memory->max == Memory::kUnlimitedSize) {
    memory->max = memory->initial;
  }
  if (memory->max <= memory->initial) {
    // To allow growth to work (which a testcase may assume), try to make the
    // maximum larger than the initial.
    // TODO: scan the wasm for grow instructions?
    memory->max =
      std::min(Address(memory->initial + 1), Address(Memory::kMaxSize32));
  }

  if (!preserveImportsAndExports) {
    // Avoid an imported memory (which the fuzz harness would need to handle).
    for (auto& memory : wasm.memories) {
      memory->module = memory->base = Name();
    }
  }
}

void TranslateToFuzzReader::finalizeTable() {
  for (auto& table : wasm.tables) {
    ModuleUtils::iterTableSegments(
      wasm, table->name, [&](ElementSegment* segment) {
        // If the offset contains a global that was imported (which is ok) but
        // no longer is (not ok unless GC is enabled), we may need to change
        // that.
        if (!wasm.features.hasGC()) {
          for ([[maybe_unused]] auto* get :
               FindAll<GlobalGet>(segment->offset).list) {
            // No imported globals should remain.
            assert(!wasm.getGlobal(get->name)->imported());
            // TODO: the segments must not overlap...
            segment->offset =
              builder.makeConst(Literal::makeFromInt32(0, table->addressType));
          }
        }
        Address maxOffset = segment->data.size();
        if (auto* offset = segment->offset->dynCast<Const>()) {
          maxOffset = maxOffset + offset->value.getInteger();
        }
        table->initial = std::max(table->initial, maxOffset);
      });

    // The code above raises table->initial to a size large enough to accomodate
    // all of its segments, with the intention of avoiding a trap during
    // startup. However a single segment of (say) size 4GB would have a table of
    // that size, which will use a lot of memory and execute very slowly, so we
    // prefer in the fuzzer to trap on such a thing. To achieve that, set a
    // reasonable limit for the maximum table size.
    //
    // This also avoids an issue that arises from table->initial being an
    // Address (64 bits) but Table::kMaxSize being an Index (32 bits), as a
    // result of which we need to clamp to Table::kMaxSize as well in order for
    // the module to validate (but since we are clamping to a smaller value,
    // there is no need).
    const Address ReasonableMaxTableSize = 10000;
    table->initial = std::min(table->initial, ReasonableMaxTableSize);
    assert(ReasonableMaxTableSize <= Table::kMaxSize);

    table->max = oneIn(2) ? Address(Table::kUnlimitedSize) : table->initial;

    if (!preserveImportsAndExports) {
      // Avoid an imported table (which the fuzz harness would need to handle).
      table->module = table->base = Name();
    }
  }
}

void TranslateToFuzzReader::shuffleExports() {
  // Randomly ordering the exports is useful for a few reasons. First, initial
  // content may have a natural order in which to execute things (an "init"
  // export first, for example), and changing that order may lead to very
  // different execution. Second, even in the fuzzer's own random content there
  // is a "direction", since we generate as we go (e.g. no function calls a
  // later function that does not exist yet / will be created later), and also
  // we emit invokes for a function right after it (so we end up calling the
  // same code several times in succession, but interleaving it with others may
  // find more things). But we also keep a good chance for the natural order
  // here, as it may help some initial content. Note we cannot do this if we are
  // preserving the exports, as their order is something we must maintain.
  if (wasm.exports.empty() || preserveImportsAndExports || oneIn(2) ||
      random.finished()) {
    return;
  }

  // Sort the exports in the simple Fisher-Yates manner.
  // https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm
  for (Index i = 0; i < wasm.exports.size() - 1; i++) {
    // Pick the index of the item to place at index |i|. The number of items to
    // pick from begins at the full length, then decreases with i.
    auto j = i + upTo(wasm.exports.size() - i);

    // Swap the item over here.
    if (j != i) {
      std::swap(wasm.exports[i], wasm.exports[j]);
    }
  }

  wasm.updateMaps();
}

void TranslateToFuzzReader::prepareHangLimitSupport() {
  HANG_LIMIT_GLOBAL = Names::getValidGlobalName(wasm, "hangLimit");
}

void TranslateToFuzzReader::addHangLimitSupport() {
  auto glob =
    builder.makeGlobal(HANG_LIMIT_GLOBAL,
                       Type::i32,
                       builder.makeConst(int32_t(fuzzParams->HANG_LIMIT)),
                       Builder::Mutable);
  wasm.addGlobal(std::move(glob));
}

void TranslateToFuzzReader::addImportLoggingSupport() {
  for (auto type : loggableTypes) {
    auto func = std::make_unique<Function>();
    Name baseName = std::string("log-") + type.toString();
    func->name = Names::getValidFunctionName(wasm, baseName);
    logImportNames[type] = func->name;
    if (!preserveImportsAndExports) {
      func->module = "fuzzing-support";
      func->base = baseName;
      func->type = Type(Signature(type, Type::none), NonNullable, Inexact);
    } else {
      // We cannot add an import, so just make it a trivial function (this is
      // simpler than avoiding calls to logging in all the rest of the logic).
      func->body = builder.makeNop();
      func->type = Type(Signature(type, Type::none), NonNullable, Exact);
    }
    wasm.addFunction(std::move(func));
  }
}

void TranslateToFuzzReader::addImportCallingSupport() {
  if (preserveImportsAndExports) {
    return;
  }

  if (wasm.features.hasReferenceTypes() && closedWorld) {
    // In closed world mode we must *remove* the call-ref* imports, if they
    // exist in the initial content. These are not valid to call in closed-world
    // mode as they call function references. (Another solution here would be to
    // make closed-world issue validation errors on these imports, but that
    // would require changes to the general-purpose validator.)
    for (auto& func : wasm.functions) {
      if (func->imported() && func->module == "fuzzing-support" &&
          func->base.startsWith("call-ref")) {
        // Make it non-imported, and with a simple body.
        func->module = func->base = Name();
        func->type = func->type.with(Exact);
        auto results = func->getResults();
        func->body =
          results.isConcrete() ? makeConst(results) : makeNop(Type::none);
      }
    }
  }

  // Only add these some of the time, as they inhibit some fuzzing (things like
  // wasm-ctor-eval and wasm-merge are sensitive to the wasm being able to call
  // its own exports, and to care about the indexes of the exports).
  if (oneIn(2) || random.finished()) {
    return;
  }

  auto choice = upTo(16);

  if (choice & 1) {
    // Given an export index, call it from JS.
    // A second parameter has flags. The first bit determines whether we catch
    // and rethrow all exceptions. (This ends up giving us the same signature
    // and behavior as when we do not rethrow, so we just add the flags here
    // rather than another export.)
    callExportImportName = Names::getValidFunctionName(wasm, "call-export");
    auto func = std::make_unique<Function>();
    func->name = callExportImportName;
    func->module = "fuzzing-support";
    func->base = "call-export";
    func->type =
      Type(Signature({Type::i32, Type::i32}, Type::none), NonNullable, Inexact);
    wasm.addFunction(std::move(func));
  }

  if (choice & 2) {
    // Given an export index, call it from JS and catch all exceptions. Return
    // whether we caught. Exceptions are common (if the index is invalid, in
    // particular), so a variant that catches is useful to avoid halting.
    callExportCatchImportName =
      Names::getValidFunctionName(wasm, "call-export-catch");
    auto func = std::make_unique<Function>();
    func->name = callExportCatchImportName;
    func->module = "fuzzing-support";
    func->base = "call-export-catch";
    func->type = Type(Signature(Type::i32, Type::i32), NonNullable, Inexact);
    wasm.addFunction(std::move(func));
  }

  // If the wasm will be used for closed-world testing, we cannot use the
  // call-ref variants, as mentioned before.
  if (wasm.features.hasReferenceTypes() && !closedWorld) {
    if (choice & 4) {
      // Given an funcref, call it from JS.
      callRefImportName = Names::getValidFunctionName(wasm, "call-ref");
      auto func = std::make_unique<Function>();
      func->name = callRefImportName;
      func->module = "fuzzing-support";
      func->base = "call-ref";
      // As call-export, there is a flags param that allows us to catch+rethrow
      // all exceptions.
      func->type =
        Type(Signature({Type(HeapType::func, Nullable), Type::i32}, Type::none),
             NonNullable,
             Inexact);
      wasm.addFunction(std::move(func));
    }

    if (choice & 8) {
      // Given an funcref, call it from JS and catch all exceptions (similar
      // to callExportCatch), return 1 if we caught).
      callRefCatchImportName =
        Names::getValidFunctionName(wasm, "call-ref-catch");
      auto func = std::make_unique<Function>();
      func->name = callRefCatchImportName;
      func->module = "fuzzing-support";
      func->base = "call-ref-catch";
      func->type = Type(Signature(Type(HeapType::func, Nullable), Type::i32),
                        NonNullable,
                        Inexact);
      wasm.addFunction(std::move(func));
    }
  }
}

void TranslateToFuzzReader::addImportThrowingSupport() {
  if (random.finished()) {
    return;
  }
  // Throw some kind of exception from JS. If we send 0 then a pure JS
  // exception is thrown, and any other value is the value in a wasm tag.
  throwImportName = Names::getValidFunctionName(wasm, "throw");
  auto func = std::make_unique<Function>();
  func->name = throwImportName;
  if (!preserveImportsAndExports) {
    func->module = "fuzzing-support";
    func->base = "throw";
    func->type = Type(Signature(Type::i32, Type::none), NonNullable, Inexact);
  } else {
    // As with logging, implement in a trivial way when we cannot add imports.
    func->body = builder.makeNop();
    func->type = Type(Signature(Type::i32, Type::none), NonNullable, Exact);
  }
  wasm.addFunction(std::move(func));
}

void TranslateToFuzzReader::addImportTableSupport() {
  // For the table imports to be able to do anything, we must export a table
  // for them. For simplicity, use the funcref table we use internally, though
  // we could pick one at random, support non-funcref ones, and even export
  // multiple ones TODO
  if (!funcrefTableName || random.finished()) {
    return;
  }

  // If a "table" export already exists, skip fuzzing these imports, as the
  // current export may not contain a valid table for it. We also skip if we are
  // not adding imports or exports.
  if (wasm.getExportOrNull("table") || preserveImportsAndExports) {
    return;
  }

  // Do not always export the table even if we can, as it inhibits some things
  // in the fuzzer (with this export, the wasm becomes more sensitive to
  // otherwise inconsequential changes: calling the table-get/set imports is
  // influenced by the existence of this export).
  if (!random.oneIn(3)) {
    return;
  }

  // Export the table.
  wasm.addExport(
    builder.makeExport("table", funcrefTableName, ExternalKind::Table));

  // Get from the table.
  {
    tableGetImportName = Names::getValidFunctionName(wasm, "table-get");
    auto func = std::make_unique<Function>();
    func->name = tableGetImportName;
    func->module = "fuzzing-support";
    func->base = "table-get";
    func->type = Type(Signature({Type::i32}, Type(HeapType::func, Nullable)),
                      NonNullable,
                      Inexact);
    wasm.addFunction(std::move(func));
  }

  // Set into the table.
  {
    tableSetImportName = Names::getValidFunctionName(wasm, "table-set");
    auto func = std::make_unique<Function>();
    func->name = tableSetImportName;
    func->module = "fuzzing-support";
    func->base = "table-set";
    func->type =
      Type(Signature({Type::i32, Type(HeapType::func, Nullable)}, Type::none),
           NonNullable,
           Inexact);
    wasm.addFunction(std::move(func));
  }
}

void TranslateToFuzzReader::addImportSleepSupport() {
  // Fuzz this somewhat rarely, as it may be slow, and only when we can add
  // imports.
  if (preserveImportsAndExports || !oneIn(4) || random.finished()) {
    return;
  }

  // An import that sleeps for a given number of milliseconds, and also receives
  // an integer id. It returns that integer id (useful for tracking separate
  // sleeps).
  sleepImportName = Names::getValidFunctionName(wasm, "sleep");
  auto func = std::make_unique<Function>();
  func->name = sleepImportName;
  func->module = "fuzzing-support";
  func->base = "sleep";
  func->type =
    Type(Signature({Type::i32, Type::i32}, Type::i32), NonNullable, Inexact);
  wasm.addFunction(std::move(func));
}

void TranslateToFuzzReader::addHashMemorySupport() {
  // Don't always add this.
  if (oneIn(2) || random.finished()) {
    return;
  }

  // Add memory hasher helper (for the hash, see hash.h). The function looks
  // like:
  // function hashMemory() {
  //   hash = 5381;
  //   hash = ((hash << 5) + hash) ^ mem[0];
  //   hash = ((hash << 5) + hash) ^ mem[1];
  //   ..
  //   return hash;
  // }
  std::vector<Expression*> contents;
  contents.push_back(
    builder.makeLocalSet(0, builder.makeConst(uint32_t(5381))));
  auto zero = Literal::makeFromInt32(0, wasm.memories[0]->addressType);
  for (Index i = 0; i < fuzzParams->USABLE_MEMORY; i++) {
    contents.push_back(builder.makeLocalSet(
      0,
      builder.makeBinary(
        XorInt32,
        builder.makeBinary(
          AddInt32,
          builder.makeBinary(ShlInt32,
                             builder.makeLocalGet(0, Type::i32),
                             builder.makeConst(uint32_t(5))),
          builder.makeLocalGet(0, Type::i32)),
        builder.makeLoad(1,
                         false,
                         i,
                         1,
                         builder.makeConst(zero),
                         Type::i32,
                         wasm.memories[0]->name))));
  }
  contents.push_back(builder.makeLocalGet(0, Type::i32));
  auto* body = builder.makeBlock(contents);
  hashMemoryName = Names::getValidFunctionName(wasm, "hashMemory");
  auto* hasher = wasm.addFunction(builder.makeFunction(
    hashMemoryName,
    Type(Signature(Type::none, Type::i32), NonNullable, Exact),
    {Type::i32},
    body));

  if (!preserveImportsAndExports && !wasm.getExportOrNull("hashMemory")) {
    wasm.addExport(
      builder.makeExport("hashMemory", hasher->name, ExternalKind::Function));
    // Export memory so JS fuzzing can use it
    if (!wasm.getExportOrNull("memory")) {
      wasm.addExport(builder.makeExport(
        "memory", wasm.memories[0]->name, ExternalKind::Memory));
    }
  }
}

void TranslateToFuzzReader::setImportedModule(std::string importedModuleName) {
  importedModule.emplace();

  importedModule->features = FeatureSet::All;
  ModuleReader().read(importedModuleName, *importedModule);
}

void TranslateToFuzzReader::useImportedFunctions() {
  if (!importedModule) {
    return;
  }

  // Add some of the module's exported functions as imports, at a random rate.
  auto rate = upTo(11);
  for (auto& exp : importedModule->exports) {
    if (exp->kind != ExternalKind::Function || upTo(10) >= rate) {
      continue;
    }

    auto* func = importedModule->getFunction(*exp->getInternalName());
    auto name =
      Names::getValidFunctionName(wasm, "primary_" + exp->name.toString());
    // We can import it as its own type, or any (declared) supertype.
    auto type = getSuperType(func->type).with(NonNullable).with(Inexact);
    auto import = builder.makeFunction(name, type, {});
    import->module = "primary";
    import->base = exp->name;
    wasm.addFunction(std::move(import));
  }

  // TODO: All other imports: memories, tables, etc. We must, as we do
  //       with functions, take care to run this *after* the removal of those
  //       imports (as normally we remove them all, as the fuzzer harness will
  //       not provide them, but an imported module is the exception).
}

void TranslateToFuzzReader::useImportedGlobals() {
  if (!importedModule) {
    return;
  }

  // Add some of the module's exported globals as imports, at a random rate.
  auto rate = upTo(11);
  for (auto& exp : importedModule->exports) {
    if (exp->kind != ExternalKind::Global || upTo(10) >= rate) {
      continue;
    }

    auto* global = importedModule->getGlobal(*exp->getInternalName());
    auto name =
      Names::getValidGlobalName(wasm, "primary_" + exp->name.toString());
    // We can import it as its own type, or if immutable, any (declared)
    // supertype.
    Type type;
    Builder::Mutability mutability;
    if (global->mutable_) {
      mutability = Builder::Mutable;
      type = global->type;
    } else {
      mutability = Builder::Immutable;
      type = getSuperType(global->type);
    }
    auto import = builder.makeGlobal(name, type, nullptr, mutability);
    import->module = "primary";
    import->base = exp->name;
    useGlobalLater(wasm.addGlobal(std::move(import)));
  }
}

TranslateToFuzzReader::FunctionCreationContext::FunctionCreationContext(
  TranslateToFuzzReader& parent, Function* func)
  : parent(parent), func(func) {
  parent.funcContext = this;

  // Note the types of all locals.
  computeTypeLocals();

  // Find the right index for labelIndex: we emit names like label$5, so we need
  // the index to be larger than all currently existing.
  if (!func->body) {
    return;
  }

  struct Finder : public PostWalker<Finder, UnifiedExpressionVisitor<Finder>> {
    Index maxIndex = 0;

    void visitExpression(Expression* curr) {
      // Note all scope names, and fix up all uses.
      BranchUtils::operateOnScopeNameDefs(curr, [&](Name& name) {
        if (name.is()) {
          if (name.startsWith("label$")) {
            auto str = name.toString();
            str = str.substr(6);
            Index index = atoi(str.c_str());
            maxIndex = std::max(maxIndex, index + 1);
          }
        }
      });
    }
  } finder;
  finder.walk(func->body);
  labelIndex = finder.maxIndex;
}

TranslateToFuzzReader::FunctionCreationContext::~FunctionCreationContext() {
  // We must ensure non-nullable locals validate. Later down we'll run
  // TypeUpdating::handleNonDefaultableLocals which will make them validate by
  // turning them nullable + add ref.as_non_null to fix up types. That has the
  // downside of making them trap at runtime, however, and also we lose the non-
  // nullability in the type, so we prefer to do a manual fixup that avoids a
  // trap, which we do by writing a non-nullable value into the local at the
  // function entry.
  // TODO: We could be more precise and use a LocalGraph here, at the cost of
  //       doing more work.
  LocalStructuralDominance info(
    func, parent.wasm, LocalStructuralDominance::NonNullableOnly);
  for (auto index : info.nonDominatingIndices) {
    // Do not always do this, but with high probability, to reduce the amount of
    // traps.
    if (!parent.oneIn(5)) {
      auto* value = parent.makeTrivial(func->getLocalType(index));
      func->body = parent.builder.makeSequence(
        parent.builder.makeLocalSet(index, value), func->body);
    }
  }

  // Then, to handle remaining cases we did not just fix up, do the general
  // fixup to ensure we validate.
  TypeUpdating::handleNonDefaultableLocals(func, parent.wasm);

  assert(breakableStack.empty());
  assert(hangStack.empty());
  parent.funcContext = nullptr;
}

Expression* TranslateToFuzzReader::makeHangLimitCheck() {
  // If the hang limit global reaches 0 then we trap and reset it. That allows
  // calls to other exports to proceed, with hang checking, after the trap halts
  // the currently called export.
  return builder.makeSequence(
    builder.makeIf(
      builder.makeUnary(UnaryOp::EqZInt32,
                        builder.makeGlobalGet(HANG_LIMIT_GLOBAL, Type::i32)),
      builder.makeSequence(builder.makeGlobalSet(HANG_LIMIT_GLOBAL,
                                                 builder.makeConst(int32_t(
                                                   fuzzParams->HANG_LIMIT))),
                           builder.makeUnreachable())),
    builder.makeGlobalSet(
      HANG_LIMIT_GLOBAL,
      builder.makeBinary(BinaryOp::SubInt32,
                         builder.makeGlobalGet(HANG_LIMIT_GLOBAL, Type::i32),
                         builder.makeConst(int32_t(1)))));
}

Expression* TranslateToFuzzReader::makeImportLogging() {
  auto type = getLoggableType();
  return builder.makeCall(logImportNames[type], {make(type)}, Type::none);
}

Expression* TranslateToFuzzReader::makeImportThrowing(Type type) {
  // TODO: This and makeThrow should probably be rare, as they halt the program.

  // We throw from the import, so this call appears to be none and not
  // unreachable.
  assert(type == Type::none);

  // An argument of 0 means to throw a JS exception, and otherwise the value in
  // a wasm tag. Emit 0 or non-zero with ~equal probability.
  Expression* arg;
  if (oneIn(2)) {
    arg = builder.makeConst(int32_t(0));
  } else {
    arg = makeConst(Type::i32);
  }
  return builder.makeCall(throwImportName, {arg}, Type::none);
}

Expression* TranslateToFuzzReader::makeImportTableGet() {
  assert(tableGetImportName);
  return builder.makeCall(
    tableGetImportName, {make(Type::i32)}, Type(HeapType::func, Nullable));
}

Expression* TranslateToFuzzReader::makeImportTableSet(Type type) {
  assert(type == Type::none);
  assert(tableSetImportName);
  return builder.makeCall(
    tableSetImportName,
    {make(Type::i32), makeBasicRef(Type(HeapType::func, Nullable))},
    Type::none);
}

Expression* TranslateToFuzzReader::makeImportCallCode(Type type) {
  // Call code: either an export or a ref. Each has a catching and non-catching
  // variant. The catching variants return i32, the others none.
  assert(type == Type::none || type == Type::i32);
  auto catching = type == Type::i32;
  auto exportTarget =
    catching ? callExportCatchImportName : callExportImportName;
  auto refTarget = catching ? callRefCatchImportName : callRefImportName;

  // We want to call a ref less often, as refs are more likely to error (a
  // function reference can have arbitrary params and results, including things
  // that error on the JS boundary; an export is already filtered for such
  // things in some cases - when we legalize the boundary - and even if not, we
  // emit lots of void(void) functions - all the invoke_foo functions - that are
  // safe to call).
  if (refTarget) {
    // This matters a lot more in the variants that do *not* catch (in the
    // catching ones, we just get a result of 1, but when not caught it halts
    // execution).
    if ((catching && (!exportTarget || oneIn(2))) || (!catching && oneIn(4))) {
      // Most of the time make a non-nullable funcref, to avoid errors.
      auto refType = Type(HeapType::func, oneIn(10) ? Nullable : NonNullable);
      std::vector<Expression*> args = {make(refType)};
      if (!catching) {
        // Only the first bit matters here, so we can send anything (this is
        // future-proof for later bits, and has no downside now).
        args.push_back(make(Type::i32));
      }
      return builder.makeCall(refTarget, args, type);
    }
  }

  if (!exportTarget) {
    // We decided not to emit a call-ref here, due to fear of erroring, and
    // there is no call-export, so just emit something trivial.
    return makeTrivial(type);
  }

  // Pick the maximum export index to call.
  Index maxIndex = wasm.exports.size();
  if (type == Type::i32) {
    // This swallows errors, so we can be less careful, but we do still want to
    // avoid swallowing a lot as executing code is more interesting. (Note that
    // even though we double here, the risk is not that great: we are still
    // adding functions as we go, so the first half of functions/exports can
    // double here and still end up in bounds by the time we've added them all.)
    maxIndex = (maxIndex + 1) * 2;
  }

  // Most of the time, call a valid export index in the range we picked, but
  // sometimes allow anything at all.
  auto* index = make(Type::i32);
  if (!allowOOB || !oneIn(10)) {
    index = builder.makeBinary(
      RemUInt32, index, builder.makeConst(int32_t(maxIndex)));
  }

  // The non-catching variants send a flags argument, which says whether to
  // catch+rethrow.
  std::vector<Expression*> args = {index};
  if (!catching) {
    // Only the first bit matters here, so we can send anything (this is
    // future-proof for later bits, and has no downside now).
    args.push_back(make(Type::i32));
  }
  return builder.makeCall(exportTarget, args, type);
}

Expression* TranslateToFuzzReader::makeImportSleep(Type type) {
  // Sleep for some ms, and return a given id.
  auto* ms = make(Type::i32);
  auto id = make(Type::i32);
  return builder.makeCall(sleepImportName, {ms, id}, Type::i32);
}

Expression* TranslateToFuzzReader::makeMemoryHashLogging() {
  auto* hash = builder.makeCall(hashMemoryName, {}, Type::i32);
  return builder.makeCall(logImportNames[Type::i32], {hash}, Type::none);
}

void TranslateToFuzzReader::processFunctions() {
  // Functions that are eligible for being modded. We only do so once to each
  // function, at most, so once we do we remove it from here.
  std::vector<Function*> moddable;

  // Defined initial functions are moddable.
  for (auto& func : wasm.functions) {
    if (!func->imported()) {
      moddable.push_back(func.get());
    }
  }

  auto numInitialExports = wasm.exports.size();

  // Add invocations, which can help execute the code here even if the function
  // was not exported (or was exported but with a signature that traps
  // immediately, like receiving a non-nullable ref, that the fuzzer can't
  // provide from JS). Note we cannot iterate on wasm.functions because
  // addInvocations modifies that.
  for (auto* func : moddable) {
    addInvocations(func);
  }

  // We do not want to always mod in the same frequency. Pick a chance to mod a
  // function. When the chance is maximal we will mod every single function, and
  // immediately after creating it; when the chance is minimal we will not mod
  // anything; values in the middle will end up randomly modding some functions,
  // at random times (random times are useful because we might create function
  // A, then B, then mod A, and since B has already been created, the modding of
  // A may lead to calls to B).
  const int RESOLUTION = 10;
  auto chance = upTo(RESOLUTION + 1);

  // We do not want to always add new functions, if there are initial ones:
  // adding many additional functions will cause a lot of global properties to
  // change, e.g., if the initial content was a carefully crafted testcase
  // showing some situation of reads and writes between struct fields, adding
  // many new functions will likely add reads and writes to all the fields,
  // preventing global operations like field removal or immutabilification.
  auto allowNew = !haveInitialFunctions || !oneIn(10);

  // Keep working while we have random data.
  while (!random.finished()) {
    if (!moddable.empty() && upTo(RESOLUTION) < chance) {
      // Mod an existing function.
      auto index = upTo(moddable.size());
      auto* func = moddable[index];
      modFunction(func);

      // Remove this function from the vector by swapping the last item to its
      // place, and truncating.
      moddable[index] = moddable.back();
      moddable.pop_back();
    } else if (allowNew) {
      // Add a new function
      auto* func = addFunction();
      addInvocations(func);

      // It may be modded later, if we allow out-of-bounds: we emit OOB checks
      // in the code we just generated, and any changes could break that.
      if (allowOOB) {
        moddable.push_back(func);
      }
    } else {
      // If we found nothing to do, consume some data so that we make progress
      // towards the loop ending.
      get();
    }
  }

  // Interpose on initial exports. When initial content contains exports, it can
  // be useful to add new code that executes in them, rather than just adding
  // new exports later. To some extent modifying the initially-exported function
  // gives us that, but typically these are small changes, not calls to entirely
  // new code (and this is especially important when preserveImportsAndExports,
  // as in that mode we do not add new exports, so this interposing is our main
  // chance to run new code using the existing exports).
  //
  // Interpose with a call before the old code. We do a call here so that we end
  // up running a useful amount of new code (rather than just make(none) which
  // would only emit something local in the current function, and which depends
  // on its contents).
  // TODO: We could also interpose after, either in functions without results,
  //       or by saving the results to a temp local as we call.
  //
  // Specifically, we will call functions, for simplicity, with no params or
  // results. Such functions exist in abundance in general, because the
  // invocations we add look exactly that way. First, find all such functions,
  // and then find places to interpose calls to them.
  std::vector<Name> noParamsOrResultFuncs;
  for (auto& func : wasm.functions) {
    if (func->getParams() == Type::none && func->getResults() == Type::none) {
      noParamsOrResultFuncs.push_back(func->name);
    }
  }
  if (!noParamsOrResultFuncs.empty()) {
    for (Index i = 0; i < numInitialExports; i++) {
      auto& exp = wasm.exports[i];
      if (exp->kind == ExternalKind::Function && upTo(RESOLUTION) < chance) {
        auto* func = wasm.getFunction(*exp->getInternalName());
        if (!func->imported()) {
          auto* call =
            builder.makeCall(pick(noParamsOrResultFuncs), {}, Type::none);
          func->body = builder.makeSequence(call, func->body);
        }
      }
    }
  }

  // At the very end, add hang limit checks (so no modding can override them).
  if (fuzzParams->HANG_LIMIT > 0) {
    for (auto& func : wasm.functions) {
      if (!func->imported()) {
        addHangLimitChecks(func.get());
      }
    }
  }
}

// TODO: return std::unique_ptr<Function>
Function* TranslateToFuzzReader::addFunction() {
  LOGGING_PERCENT = upToSquared(100);
  auto allocation = std::make_unique<Function>();
  auto* func = allocation.get();
  func->name = Names::getValidFunctionName(wasm, "func");

  // Pick params and results. There may be an interesting heap type we can use.
  std::optional<HeapType> funcType;
  auto& funcTypes = interestingHeapSubTypes[HeapTypes::func];
  if (!funcTypes.empty() && oneIn(2)) {
    auto type = pick(funcTypes);
    if (type.getSignature().params.size() < (size_t)fuzzParams->MAX_PARAMS) {
      // This is suitable for us.
      funcType = type;
    }
  }
  if (!funcType) {
    // Generate a new type on the fly.
    Index numParams = upToSquared(fuzzParams->MAX_PARAMS);
    std::vector<Type> params;
    params.reserve(numParams);
    for (Index i = 0; i < numParams; i++) {
      auto type = getSingleConcreteType();
      params.push_back(type);
    }
    auto paramType = Type(params);
    auto resultType = getControlFlowType();
    funcType = Signature(paramType, resultType);
  }
  func->type = Type(*funcType, NonNullable, Exact);

  Index numVars = upToSquared(fuzzParams->MAX_VARS);
  for (Index i = 0; i < numVars; i++) {
    auto type = getConcreteType();
    if (!TypeUpdating::canHandleAsLocal(type)) {
      type = Type::i32;
    }
    func->vars.push_back(type);
  }
  // Generate the function creation context after we filled in locals, which it
  // will scan.
  FunctionCreationContext context(*this, func);
  // with small chance, make the body unreachable
  auto bodyType = func->getResults();
  if (oneIn(10)) {
    bodyType = Type::unreachable;
  }
  // with reasonable chance make the body a block
  if (oneIn(2)) {
    func->body = makeBlock(bodyType);
  } else {
    func->body = make(bodyType);
  }

  // Add hang limit checks after all other operations on the function body.
  wasm.addFunction(std::move(allocation));
  // Export some functions, but not all (to allow inlining etc.). Try to export
  // at least one, though, to keep each testcase interesting. Avoid non-
  // nullable params, as those cannot be constructed by the fuzzer on the
  // outside.
  auto paramType = func->getParams();
  auto resultType = func->getResults();
  bool validExportParams =
    std::all_of(paramType.begin(), paramType.end(), [&](Type t) {
      return t.isDefaultable() && isValidPublicType(t);
    });
  if (!preserveImportsAndExports && validExportParams &&
      isValidPublicType(resultType) && (numAddedFunctions == 0 || oneIn(2)) &&
      !wasm.getExportOrNull(func->name)) {
    wasm.addExport(
      Builder::makeExport(func->name, func->name, ExternalKind::Function));
  }
  // add some to an elem segment TODO we could do this for imported funcs too
  while (oneIn(3) && !random.finished()) {
    auto type = func->type;
    std::vector<ElementSegment*> compatibleSegments;
    ModuleUtils::iterActiveElementSegments(wasm, [&](ElementSegment* segment) {
      if (Type::isSubType(type, segment->type)) {
        compatibleSegments.push_back(segment);
      }
    });
    auto& randomElem = compatibleSegments[upTo(compatibleSegments.size())];
    randomElem->data.push_back(builder.makeRefFunc(func->name));
  }
  numAddedFunctions++;
  return func;
}

void TranslateToFuzzReader::modFunction(Function* func) {
  FunctionCreationContext context(*this, func);

  dropToLog(func);
  // TODO: if we add OOB checks after creation, then we can do it on
  //       initial contents too, and it may be nice to *not* run these
  //       passes, like we don't run them on new functions. But, we may
  //       still want to run them some of the time, at least, so that we
  //       check variations on initial testcases even at the risk of OOB.
  recombine(func);
  mutate(func);
  fixAfterChanges(func);
}

void TranslateToFuzzReader::addHangLimitChecks(Function* func) {
  // loop limit
  for (auto* loop : FindAll<Loop>(func->body).list) {
    loop->body =
      builder.makeSequence(makeHangLimitCheck(), loop->body, loop->type);
  }
  // recursion limit
  func->body =
    builder.makeSequence(makeHangLimitCheck(), func->body, func->getResults());
  // ArrayNew can hang the fuzzer if the array size is massive. This doesn't
  // cause an OOM (which the fuzzer knows how to ignore) but it just works for
  // many seconds on building the array. To avoid that, limit the size with high
  // probability.
  for (auto* arrayNew : FindAll<ArrayNew>(func->body).list) {
    if (!oneIn(100)) {
      arrayNew->size = builder.makeBinary(
        AndInt32, arrayNew->size, builder.makeConst(int32_t(1024 - 1)));
    }
  }
}

void TranslateToFuzzReader::recombine(Function* func) {
  // Don't always do this.
  if (oneIn(2)) {
    return;
  }
  // First, scan and group all expressions by type.
  struct Scanner
    : public PostWalker<Scanner, UnifiedExpressionVisitor<Scanner>> {
    TranslateToFuzzReader& parent;
    // A map of all expressions, categorized by type.
    InsertOrderedMap<Type, std::vector<Expression*>> exprsByType;
    Scanner(TranslateToFuzzReader& parent) : parent(parent) {}

    void visitExpression(Expression* curr) {
      if (parent.canBeArbitrarilyReplaced(curr)) {
        for (auto type : getRelevantTypes(curr->type)) {
          exprsByType[type].push_back(curr);
        }
      }
    }

    std::vector<Type> getRelevantTypes(Type type) {
      // Given an expression of a type, we can replace not only other
      // expressions with the same type, but also supertypes - since then we'd
      // be replacing with a subtype, which is valid.
      if (!type.isRef()) {
        return {type};
      }

      std::vector<Type> ret;
      ret.push_back(type);

      if (type.isNonNullable()) {
        auto nullable = getRelevantTypes(type.with(Nullable));
        ret.insert(ret.end(), nullable.begin(), nullable.end());
      }
      if (type.isExact()) {
        auto inexact = getRelevantTypes(type.with(Inexact));
        ret.insert(ret.end(), inexact.begin(), inexact.end());
        // Do not consider exact references to supertypes.
        return ret;
      }

      for (auto heapType = type.getHeapType().getSuperType(); heapType;
           heapType = heapType->getSuperType()) {
        ret.push_back(type.with(*heapType));
      }

      return ret;
    }
  };
  Scanner scanner(*this);
  scanner.walk(func->body);
  // Potentially trim the list of possible picks, so replacements are more
  // likely to collide.
  for (auto& pair : scanner.exprsByType) {
    if (oneIn(2)) {
      continue;
    }
    auto& list = pair.second;
    std::vector<Expression*> trimmed;
    size_t num = upToSquared(list.size());
    for (size_t i = 0; i < num; i++) {
      trimmed.push_back(pick(list));
    }
    if (trimmed.empty()) {
      trimmed.push_back(pick(list));
    }
    list.swap(trimmed);
  }
  // Replace them with copies, to avoid a copy into one altering another copy
  for (auto& pair : scanner.exprsByType) {
    for (auto*& item : pair.second) {
      item = ExpressionManipulator::copy(item, wasm);
    }
  }
  // Second, with some probability replace an item with another item having
  // a proper type. (This is not always valid due to nesting of labels, but
  // we'll fix that up later.)
  struct Modder : public PostWalker<Modder, UnifiedExpressionVisitor<Modder>> {
    Module& wasm;
    Scanner& scanner;
    TranslateToFuzzReader& parent;

    Modder(Module& wasm, Scanner& scanner, TranslateToFuzzReader& parent)
      : wasm(wasm), scanner(scanner), parent(parent) {}

    void visitExpression(Expression* curr) {
      if (parent.oneIn(10) && parent.canBeArbitrarilyReplaced(curr)) {
        // Replace it!
        auto& candidates = scanner.exprsByType[curr->type];
        assert(!candidates.empty()); // this expression itself must be there
        auto* rep = parent.pick(candidates);
        replaceCurrent(ExpressionManipulator::copy(rep, wasm));
      }
    }
  };
  Modder modder(wasm, scanner, *this);
  modder.walk(func->body);
  // TODO: A specific form of recombination we should perhaps do more often is
  //       to recombine among an expression's children, and in particular to
  //       reorder them.
}

// Given two expressions, try to replace one of the children of the first with
// the second. For example, given i32.add and an i32.const, the i32.const could
// be placed as either of the children of the i32.add. This tramples the
// existing content there. Returns true if we found a place.
static bool replaceChildWith(Expression* expr, Expression* with) {
  for (auto*& child : ChildIterator(expr)) {
    // To replace, we must have an appropriate type, and we cannot replace a
    // Pop under any circumstances.
    if (Type::isSubType(with->type, child->type) &&
        FindAll<Pop>(child).list.empty()) {
      child = with;
      return true;
    }
  }
  return false;
}

void TranslateToFuzzReader::mutate(Function* func) {
  // We want a 50% chance to not do this at all, and otherwise, we want to pick
  // a different frequency to do it in each function. That gives us more
  // diversity between fuzzings of the same initial content (once we might
  // mutate with 5%, and only change one or two places, while another time we
  // might mutate with 50% and change quite a lot; without this type of
  // mechanism, in a large function the amount of mutations will generally be
  // very close to the mean due to the central limit theorem).
  auto r = upTo(200);
  if (r > 100) {
    return;
  }

  // Prefer lower numbers: We want something like a 10% chance to mutate on
  // average. To achieve that, we raise r/100, which is in the range [0, 1], to
  // the 9th power, giving us a number also in the range [0, 1] with a mean of
  //   \integral_0^1 t^9 dx = 0.1 * t^10 |_0^1 = 0.1
  // As a result, we get a value in the range of 0-100%. (Note that 100% is ok
  // since we can't replace everything anyhow, see below.)
  double t = r;
  t = t / 100;
  t = pow(t, 9);
  Index percentChance = t * 100;
  // Adjust almost-zero frequencies to at least a few %, just so we have some
  // reasonable chance of making some changes.
  percentChance = std::max(percentChance, Index(3));

  // First, find things to replace and their types. SubtypingDiscoverer needs to
  // do this in a single, full walk (as types of children depend on parents, and
  // even block targets).
  struct Finder
    : public ControlFlowWalker<Finder, SubtypingDiscoverer<Finder>> {
    // Maps children we can replace to the types we can replace them with. We
    // only store nontrivial ones (i.e., where the type is not just the child's
    // type).
    std::unordered_map<Expression*, GLBFinder> childTypes;

    // We only care about constraints on Expression* things.
    void noteSubtype(Type sub, Type super) {}
    void noteSubtype(HeapType sub, HeapType super) {}

    void noteSubtype(Type sub, Expression* super) {
      // The expression must be a supertype of a fixed type. Nothing to do.
    }
    void noteSubtype(Expression* sub, Type super) {
      if (super.isRef()) {
        childTypes[sub].note(super);
      }
    }
    void noteSubtype(Expression* sub, Expression* super) {
      noteSubtype(sub, super->type);
    }
    void noteNonFlowSubtype(Expression* sub, Type super) {
      noteSubtype(sub, super);
    }

    // TODO: Many casts can accept the top type. We may need to use visit*(), to
    //       handle each expression class separately.
    void noteCast(HeapType src, Type dst) {}
    void noteCast(Expression* src, Type dst) {}
    void noteCast(Expression* src, Expression* dst) {}
  } finder;

  if (oneIn(2)) {
    // |finder| reads the IR, and it must be totally valid - e.g. breaks have a
    // proper break target - or else we'd hit internal errors. Fix it up first.
    // (Otherwise, fixing it up is done once after mutation, and in that case
    // we can mutate the IR in simple ways but not read it using
    // useSubtypingDiscoverer). We avoid always doing this second fixup as it
    // may bias the code in some ways.
    fixAfterChanges(func);
    finder.walkFunctionInModule(func, &wasm);
  }

  // Next, modify things.
  struct Modder : public PostWalker<Modder, UnifiedExpressionVisitor<Modder>> {
    TranslateToFuzzReader& parent;
    Index percentChance;
    Finder& finder;

    // Whether to replace with unreachable. This can lead to less code getting
    // executed, so we don't want to do it all the time even in a big function.
    bool allowUnreachable;

    Modder(TranslateToFuzzReader& parent, Index percentChance, Finder& finder)
      : parent(parent), percentChance(percentChance), finder(finder) {
      // If the parent allows it then sometimes replace with an unreachable, and
      // sometimes not. Even if we allow it, only do it in certain functions
      // (half the time) and only do it rarely (see below).
      allowUnreachable = parent.allowAddingUnreachableCode && parent.oneIn(2);
    }

    void visitExpression(Expression* curr) {
      // See if we want to replace it.
      if (!parent.canBeArbitrarilyReplaced(curr) ||
          parent.upTo(100) >= percentChance) {
        return;
      }

      // Find the type to replace with.
      auto type = curr->type;
      if (type.isRef()) {
        auto& glb = finder.childTypes[curr];
        if (glb.noted()) {
          type = glb.getGLB();
          // We can only be given a less-refined type (certainly we can replace
          // curr with its own type).
          assert(Type::isSubType(curr->type, type));
        }
      }

      // We can replace in various modes, see below. Generate a random number
      // up to 100 to help us there.
      int mode = parent.upTo(100);

      if (allowUnreachable && mode < 5) {
        replaceCurrent(parent.make(Type::unreachable));
        return;
      }

      // For constants, perform only a small tweaking in some cases.
      // TODO: more minor tweaks to immediates, like making a load atomic or
      // not, changing an offset, etc.
      if (auto* c = curr->dynCast<Const>()) {
        if (mode < 50) {
          c->value = parent.tweak(c->value);
        } else {
          // Just replace the entire thing.
          replaceCurrent(parent.make(type));
        }
        return;
      }

      // Generate a replacement for the expression, and by default replace all
      // of |curr| (including children) with that replacement, but in some
      // cases we can do more subtle things.
      //
      // Note that such a replacement is not always valid due to nesting of
      // labels, but we'll fix that up later. Note also that make() picks a
      // subtype, so this has a chance to replace us with anything that is
      // valid to put here.
      auto* rep = parent.make(type);
      if (mode < 33 && rep->type != Type::none) {
        // This has a non-none type. Replace the output, keeping the
        // expression and its children in a drop. This "interposes" between
        // this expression and its parent, something like this:
        //
        //    (D
        //      (A
        //        (B)
        //        (C)
        //      )
        //    )
        ////
        //    => ;; keep A, replace it in the parent
        //
        //    (D
        //      (block
        //        (drop
        //          (A
        //            (B)
        //            (C)
        //          )
        //        )
        //        (NEW)
        //      )
        //    )
        //
        // We also sometimes try to insert A as a child of NEW, so we actually
        // interpose directly:
        //
        //    (D
        //      (NEW
        //        (A
        //          (B)
        //          (C)
        //        )
        //      )
        //    )
        //
        // We do not do that all the time, as inserting a drop is actually an
        // important situation to test: the drop makes the output of A unused,
        // which may let optimizations remove it.
        if ((mode & 1) && replaceChildWith(rep, curr)) {
          // We managed to replace one of the children with curr, and have
          // nothing more to do.
        } else {
          // Drop curr and append.
          rep = parent.builder.makeSequence(parent.builder.makeDrop(curr), rep);
        }
      } else if (mode >= 66 && !Properties::isControlFlowStructure(curr)) {
        ChildIterator children(curr);
        auto numChildren = children.getNumChildren();
        if (numChildren > 0 && numChildren < 5) {
          // This is a normal (non-control-flow) expression with at least one
          // child (and not an excessive amount of them; see the processing
          // below). "Interpose" between the children and this expression by
          // keeping them and replacing the parent |curr|. We do this by
          // generating drops of the children, like this:
          //
          //  (A
          //    (B)
          //    (C)
          //  )
          //
          //  => ;; keep children, replace A
          //
          //  (block
          //    (drop (B))
          //    (drop (C))
          //    (NEW)
          //  )
          //
          auto* block = parent.builder.makeBlock();
          for (auto* child : children) {
            // Only drop the child if we can't replace it as one of NEW's
            // children. This does a linear scan of |rep| which is the reason
            // for the above limit on the number of children.
            if (!replaceChildWith(rep, child)) {
              block->list.push_back(parent.builder.makeDrop(child));
            }
          }

          if (!block->list.empty()) {
            // We need the block, that is, we did not find a place for all the
            // children.
            block->list.push_back(rep);
            block->finalize();
            rep = block;
          }
        }
      }
      replaceCurrent(rep);
    }
  };

  Modder modder(*this, percentChance, finder);
  modder.walkFunctionInModule(func, &wasm);
}

void TranslateToFuzzReader::fixAfterChanges(Function* func) {
  struct Fixer
    : public ExpressionStackWalker<Fixer, UnifiedExpressionVisitor<Fixer>> {
    Module& wasm;
    TranslateToFuzzReader& parent;

    Fixer(Module& wasm, TranslateToFuzzReader& parent)
      : wasm(wasm), parent(parent) {}

    // Track seen names to find duplication, which is invalid.
    std::set<Name> seen;

    void visitExpression(Expression* curr) {
      // Note all scope names, and fix up all uses.
      BranchUtils::operateOnScopeNameDefs(curr, [&](Name& name) {
        if (name.is()) {
          if (seen.count(name)) {
            replace();
          } else {
            seen.insert(name);
          }
        }
      });
      BranchUtils::operateOnScopeNameUses(curr, [&](Name& name) {
        if (name.is()) {
          replaceIfInvalid(name);
        }
      });
    }

    void replaceIfInvalid(Name target) {
      if (!hasBreakTarget(target)) {
        // There is no valid parent, replace with something trivially safe.
        replace();
      }
    }

    void replace() { replaceCurrent(parent.makeTrivial(getCurrent()->type)); }

    bool hasBreakTarget(Name name) {
      // The break must be on top.
      assert(!expressionStack.empty());
      if (expressionStack.size() < 2) {
        // There must be a scope for this break to be valid.
        return false;
      }
      Index i = expressionStack.size() - 2;
      while (1) {
        auto* curr = expressionStack[i];
        bool has = false;
        BranchUtils::operateOnScopeNameDefs(curr, [&](Name& def) {
          if (def == name) {
            has = true;
          }
        });
        if (has) {
          return true;
        }
        if (i == 0) {
          return false;
        }
        i--;
      }
    }

    void visitRethrow(Rethrow* curr) {
      if (!isValidTryRef(curr->target, curr)) {
        replace();
      } else {
        visitExpression(curr);
      }
    }

    void visitTry(Try* curr) {
      if (curr->delegateTarget.is() &&
          !isValidTryRef(curr->delegateTarget, curr)) {
        replace();
      } else {
        visitExpression(curr);
      }
    }

    // Check if a reference to a try is valid.
    bool isValidTryRef(Name target, Expression* curr) {
      // The rethrow or try must be on top.
      assert(!expressionStack.empty());
      assert(expressionStack.back() == curr);
      if (expressionStack.size() < 2) {
        // There must be a parent try for this to be valid.
        return false;
      }
      Index i = expressionStack.size() - 2;
      // Rethrows and try-delegates must target a try. Find it.
      while (1) {
        if (auto* tryy = expressionStack[i]->dynCast<Try>()) {
          // A rethrow must be nested in a catch of that try, not the body. A
          // try-delegate is the reverse. Look at the child above us to check,
          // when we find the proper try.
          if (tryy->name == target) {
            assert(i + 1 < expressionStack.size());
            auto* child = expressionStack[i + 1];
            if (curr->is<Rethrow>()) {
              return child != tryy->body;
            }
            assert(curr->is<Try>());
            return child == tryy->body;
          }
        }
        if (i == 0) {
          // We never found our try.
          return false;
        }
        i--;
      }
    }
  } fixer(wasm, *this);
  fixer.walk(func->body);

  // Refinalize at the end, after labels are all fixed up.
  ReFinalize().walkFunctionInModule(func, &wasm);
}

void TranslateToFuzzReader::modifyInitialFunctions() {
  if (wasm.functions.empty()) {
    return;
  }
  // Do not iterate directly on wasm.functions itself (that is, avoid
  //   for (x : wasm.functions)
  // ) as we may add to it as we go through the functions - make() can add new
  // functions to implement a RefFunc. Instead, use an index. This avoids an
  // iterator invalidation, and also we will process those new functions at
  // the end (currently that is not needed atm, but it might in the future).
  for (Index i = 0; i < wasm.functions.size(); i++) {
    auto* func = wasm.functions[i].get();
    // We can't allow extra imports, as the fuzzing infrastructure wouldn't
    // know what to provide. Keep only our own fuzzer imports (or, if we are
    // preserving imports, keep them all).
    if (func->imported() &&
        (func->module == "fuzzing-support" || preserveImportsAndExports)) {
      continue;
    }
    if (func->imported()) {
      FunctionCreationContext context(*this, func);
      func->module = func->base = Name();
      func->type = func->type.with(Exact);
      func->body = make(func->getResults());
    }
  }

  // Remove a start function - the fuzzing harness expects code to run only
  // from exports.
  wasm.start = Name();
}

void TranslateToFuzzReader::dropToLog(Function* func) {
  // Don't always do this.
  if (oneIn(2)) {
    return;
  }
  struct Modder : public PostWalker<Modder> {
    Module& wasm;
    TranslateToFuzzReader& parent;

    Modder(Module& wasm, TranslateToFuzzReader& parent)
      : wasm(wasm), parent(parent) {}

    void visitDrop(Drop* curr) {
      if (parent.isLoggableType(curr->value->type) && parent.oneIn(2)) {
        auto target = parent.logImportNames[curr->value->type];
        replaceCurrent(
          parent.builder.makeCall(target, {curr->value}, Type::none));
      }
    }
  };
  Modder modder(wasm, *this);
  modder.walk(func->body);
}

void TranslateToFuzzReader::addInvocations(Function* func) {
  Name name = func->name.toString() + std::string("_invoker");
  if (wasm.getFunctionOrNull(name) || wasm.getExportOrNull(name)) {
    return;
  }
  auto invoker =
    builder.makeFunction(name, Type(Signature(), NonNullable, Exact), {});
  Block* body = builder.makeBlock();
  invoker->body = body;
  FunctionCreationContext context(*this, invoker.get());
  std::vector<Expression*> invocations;
  while (oneIn(2) && !random.finished()) {
    std::vector<Expression*> args;
    for (const auto& type : func->getParams()) {
      args.push_back(makeConst(type));
    }
    Expression* invoke = builder.makeCall(func->name, args, func->getResults());
    if (func->getResults().isConcrete()) {
      invoke = builder.makeDrop(invoke);
    }
    invocations.push_back(invoke);
    // log out memory in some cases
    if (hashMemoryName && oneIn(2)) {
      invocations.push_back(makeMemoryHashLogging());
    }
  }
  if (invocations.empty()) {
    return;
  }
  body->list.set(invocations);
  wasm.addFunction(std::move(invoker));

  // Most of the benefit of invocations is lost when we do not add exports for
  // them, but still, they might be called by existing functions.
  if (!preserveImportsAndExports) {
    wasm.addExport(builder.makeExport(name, name, ExternalKind::Function));
  }
}

Expression* TranslateToFuzzReader::make(Type type) {
  type = getSubType(type);
  if (trivialNesting) {
    // We are nested under a makeTrivial call, so only emit something trivial.
    return makeTrivial(type);
  }
  // When we should stop, emit something small (but not necessarily trivial).
  if (random.finished() ||
      nesting >= 5 * fuzzParams->NESTING_LIMIT || // hard limit
      (nesting >= fuzzParams->NESTING_LIMIT && !oneIn(3))) {
    if (type.isConcrete()) {
      if (!funcContext || oneIn(2)) {
        return makeConst(type);
      } else {
        return makeLocalGet(type);
      }
    } else if (type == Type::none) {
      assert(funcContext);
      if (oneIn(2)) {
        return makeNop(type);
      } else {
        return makeLocalSet(type);
      }
    }
    assert(type == Type::unreachable);
    return makeTrivial(type);
  }
  nesting++;
  Expression* ret = nullptr;
  if (!funcContext) {
    // We are in a global init or similar, and can only emit constants.
    ret = makeConst(type);
  } else if (type.isConcrete()) {
    ret = _makeConcrete(type);
  } else if (type == Type::none) {
    ret = _makenone();
  } else {
    assert(type == Type::unreachable);
    ret = _makeunreachable();
  }
  if (!Type::isSubType(ret->type, type)) {
    Fatal() << "Did not generate the right subtype of "
            << ModuleType(wasm, type) << ", instead we have "
            << ModuleType(wasm, ret->type) << " : "
            << ModuleExpression(wasm, ret) << '\n';
  }
  nesting--;
  return ret;
}

Expression* TranslateToFuzzReader::_makeConcrete(Type type) {
  bool canMakeControlFlow = !type.isTuple() || wasm.features.hasMultivalue();
  using Self = TranslateToFuzzReader;
  FeatureOptions<Expression* (Self::*)(Type)> options;
  using WeightedOption = decltype(options)::WeightedOption;
  options.add(FeatureSet::MVP,
              WeightedOption{&Self::makeLocalGet, VeryImportant},
              WeightedOption{&Self::makeLocalSet, VeryImportant},
              WeightedOption{&Self::makeGlobalGet, Important},
              WeightedOption{&Self::makeConst, Important});
  if (canMakeControlFlow) {
    options
      .add(FeatureSet::MVP,
           WeightedOption{&Self::makeBlock, Important},
           WeightedOption{&Self::makeIf, Important},
           WeightedOption{&Self::makeLoop, Important},
           WeightedOption{&Self::makeBreak, Important},
           &Self::makeCall,
           &Self::makeCallIndirect)
      .add(FeatureSet::ExceptionHandling, &Self::makeTry)
      .add(FeatureSet::ExceptionHandling, &Self::makeTryTable)
      .add(FeatureSet::ReferenceTypes | FeatureSet::GC, &Self::makeCallRef)
      .add(FeatureSet::ReferenceTypes | FeatureSet::GC, &Self::makeBrOn);
  }
  if (type.isSingle()) {
    options
      .add(FeatureSet::MVP,
           WeightedOption{&Self::makeUnary, Important},
           WeightedOption{&Self::makeBinary, Important},
           &Self::makeSelect)
      .add(FeatureSet::Multivalue, &Self::makeTupleExtract);
  }
  if (type.isSingle() && !type.isRef()) {
    options.add(FeatureSet::MVP, {&Self::makeLoad, Important});
    options.add(FeatureSet::SIMD, &Self::makeSIMD);
  }
  if (type.isInteger()) {
    options.add(FeatureSet::Atomics, &Self::makeAtomic);
  }
  if (type == Type::i32) {
    if (callExportCatchImportName || callRefCatchImportName) {
      options.add(FeatureSet::MVP, &Self::makeImportCallCode);
    }
    if (sleepImportName) {
      options.add(FeatureSet::MVP, &Self::makeImportSleep);
    }
    options.add(FeatureSet::ReferenceTypes, &Self::makeRefIsNull);
    options.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
                // Prioritize ref.eq heavily as it is the one instruction that
                // tests reference identity.
                {&Self::makeRefEq, VeryImportant},
                &Self::makeRefTest,
                &Self::makeI31Get);
    options.add(FeatureSet::ReferenceTypes | FeatureSet::GC |
                  FeatureSet::Strings,
                &Self::makeStringEncode,
                &Self::makeStringEq,
                &Self::makeStringMeasure,
                &Self::makeStringGet);
  }
  if (type.isTuple()) {
    options.add(FeatureSet::Multivalue, &Self::makeTupleMake);
  }
  if (type.isRef()) {
    auto heapType = type.getHeapType();
    if (heapType.isBasic()) {
      options.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
                  &Self::makeBasicRef);
      if (type.isNullable() && funcContext) {
        if (heapType == HeapType::func) {
          options.add(FeatureSet::ReferenceTypes, &Self::makeTableGet);
        }
        if (heapType == HeapType::exn) {
          options.add(FeatureSet::ExceptionHandling, &Self::makeTableGet);
        }
      }
    } else {
      options.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
                  &Self::makeCompoundRef);
    }
    if (type.isCastable()) {
      // Exact casts are only allowed with custom descriptors enabled.
      if (type.isInexact() || wasm.features.hasCustomDescriptors()) {
        options.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
                    &Self::makeRefCast);
      }
    }
    if (heapType.getDescribedType()) {
      options.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
                  &Self::makeRefGetDesc);
    }
  }
  if (wasm.features.hasGC()) {
    if (typeStructFields.find(type) != typeStructFields.end()) {
      options.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
                  &Self::makeStructGet);
    }
    if (typeArrays.find(type) != typeArrays.end()) {
      options.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
                  &Self::makeArrayGet);
    }
  }
  return (this->*pick(options))(type);
}

Expression* TranslateToFuzzReader::_makenone() {
  auto choice = upTo(100);
  if (choice < LOGGING_PERCENT) {
    if (!hashMemoryName || choice < LOGGING_PERCENT / 2) {
      return makeImportLogging();
    } else {
      return makeMemoryHashLogging();
    }
  }
  using Self = TranslateToFuzzReader;
  auto options = FeatureOptions<Expression* (Self::*)(Type)>();
  using WeightedOption = decltype(options)::WeightedOption;
  options
    .add(FeatureSet::MVP,
         WeightedOption{&Self::makeLocalSet, VeryImportant},
         WeightedOption{&Self::makeBlock, Important},
         WeightedOption{&Self::makeIf, Important},
         WeightedOption{&Self::makeLoop, Important},
         WeightedOption{&Self::makeBreak, Important},
         WeightedOption{&Self::makeStore, Important},
         &Self::makeCall,
         &Self::makeCallIndirect,
         &Self::makeDrop,
         &Self::makeNop,
         &Self::makeGlobalSet)
    .add(FeatureSet::BulkMemory, &Self::makeBulkMemory)
    .add(FeatureSet::Atomics, &Self::makeAtomic)
    .add(FeatureSet::ReferenceTypes, &Self::makeTableSet)
    .add(FeatureSet::ExceptionHandling, &Self::makeTry)
    .add(FeatureSet::ExceptionHandling, &Self::makeTryTable)
    .add(FeatureSet::ExceptionHandling, &Self::makeImportThrowing)
    .add(FeatureSet::ReferenceTypes | FeatureSet::GC, &Self::makeCallRef)
    .add(FeatureSet::ReferenceTypes | FeatureSet::GC, &Self::makeStructSet)
    .add(FeatureSet::ReferenceTypes | FeatureSet::GC, &Self::makeArraySet)
    .add(FeatureSet::ReferenceTypes | FeatureSet::GC, &Self::makeBrOn)
    .add(FeatureSet::ReferenceTypes | FeatureSet::GC,
         &Self::makeArrayBulkMemoryOp);
  if (tableSetImportName) {
    options.add(FeatureSet::ReferenceTypes, &Self::makeImportTableSet);
  }
  if (callExportImportName || callRefImportName) {
    options.add(FeatureSet::MVP, &Self::makeImportCallCode);
  }
  return (this->*pick(options))(Type::none);
}

Expression* TranslateToFuzzReader::_makeunreachable() {
  using Self = TranslateToFuzzReader;
  auto options = FeatureOptions<Expression* (Self::*)(Type)>();
  using WeightedOption = decltype(options)::WeightedOption;
  // Many instructions can become unreachable if a child is unreachable. We
  // create such code in mutate() (see |allowUnreachable| there). The list of
  // instructions here are those that necessarily have unreachable type, and are
  // only created here (though they might have other variations that are
  // reachable, like br has br_if that is created elsewhere, and we have call
  // here because of return calls, etc.).
  options
    .add(FeatureSet::MVP,
         WeightedOption{&Self::makeBreak, Important},
         &Self::makeUnreachable,
         &Self::makeCall,
         &Self::makeCallIndirect,
         &Self::makeSwitch,
         &Self::makeReturn)
    .add(FeatureSet::ExceptionHandling, &Self::makeThrow, &Self::makeThrowRef)
    .add(FeatureSet::ReferenceTypes | FeatureSet::GC, &Self::makeCallRef);
  return (this->*pick(options))(Type::unreachable);
}

Expression* TranslateToFuzzReader::makeTrivial(Type type) {
  struct TrivialNester {
    TranslateToFuzzReader& parent;
    TrivialNester(TranslateToFuzzReader& parent) : parent(parent) {
      parent.trivialNesting++;
    }
    ~TrivialNester() { parent.trivialNesting--; }
  } nester(*this);

  if (type.isConcrete()) {
    // If we have a function context, use a local half the time. Use a local
    // less often if the local is non-nullable, however, as then we might be
    // using it before it was set, which would trap.
    if (funcContext && oneIn(type.isNonNullable() ? 10 : 2)) {
      return makeLocalGet(type);
    }

    // Either make a const, or a global.get (which may fail to find a suitable
    // global, especially in a non-function context, and if so it will make a
    // constant instead).
    return oneIn(2) ? makeConst(type) : makeGlobalGet(type);
  } else if (type == Type::none) {
    return makeNop(type);
  }
  assert(type == Type::unreachable);
  Expression* ret = nullptr;
  if (funcContext->func->getResults().isConcrete()) {
    ret = makeTrivial(funcContext->func->getResults());
  }
  return builder.makeReturn(ret);
}

Expression* TranslateToFuzzReader::makeBlock(Type type) {
  auto* ret = builder.makeBlock();
  ret->type = type; // so we have it during child creation
  ret->name = makeLabel();
  funcContext->breakableStack.push_back(ret);
  Index num = upToSquared(fuzzParams->BLOCK_FACTOR - 1); // we add another later
  if (nesting >= fuzzParams->NESTING_LIMIT / 2) {
    // smaller blocks past the limit
    num /= 2;
    if (nesting >= fuzzParams->NESTING_LIMIT && oneIn(2)) {
      // smaller blocks past the limit
      num /= 2;
    }
  }
  // not likely to have a block of size 1
  if (num == 0 && !oneIn(10)) {
    num++;
  }
  while (num > 0 && !random.finished()) {
    ret->list.push_back(make(Type::none));
    num--;
  }
  // give a chance to make the final element an unreachable break, instead
  // of concrete - a common pattern (branch to the top of a loop etc.)
  if (!random.finished() && type.isConcrete() && oneIn(2)) {
    ret->list.push_back(makeBreak(Type::unreachable));
  } else {
    ret->list.push_back(make(type));
  }
  funcContext->breakableStack.pop_back();
  if (type.isConcrete()) {
    ret->finalize(type);
  } else {
    ret->finalize();
  }
  if (ret->type != type) {
    // e.g. we might want an unreachable block, but a child breaks to it
    assert(type == Type::unreachable && ret->type == Type::none);
    return builder.makeSequence(ret, make(Type::unreachable));
  }
  return ret;
}

Expression* TranslateToFuzzReader::makeLoop(Type type) {
  auto* ret = wasm.allocator.alloc<Loop>();
  ret->type = type; // So we have it during child creation
  ret->name = makeLabel();
  funcContext->breakableStack.push_back(ret);
  funcContext->hangStack.push_back(ret);
  // Either create random content, or do something more targeted
  if (oneIn(2)) {
    ret->body = makeMaybeBlock(type);
  } else {
    // Ensure a branch back. Also optionally create some loop vars.
    std::vector<Expression*> list;
    list.push_back(makeMaybeBlock(Type::none)); // Primary contents
    // Possible branch back
    list.push_back(builder.makeBreak(ret->name, nullptr, makeCondition()));
    list.push_back(make(type)); // Final element, so we have the right type
    ret->body = builder.makeBlock(list, type);
  }
  funcContext->breakableStack.pop_back();
  funcContext->hangStack.pop_back();
  ret->finalize(type);
  return ret;
}

Expression* TranslateToFuzzReader::makeCondition() {
  // We want a 50-50 chance for the condition to be taken, for interesting
  // execution paths. by itself, there is bias (e.g. most consts are "yes") so
  // even that out with noise
  auto* ret = make(Type::i32);
  if (oneIn(2)) {
    ret = builder.makeUnary(UnaryOp::EqZInt32, ret);
  }
  return ret;
}

Expression* TranslateToFuzzReader::makeMaybeBlock(Type type) {
  // if past the limit, prefer not to emit blocks
  if (nesting >= fuzzParams->NESTING_LIMIT || oneIn(3)) {
    return make(type);
  } else {
    return makeBlock(type);
  }
}

Expression* TranslateToFuzzReader::buildIf(const struct ThreeArgs& args,
                                           Type type) {
  return builder.makeIf(args.a, args.b, args.c, type);
}

Expression* TranslateToFuzzReader::makeIf(Type type) {
  auto* condition = makeCondition();
  funcContext->hangStack.push_back(nullptr);

  Expression* ret;
  if (type == Type::none && oneIn(2)) {
    // Just an ifTrue arm.
    ret = buildIf({condition, makeMaybeBlock(type), nullptr}, type);
  } else {
    // Also an ifFalse arm.

    // Some of the time make one arm unreachable (but not both, as then the if
    // as a whole would be unreachable).
    auto trueType = type;
    auto falseType = type;
    switch (upTo(20)) {
      case 0:
        trueType = Type::unreachable;
        break;
      case 1:
        falseType = Type::unreachable;
        break;
    }
    ret = buildIf(
      {condition, makeMaybeBlock(trueType), makeMaybeBlock(falseType)}, type);
  }

  funcContext->hangStack.pop_back();
  return ret;
}

Expression* TranslateToFuzzReader::makeTry(Type type) {
  auto* body = make(type);
  std::vector<Name> catchTags;
  std::vector<Expression*> catchBodies;
  auto numTags = upTo(fuzzParams->MAX_TRY_CATCHES);
  std::unordered_set<Tag*> usedTags;
  for (Index i = 0; i < numTags; i++) {
    if (exceptionTags.empty()) {
      addTag();
    }
    auto* tag = pick(exceptionTags);
    if (usedTags.count(tag)) {
      continue;
    }
    usedTags.insert(tag);
    catchTags.push_back(tag->name);
  }
  // The number of tags in practice may be fewer than we planned.
  numTags = catchTags.size();
  auto numCatches = numTags;
  if (numTags == 0 || oneIn(2)) {
    // Add a catch-all.
    numCatches++;
  }
  for (Index i = 0; i < numCatches; i++) {
    // Catch bodies (aside from a catch-all) begin with a pop.
    Expression* prefix = nullptr;
    if (i < numTags) {
      auto tagType = wasm.getTag(catchTags[i])->params();
      if (tagType != Type::none) {
        auto* pop = builder.makePop(tagType);
        // Capture the pop in a local, so that it can be used later.
        // TODO: add a good chance for using this particular local in this catch
        // TODO: reuse an existing var if there is one
        auto index = builder.addVar(funcContext->func, tagType);
        prefix = builder.makeLocalSet(index, pop);
      }
    }
    auto* catchBody = make(type);
    if (prefix) {
      catchBody = builder.makeSequence(prefix, catchBody);
    }
    catchBodies.push_back(catchBody);
  }
  // TODO: delegate stuff
  return builder.makeTry(body, catchTags, catchBodies);
}

Expression* TranslateToFuzzReader::makeTryTable(Type type) {
  auto* body = make(type);

  if (funcContext->breakableStack.empty()) {
    // Nothing to break to, emit a trivial TryTable.
    // TODO: Perhaps generate a block wrapping us?
    return builder.makeTryTable(body, {}, {}, {});
  }

  if (exceptionTags.empty()) {
    addTag();
  }

  // Add catches of specific tags, and possibly a catch_all at the end. We use
  // the last iteration of the loop for that.
  std::vector<Name> catchTags;
  std::vector<Name> catchDests;
  std::vector<bool> catchRefs;
  auto numCatches = upTo(fuzzParams->MAX_TRY_CATCHES);
  for (Index i = 0; i <= numCatches; i++) {
    Name tagName;
    Type tagType;
    if (i < numCatches) {
      // Look for a specific tag.
      auto* tag = pick(exceptionTags);
      tagName = tag->name;
      tagType = tag->params();
    } else {
      // Add a catch_all at the end, some of the time (but all of the time if we
      // have nothing else).
      if (!catchTags.empty() && oneIn(2)) {
        break;
      }
      tagType = Type::none;
    }

    // We need to find a proper target to break to, which means a target that
    // has the type of the tag, or the tag + an exnref at the end.
    std::vector<Type> vec(tagType.begin(), tagType.end());
    // Use a non-nullable exnref here, and then the subtyping check below will
    // also accept a target that is nullable.
    vec.push_back(Type(HeapType::exn, NonNullable));
    auto tagTypeWithExn = Type(vec);
    int tries = fuzzParams->TRIES;
    while (tries-- > 0) {
      auto* target = pick(funcContext->breakableStack);
      auto dest = getTargetName(target);
      auto valueType = getTargetType(target);
      auto subOfTagType = Type::isSubType(tagType, valueType);
      auto subOfTagTypeWithExn = Type::isSubType(tagTypeWithExn, valueType);
      if (subOfTagType || subOfTagTypeWithExn) {
        catchTags.push_back(tagName);
        catchDests.push_back(dest);
        catchRefs.push_back(subOfTagTypeWithExn);
        break;
      }
    }
    // TODO: Perhaps generate a block wrapping us, if we fail to find a target?
    // TODO: It takes a bit of luck to find a target with an exnref - perhaps
    //       generate those?
  }

  return builder.makeTryTable(body, catchTags, catchDests, catchRefs);
}

Expression* TranslateToFuzzReader::makeBreak(Type type) {
  if (funcContext->breakableStack.empty()) {
    return makeTrivial(type);
  }
  Expression* condition = nullptr;
  if (type != Type::unreachable) {
    funcContext->hangStack.push_back(nullptr);
    condition = makeCondition();
  }
  // we need to find a proper target to break to; try a few times
  int tries = fuzzParams->TRIES;
  while (tries-- > 0) {
    auto* target = pick(funcContext->breakableStack);
    auto name = getTargetName(target);
    auto valueType = getTargetType(target);
    if (type.isConcrete()) {
      // we are flowing out a value
      if (valueType != type) {
        // we need to break to a proper place
        continue;
      }
      auto* ret = builder.makeBreak(name, make(type), condition);
      funcContext->hangStack.pop_back();
      return ret;
    } else if (type == Type::none) {
      if (valueType != Type::none) {
        // we need to break to a proper place
        continue;
      }
      auto* ret = builder.makeBreak(name, nullptr, condition);
      funcContext->hangStack.pop_back();
      return ret;
    } else {
      assert(type == Type::unreachable);
      if (valueType != Type::none) {
        // we need to break to a proper place
        continue;
      }
      // we are about to make an *un*conditional break. if it is
      // to a loop, we prefer there to be a condition along the
      // way, to reduce the chance of infinite looping
      size_t conditions = 0;
      int i = funcContext->hangStack.size();
      while (--i >= 0) {
        auto* item = funcContext->hangStack[i];
        if (item == nullptr) {
          conditions++;
        } else if (auto* loop = item->cast<Loop>()) {
          if (loop->name == name) {
            // we found the target, no more conditions matter
            break;
          }
        }
      }
      switch (conditions) {
        case 0: {
          if (!oneIn(4)) {
            continue;
          }
          break;
        }
        case 1: {
          if (!oneIn(2)) {
            continue;
          }
          break;
        }
        default: {
          if (oneIn(conditions + 1)) {
            continue;
          }
        }
      }
      return builder.makeBreak(name);
    }
  }
  // we failed to find something
  if (type != Type::unreachable) {
    funcContext->hangStack.pop_back();
  }
  return makeTrivial(type);
}

Expression* TranslateToFuzzReader::makeCall(Type type) {
  int tries = fuzzParams->TRIES;
  bool isReturn;
  while (tries-- > 0) {
    Function* target = funcContext->func;
    if (!wasm.functions.empty() && !oneIn(wasm.functions.size())) {
      target = pick(wasm.functions).get();
    }
    isReturn = type == Type::unreachable && wasm.features.hasTailCall() &&
               funcContext->func->getResults() == target->getResults();
    if (target->getResults() != type && !isReturn) {
      continue;
    }
    // we found one!
    std::vector<Expression*> args;
    for (const auto& argType : target->getParams()) {
      args.push_back(make(argType));
    }
    return builder.makeCall(target->name, args, type, isReturn);
  }
  // we failed to find something
  return makeTrivial(type);
}

Expression* TranslateToFuzzReader::makeCallIndirect(Type type) {
  auto& randomElem = wasm.elementSegments[upTo(wasm.elementSegments.size())];
  auto& data = randomElem->data;
  if (data.empty()) {
    return make(type);
  }
  // look for a call target with the right type
  Index start = upTo(data.size());
  Index i = start;
  Function* targetFn;
  bool isReturn;
  while (1) {
    // TODO: handle unreachable
    if (auto* get = data[i]->dynCast<RefFunc>()) {
      targetFn = wasm.getFunction(get->func);
      isReturn = type == Type::unreachable && wasm.features.hasTailCall() &&
                 funcContext->func->getResults() == targetFn->getResults();
      if (targetFn->getResults() == type || isReturn) {
        break;
      }
    }
    i++;
    if (i == data.size()) {
      i = 0;
    }
    if (i == start) {
      return makeTrivial(type);
    }
  }
  // with high probability, make sure the type is valid - otherwise, most are
  // going to trap
  auto addressType = wasm.getTable(funcrefTableName)->addressType;
  Expression* target;
  if (!allowOOB || !oneIn(10)) {
    target = builder.makeConst(Literal::makeFromInt32(i, addressType));
  } else {
    target = make(addressType);
  }
  std::vector<Expression*> args;
  for (const auto& type : targetFn->getParams()) {
    args.push_back(make(type));
  }
  // TODO: use a random table
  return builder.makeCallIndirect(
    funcrefTableName, target, args, targetFn->type.getHeapType(), isReturn);
}

Expression* TranslateToFuzzReader::makeCallRef(Type type) {
  // look for a call target with the right type
  Function* target;
  bool isReturn;
  decltype(fuzzParams->TRIES) i = 0;
  while (1) {
    if (i == fuzzParams->TRIES || wasm.functions.empty()) {
      // We can't find a proper target, give up.
      return makeTrivial(type);
    }
    // TODO: handle unreachable
    target = wasm.functions[upTo(wasm.functions.size())].get();
    isReturn = type == Type::unreachable && wasm.features.hasTailCall() &&
               funcContext->func->getResults() == target->getResults();
    if (target->getResults() == type || isReturn) {
      break;
    }
    i++;
  }
  std::vector<Expression*> args;
  for (const auto& type : target->getParams()) {
    args.push_back(make(type));
  }
  // TODO: half the time make a completely random item with that type.
  return builder.makeCallRef(
    builder.makeRefFunc(target->name), args, type, isReturn);
}

Expression* TranslateToFuzzReader::makeLocalGet(Type type) {
  auto& locals = funcContext->typeLocals[type];
  if (!locals.empty()) {
    return builder.makeLocalGet(pick(locals), type);
  }
  // No existing local. When we want something trivial, just give up and emit a
  // constant.
  if (trivialNesting) {
    return makeConst(type);
  }

  // Otherwise, we have 3 cases: a const, as above (we do this randomly some of
  // the time), or emit a local.get of a new local, or emit a local.tee of a new
  // local.
  auto choice = upTo(3);
  if (choice == 0 || !TypeUpdating::canHandleAsLocal(type)) {
    return makeConst(type);
  }
  // Otherwise, add a new local. If the type is not non-nullable then we may
  // just emit a get for it (which, as this is a brand-new local, will read the
  // default value, unless we are in a loop; for that reason for a non-
  // nullable local we prefer a tee later down.).
  auto index = builder.addVar(funcContext->func, type);
  LocalSet* tee = nullptr;
  if (choice == 1 || type.isNonNullable()) {
    // Create the tee here before adding the local to typeLocals (or else we
    // might end up using it prematurely inside the make() call).
    tee = builder.makeLocalTee(index, make(type), type);
  }
  funcContext->typeLocals[type].push_back(index);
  if (tee) {
    return tee;
  }
  return builder.makeLocalGet(index, type);
}

Expression* TranslateToFuzzReader::makeLocalSet(Type type) {
  bool tee = type != Type::none;
  Type valueType;
  if (tee) {
    valueType = type;
  } else {
    valueType = getConcreteType();
  }
  auto& locals = funcContext->typeLocals[valueType];
  if (locals.empty()) {
    return makeTrivial(type);
  }
  auto* value = make(valueType);
  if (tee) {
    return builder.makeLocalTee(pick(locals), value, valueType);
  } else {
    return builder.makeLocalSet(pick(locals), value);
  }
}

Expression* TranslateToFuzzReader::makeGlobalGet(Type type) {
  // In a non-function context, like in another global, we can only get from an
  // immutable global. Whether GC is enabled also matters, as it allows getting
  // from a non-import.
  auto& relevantGlobals =
    funcContext ? globalsByType
                : (wasm.features.hasGC() ? immutableGlobalsByType
                                         : importedImmutableGlobalsByType);
  auto it = relevantGlobals.find(type);
  // If we have no such relevant globals give up and emit a constant instead.
  if (it == relevantGlobals.end() || it->second.empty()) {
    return makeConst(type);
  }

  auto name = pick(it->second);
  // We don't want random fuzz code to use the hang limit global.
  assert(name != HANG_LIMIT_GLOBAL);
  return builder.makeGlobalGet(name, type);
}

Expression* TranslateToFuzzReader::makeGlobalSet(Type type) {
  assert(type == Type::none);
  type = getConcreteType();
  auto it = mutableGlobalsByType.find(type);
  if (it == mutableGlobalsByType.end() || it->second.empty()) {
    return makeTrivial(Type::none);
  }

  auto name = pick(it->second);
  // We don't want random fuzz code to use the hang limit global.
  assert(name != HANG_LIMIT_GLOBAL);
  return builder.makeGlobalSet(name, make(type));
}

Expression* TranslateToFuzzReader::makeTupleMake(Type type) {
  assert(wasm.features.hasMultivalue());
  assert(type.isTuple());
  std::vector<Expression*> elements;
  for (const auto& t : type) {
    elements.push_back(make(t));
  }
  return builder.makeTupleMake(std::move(elements));
}

Expression* TranslateToFuzzReader::makeTupleExtract(Type type) {
  // Tuples can require locals in binary format conversions.
  if (!type.isDefaultable()) {
    return makeTrivial(type);
  }
  assert(wasm.features.hasMultivalue());
  assert(type.isSingle() && type.isConcrete());
  Type tupleType = getTupleType();

  // Find indices from which we can extract `type`
  std::vector<size_t> extractIndices;
  size_t i = 0;
  for (const auto& t : tupleType) {
    if (t == type) {
      extractIndices.push_back(i);
    }
    ++i;
  }

  // If there are none, inject one
  if (extractIndices.size() == 0) {
    std::vector<Type> newElements(tupleType.begin(), tupleType.end());
    size_t injected = upTo(newElements.size());
    newElements[injected] = type;
    tupleType = Type(newElements);
    extractIndices.push_back(injected);
  }

  Index index = pick(extractIndices);
  Expression* child = make(tupleType);
  return builder.makeTupleExtract(child, index);
}

Expression* TranslateToFuzzReader::makePointer() {
  auto* ret = make(wasm.memories[0]->addressType);
  // with high probability, mask the pointer so it's in a reasonable
  // range. otherwise, most pointers are going to be out of range and
  // most memory ops will just trap
  if (!allowOOB || !oneIn(10)) {
    if (wasm.memories[0]->is64()) {
      ret = builder.makeBinary(
        AndInt64,
        ret,
        builder.makeConst(int64_t(fuzzParams->USABLE_MEMORY - 1)));
    } else {
      ret = builder.makeBinary(
        AndInt32,
        ret,
        builder.makeConst(int32_t(fuzzParams->USABLE_MEMORY - 1)));
    }
  }
  return ret;
}

Expression* TranslateToFuzzReader::makeNonAtomicLoad(Type type) {
  auto offset = logify(get());
  auto ptr = makePointer();
  switch (type.getBasic()) {
    case Type::i32: {
      bool signed_ = get() & 1;
      switch (upTo(3)) {
        case 0:
          return builder.makeLoad(
            1, signed_, offset, 1, ptr, type, wasm.memories[0]->name);
        case 1:
          return builder.makeLoad(
            2, signed_, offset, pick(1, 2), ptr, type, wasm.memories[0]->name);
        case 2:
          return builder.makeLoad(4,
                                  signed_,
                                  offset,
                                  pick(1, 2, 4),
                                  ptr,
                                  type,
                                  wasm.memories[0]->name);
      }
      WASM_UNREACHABLE("unexpected value");
    }
    case Type::i64: {
      bool signed_ = get() & 1;
      switch (upTo(4)) {
        case 0:
          return builder.makeLoad(
            1, signed_, offset, 1, ptr, type, wasm.memories[0]->name);
        case 1:
          return builder.makeLoad(
            2, signed_, offset, pick(1, 2), ptr, type, wasm.memories[0]->name);
        case 2:
          return builder.makeLoad(4,
                                  signed_,
                                  offset,
                                  pick(1, 2, 4),
                                  ptr,
                                  type,
                                  wasm.memories[0]->name);
        case 3:
          return builder.makeLoad(8,
                                  signed_,
                                  offset,
                                  pick(1, 2, 4, 8),
                                  ptr,
                                  type,
                                  wasm.memories[0]->name);
      }
      WASM_UNREACHABLE("unexpected value");
    }
    case Type::f32: {
      return builder.makeLoad(
        4, false, offset, pick(1, 2, 4), ptr, type, wasm.memories[0]->name);
    }
    case Type::f64: {
      return builder.makeLoad(
        8, false, offset, pick(1, 2, 4, 8), ptr, type, wasm.memories[0]->name);
    }
    case Type::v128: {
      if (!wasm.features.hasSIMD()) {
        return makeTrivial(type);
      }
      return builder.makeLoad(16,
                              false,
                              offset,
                              pick(1, 2, 4, 8, 16),
                              ptr,
                              type,
                              wasm.memories[0]->name);
    }
    case Type::none:
    case Type::unreachable:
      WASM_UNREACHABLE("invalid type");
  }
  WASM_UNREACHABLE("invalid type");
}

Expression* TranslateToFuzzReader::makeLoad(Type type) {
  // reference types cannot be stored in memory
  if (!allowMemory || type.isRef()) {
    return makeTrivial(type);
  }
  auto* ret = makeNonAtomicLoad(type);
  if (type != Type::i32 && type != Type::i64) {
    return ret;
  }
  if (!wasm.features.hasAtomics() || oneIn(2)) {
    return ret;
  }
  // make it atomic
  auto* load = ret->cast<Load>();
  wasm.memories[0]->shared = true;
  load->isAtomic = true;
  load->signed_ = false;
  load->align = load->bytes;
  return load;
}

Expression* TranslateToFuzzReader::makeNonAtomicStore(Type type) {
  if (type == Type::unreachable) {
    // make a normal store, then make it unreachable
    auto* ret = makeNonAtomicStore(getStorableType());
    auto* store = ret->dynCast<Store>();
    if (!store) {
      return ret;
    }
    switch (upTo(3)) {
      case 0:
        store->ptr = make(Type::unreachable);
        break;
      case 1:
        store->value = make(Type::unreachable);
        break;
      case 2:
        store->ptr = make(Type::unreachable);
        store->value = make(Type::unreachable);
        break;
    }
    store->memory = wasm.memories[0]->name;
    store->finalize();
    return store;
  }
  // the type is none or unreachable. we also need to pick the value
  // type.
  if (type == Type::none) {
    type = getStorableType();
  }
  auto offset = logify(get());
  auto ptr = makePointer();
  auto value = make(type);
  switch (type.getBasic()) {
    case Type::i32: {
      switch (upTo(3)) {
        case 0:
          return builder.makeStore(
            1, offset, 1, ptr, value, type, wasm.memories[0]->name);
        case 1:
          return builder.makeStore(
            2, offset, pick(1, 2), ptr, value, type, wasm.memories[0]->name);
        case 2:
          return builder.makeStore(
            4, offset, pick(1, 2, 4), ptr, value, type, wasm.memories[0]->name);
      }
      WASM_UNREACHABLE("invalid value");
    }
    case Type::i64: {
      switch (upTo(4)) {
        case 0:
          return builder.makeStore(
            1, offset, 1, ptr, value, type, wasm.memories[0]->name);
        case 1:
          return builder.makeStore(
            2, offset, pick(1, 2), ptr, value, type, wasm.memories[0]->name);
        case 2:
          return builder.makeStore(
            4, offset, pick(1, 2, 4), ptr, value, type, wasm.memories[0]->name);
        case 3:
          return builder.makeStore(8,
                                   offset,
                                   pick(1, 2, 4, 8),
                                   ptr,
                                   value,
                                   type,
                                   wasm.memories[0]->name);
      }
      WASM_UNREACHABLE("invalid value");
    }
    case Type::f32: {
      return builder.makeStore(
        4, offset, pick(1, 2, 4), ptr, value, type, wasm.memories[0]->name);
    }
    case Type::f64: {
      return builder.makeStore(
        8, offset, pick(1, 2, 4, 8), ptr, value, type, wasm.memories[0]->name);
    }
    case Type::v128: {
      if (!wasm.features.hasSIMD()) {
        return makeTrivial(type);
      }
      return builder.makeStore(16,
                               offset,
                               pick(1, 2, 4, 8, 16),
                               ptr,
                               value,
                               type,
                               wasm.memories[0]->name);
    }
    case Type::none:
    case Type::unreachable:
      WASM_UNREACHABLE("invalid type");
  }
  WASM_UNREACHABLE("invalid type");
}

Expression* TranslateToFuzzReader::makeStore(Type type) {
  if (!allowMemory || type.isRef()) {
    return makeTrivial(type);
  }
  auto* ret = makeNonAtomicStore(type);
  auto* store = ret->dynCast<Store>();
  if (!store) {
    return ret;
  }
  if (store->value->type != Type::i32 && store->value->type != Type::i64) {
    return store;
  }
  if (!wasm.features.hasAtomics() || oneIn(2)) {
    return store;
  }
  // make it atomic
  wasm.memories[0]->shared = true;
  store->isAtomic = true;
  store->align = store->bytes;
  return store;
}

// Makes a small change to a constant value.
Literal TranslateToFuzzReader::tweak(Literal value) {
  auto type = value.type;
  if (type.isVector()) {
    // TODO: tweak each lane?
    return value;
  }
  // +- 1
  switch (upTo(5)) {
    case 0:
      value = value.add(Literal::makeNegOne(type));
      break;
    case 1:
      value = value.add(Literal::makeOne(type));
      break;
    default: {
    }
  }
  // For floats, optionally add a non-integer adjustment in +- [-1, 1]
  if (type.isFloat() && oneIn(2)) {
    const int RANGE = 1000;
    auto RANGE_LITERAL = Literal::makeFromInt32(RANGE, type);
    // adjustment -> [0, 2 * RANGE]
    auto adjustment = Literal::makeFromInt32(upTo(2 * RANGE + 1), type);
    // adjustment -> [-RANGE, RANGE]
    adjustment = adjustment.sub(RANGE_LITERAL);
    // adjustment -> [-1, 1]
    adjustment = adjustment.div(RANGE_LITERAL);
    value = value.add(adjustment);
  }
  // Flip sign.
  if (oneIn(2)) {
    value = value.mul(Literal::makeNegOne(type));
  }
  return value;
}

Literal TranslateToFuzzReader::makeLiteral(Type type) {
  if (type == Type::v128) {
    // generate each lane individually for random lane interpretation
    switch (upTo(6)) {
      case 0:
        return Literal(std::array<Literal, 16>{{makeLiteral(Type::i32),
                                                makeLiteral(Type::i32),
                                                makeLiteral(Type::i32),
                                                makeLiteral(Type::i32),
                                                makeLiteral(Type::i32),
                                                makeLiteral(Type::i32),
                                                makeLiteral(Type::i32),
                                                makeLiteral(Type::i32),
                                                makeLiteral(Type::i32),
                                                makeLiteral(Type::i32),
                                                makeLiteral(Type::i32),
                                                makeLiteral(Type::i32),
                                                makeLiteral(Type::i32),
                                                makeLiteral(Type::i32),
                                                makeLiteral(Type::i32),
                                                makeLiteral(Type::i32)}});
      case 1:
        return Literal(std::array<Literal, 8>{{makeLiteral(Type::i32),
                                               makeLiteral(Type::i32),
                                               makeLiteral(Type::i32),
                                               makeLiteral(Type::i32),
                                               makeLiteral(Type::i32),
                                               makeLiteral(Type::i32),
                                               makeLiteral(Type::i32),
                                               makeLiteral(Type::i32)}});
      case 2:
        return Literal(std::array<Literal, 4>{{makeLiteral(Type::i32),
                                               makeLiteral(Type::i32),
                                               makeLiteral(Type::i32),
                                               makeLiteral(Type::i32)}});
      case 3:
        return Literal(std::array<Literal, 2>{
          {makeLiteral(Type::i64), makeLiteral(Type::i64)}});
      case 4:
        return Literal(std::array<Literal, 4>{{makeLiteral(Type::f32),
                                               makeLiteral(Type::f32),
                                               makeLiteral(Type::f32),
                                               makeLiteral(Type::f32)}});
      case 5:
        return Literal(std::array<Literal, 2>{
          {makeLiteral(Type::f64), makeLiteral(Type::f64)}});
      default:
        WASM_UNREACHABLE("unexpected value");
    }
  }

  switch (upTo(4)) {
    case 0: {
      // totally random, entire range
      switch (type.getBasic()) {
        case Type::i32:
          return Literal(get32());
        case Type::i64:
          return Literal(get64());
        case Type::f32:
          return Literal(getFloat());
        case Type::f64:
          return Literal(getDouble());
        case Type::v128:
        case Type::none:
        case Type::unreachable:
          WASM_UNREACHABLE("invalid type");
      }
      break;
    }
    case 1: {
      // small range
      int64_t small;
      switch (upTo(6)) {
        case 0:
          small = int8_t(get());
          break;
        case 1:
          small = uint8_t(get());
          break;
        case 2:
          small = int16_t(get16());
          break;
        case 3:
          small = uint16_t(get16());
          break;
        case 4:
          small = int32_t(get32());
          break;
        case 5:
          small = uint32_t(get32());
          break;
        default:
          WASM_UNREACHABLE("invalid value");
      }
      switch (type.getBasic()) {
        case Type::i32:
          return Literal(int32_t(small));
        case Type::i64:
          return Literal(int64_t(small));
        case Type::f32:
          return Literal(float(small));
        case Type::f64:
          return Literal(double(small));
        case Type::v128:
        case Type::none:
        case Type::unreachable:
          WASM_UNREACHABLE("unexpected type");
      }
      break;
    }
    case 2: {
      // special values
      Literal value;
      switch (type.getBasic()) {
        case Type::i32:
          value = Literal(pick<int32_t>(0,
                                        std::numeric_limits<int8_t>::min(),
                                        std::numeric_limits<int8_t>::max(),
                                        std::numeric_limits<int16_t>::min(),
                                        std::numeric_limits<int16_t>::max(),
                                        std::numeric_limits<int32_t>::min(),
                                        std::numeric_limits<int32_t>::max(),
                                        std::numeric_limits<uint8_t>::max(),
                                        std::numeric_limits<uint16_t>::max(),
                                        std::numeric_limits<uint32_t>::max()));
          break;
        case Type::i64:
          value = Literal(pick<int64_t>(0,
                                        std::numeric_limits<int8_t>::min(),
                                        std::numeric_limits<int8_t>::max(),
                                        std::numeric_limits<int16_t>::min(),
                                        std::numeric_limits<int16_t>::max(),
                                        std::numeric_limits<int32_t>::min(),
                                        std::numeric_limits<int32_t>::max(),
                                        std::numeric_limits<int64_t>::min(),
                                        std::numeric_limits<int64_t>::max(),
                                        std::numeric_limits<uint8_t>::max(),
                                        std::numeric_limits<uint16_t>::max(),
                                        std::numeric_limits<uint32_t>::max(),
                                        std::numeric_limits<uint64_t>::max()));
          break;
        case Type::f32:
          value = Literal(pick<float>(0.0f,
                                      -0.0f,
                                      std::numeric_limits<float>::min(),
                                      std::numeric_limits<float>::max(),
                                      std::numeric_limits<int32_t>::min(),
                                      std::numeric_limits<int32_t>::max(),
                                      std::numeric_limits<int64_t>::min(),
                                      std::numeric_limits<int64_t>::max(),
                                      std::numeric_limits<uint32_t>::max(),
                                      std::numeric_limits<uint64_t>::max()));
          break;
        case Type::f64:
          value = Literal(pick<double>(0.0,
                                       -0.0,
                                       std::numeric_limits<float>::min(),
                                       std::numeric_limits<float>::max(),
                                       std::numeric_limits<double>::min(),
                                       std::numeric_limits<double>::max(),
                                       std::numeric_limits<int32_t>::min(),
                                       std::numeric_limits<int32_t>::max(),
                                       std::numeric_limits<int64_t>::min(),
                                       std::numeric_limits<int64_t>::max(),
                                       std::numeric_limits<uint32_t>::max(),
                                       std::numeric_limits<uint64_t>::max()));
          break;
        case Type::v128:
        case Type::none:
        case Type::unreachable:
          WASM_UNREACHABLE("unexpected type");
      }
      return tweak(value);
    }
    case 3: {
      // powers of 2
      Literal value;
      switch (type.getBasic()) {
        case Type::i32:
          value = Literal(int32_t(1) << upTo(32));
          break;
        case Type::i64:
          value = Literal(int64_t(1) << upTo(64));
          break;
        case Type::f32:
          value = Literal(float(int64_t(1) << upTo(64)));
          break;
        case Type::f64:
          value = Literal(double(int64_t(1) << upTo(64)));
          break;
        case Type::v128:
        case Type::none:
        case Type::unreachable:
          WASM_UNREACHABLE("unexpected type");
      }
      return tweak(value);
    }
  }
  WASM_UNREACHABLE("invalid value");
}

Expression* TranslateToFuzzReader::makeRefFuncConst(Type type) {
  auto heapType = type.getHeapType();
  auto share = heapType.getShared();
  if (heapType.isBasic()) {
    assert(heapType.getBasic(Unshared) == HeapType::func);
    // With high probability, use the last created function if possible.
    // Otherwise, continue on to select some other function.
    if (funcContext &&
        funcContext->func->type.getHeapType().getShared() == share &&
        !oneIn(4)) {
      auto* target = funcContext->func;
      return builder.makeRefFunc(target->name, target->type);
    }
  }
  // Look for a proper function starting from a random location, and loop from
  // there, wrapping around to 0.
  if (!wasm.functions.empty()) {
    Index start = upTo(wasm.functions.size());
    Index i = start;
    do {
      auto& func = wasm.functions[i];
      if (Type::isSubType(func->type, type)) {
        return builder.makeRefFunc(func->name);
      }
      i = (i + 1) % wasm.functions.size();
    } while (i != start);
  }
  // We don't have a matching function. Create a null some of the time here,
  // but only rarely if the type is non-nullable (because in that case we'd need
  // to add a ref.as_non_null to validate, and the code will trap when we get
  // here).
  if ((type.isNullable() && oneIn(2)) ||
      (type.isNonNullable() && oneIn(16) && funcContext)) {
    Expression* ret = builder.makeRefNull(HeapTypes::nofunc.getBasic(share));
    if (!type.isNullable()) {
      assert(funcContext);
      ret = builder.makeRefAs(RefAsNonNull, ret);
    }
    return ret;
  }
  // As a final option, create a new function with the correct signature. If it
  // returns a value, write a trap as we do not want to create any more code
  // here (we might end up recursing). Note that a trap in the function lets us
  // execute more code then the ref.as_non_null path just before us, which traps
  // even if we never call the function.
  if (heapType.isBasic()) {
    // We need a specific signature type to create a function. Pick an arbitrary
    // signature if we only had generic 'func' here.
    TypeBuilder builder(1);
    builder[0] = Signature(Type::none, Type::none);
    builder[0].setShared(share);
    heapType = (*builder.build())[0];
  }
  auto* body = heapType.getSignature().results == Type::none
                 ? (Expression*)builder.makeNop()
                 : (Expression*)builder.makeUnreachable();
  auto* func = wasm.addFunction(
    builder.makeFunction(Names::getValidFunctionName(wasm, "ref_func_target"),
                         Type(heapType, NonNullable, Exact),
                         {},
                         body));
  return builder.makeRefFunc(func->name);
}

Expression* TranslateToFuzzReader::makeConst(Type type) {
  if (type.isRef()) {
    assert(wasm.features.hasReferenceTypes());
    // With a low chance, just emit a null if that is valid.
    if (type.isNullable() && oneIn(8)) {
      return builder.makeRefNull(type.getHeapType());
    }
    if (type.getHeapType().isString()) {
      return makeStringConst();
    }
    if (type.getHeapType().isBasic()) {
      return makeBasicRef(type);
    } else {
      return makeCompoundRef(type);
    }
  } else if (type.isTuple()) {
    std::vector<Expression*> operands;
    for (const auto& t : type) {
      operands.push_back(makeConst(t));
    }
    return builder.makeTupleMake(std::move(operands));
  } else {
    assert(type.isBasic());
    return builder.makeConst(makeLiteral(type));
  }
}

Expression* TranslateToFuzzReader::makeBasicRef(Type type) {
  assert(type.isRef());
  auto heapType = type.getHeapType();
  assert(heapType.isBasic());
  assert(wasm.features.hasReferenceTypes());
  auto share = heapType.getShared();
  switch (heapType.getBasic(Unshared)) {
    case HeapType::ext: {
      if (wasm.features.hasStrings() && share == Unshared && oneIn(2)) {
        // Shared strings not yet supported.
        return makeConst(Type(HeapType::string, NonNullable));
      }
      auto null = builder.makeRefNull(HeapTypes::ext.getBasic(share));
      // TODO: support actual non-nullable externrefs via imported globals or
      // similar.
      if (!type.isNullable()) {
        return builder.makeRefAs(RefAsNonNull, null);
      }
      return null;
    }
    case HeapType::func: {
      // Rarely, emit a call to imported table.get (when nullable, unshared, and
      // where we can emit a call).
      if (type.isNullable() && share == Unshared && funcContext &&
          tableGetImportName && !oneIn(3)) {
        return makeImportTableGet();
      }
      return makeRefFuncConst(type);
    }
    case HeapType::cont: {
      // Most of the time, avoid null continuations, as they will trap.
      if (type.isNullable() && oneIn(4)) {
        return builder.makeRefNull(HeapTypes::cont.getBasic(share));
      }
      // Emit the simplest possible continuation.
      auto funcSig = Signature(Type::none, Type::none);
      auto funcType = Type(funcSig, NonNullable);
      auto contType = Continuation(funcSig);
      return builder.makeContNew(contType, makeRefFuncConst(funcType));
    }
    case HeapType::any: {
      // Choose a subtype we can materialize a constant for. We cannot
      // materialize non-nullable refs to func or i31 in global contexts.
      Nullability nullability = getSubType(type.getNullability());
      assert(wasm.features.hasGC());
      auto subtype = pick(HeapTypes::i31, HeapTypes::struct_, HeapTypes::array);
      return makeConst(Type(subtype.getBasic(share), nullability));
    }
    case HeapType::eq: {
      if (!wasm.features.hasGC()) {
        // Without wasm GC all we have is an "abstract" eqref type, which is
        // a subtype of anyref, but we cannot create constants of it, except
        // for null.
        assert(type.isNullable());
        return builder.makeRefNull(HeapTypes::none.getBasic(share));
      }
      auto nullability = getSubType(type.getNullability());
      // ref.i31 is not allowed in initializer expressions.
      HeapType subtype;
      switch (upTo(3)) {
        case 0:
          subtype = HeapType::i31;
          break;
        case 1:
          subtype = HeapType::struct_;
          break;
        case 2:
          subtype = HeapType::array;
          break;
      }
      return makeConst(Type(subtype.getBasic(share), nullability));
    }
    case HeapType::i31: {
      assert(wasm.features.hasGC());
      if (type.isNullable() && oneIn(4)) {
        return builder.makeRefNull(HeapTypes::none.getBasic(share));
      }
      return builder.makeRefI31(makeConst(Type::i32), share);
    }
    case HeapType::struct_: {
      assert(wasm.features.hasGC());
      // TODO: Construct nontrivial types. For now just create a hard coded
      // struct.
      // Use a local static to avoid the expense of canonicalizing a new type
      // every time.
      static HeapType trivialStruct = HeapType(Struct());
      static HeapType sharedTrivialStruct = []() {
        TypeBuilder builder(1);
        builder[0] = Struct{};
        builder[0].setShared();
        return (*builder.build())[0];
      }();
      auto ht = share == Shared ? sharedTrivialStruct : trivialStruct;
      return builder.makeStructNew(ht, std::vector<Expression*>{});
    }
    case HeapType::array: {
      static HeapType trivialArray =
        HeapType(Array(Field(Field::PackedType::i8, Immutable)));
      static HeapType sharedTrivialArray = []() {
        TypeBuilder builder(1);
        builder[0] = Array(Field(Field::PackedType::i8, Immutable));
        builder[0].setShared();
        return (*builder.build())[0];
      }();
      auto ht = share == Shared ? sharedTrivialArray : trivialArray;
      return builder.makeArrayNewFixed(ht, {});
    }
    case HeapType::exn: {
      // If nullable, sometimes emit a null. If not in a function context, see
      // below, we need a null as well regardless of the type.
      if ((type.isNullable() && oneIn(2)) || !funcContext) {
        auto* null = builder.makeRefNull(HeapTypes::exn.getBasic(share));
        if (type.isNullable()) {
          return null;
        }
        // The type is non-nullable, so we are here because we are in a non-
        // function context, with nothing valid to emit. "Fix" it with a cast,
        // which is not valid IR, but which the calling code will handle.
        assert(!funcContext);
        return builder.makeRefAs(RefAsNonNull, null);
      }

      // Emit a throw in a block.
      auto* throww = makeThrow(Type::unreachable);
      auto label = makeLabel();
      auto* tryy = builder.makeTryTable(throww, {Name()}, {label}, {true});
      return builder.makeBlock(label, tryy);
    }
    case HeapType::string: {
      // In non-function contexts all we can do is string.const.
      assert(share == Unshared && "shared strings not supported");
      if (!funcContext) {
        return makeStringConst();
      }
      switch (upTo(11)) {
        case 0:
        case 1:
        case 2:
          return makeStringConst();
        case 3:
        case 4:
        case 5:
          return makeStringNewCodePoint();
        case 6:
        case 7:
          // We less frequently make string.new_array as it may generate a lot
          // of code for the array in some cases.
          return makeStringNewArray();
        case 8:
          // We much less frequently make string.concat as it will recursively
          // generate two string children, i.e., it can lead to exponential
          // growth.
          return makeStringConcat();
        case 9:
        case 10:
          return makeStringSlice();
      }
      WASM_UNREACHABLE("bad switch");
    }
    case HeapType::none:
    case HeapType::noext:
    case HeapType::nofunc:
    case HeapType::nocont:
    case HeapType::noexn: {
      auto null = builder.makeRefNull(heapType.getBasic(share));
      if (!type.isNullable()) {
        assert(funcContext);
        return builder.makeRefAs(RefAsNonNull, null);
      }
      return null;
    }
  }
  WASM_UNREACHABLE("invalid basic ref type");
}

Expression* TranslateToFuzzReader::makeCompoundRef(Type type) {
  assert(type.isRef());
  auto heapType = type.getHeapType();
  assert(!heapType.isBasic());
  assert(wasm.features.hasReferenceTypes());

  // Prefer not to emit a null, in general, as we can trap from them. If it is
  // nullable, give a small chance to do so; if we hit the nesting limit then we
  // really have no choice and must emit a null (or else we could infinitely
  // recurse). For the nesting limit, use a bound that is higher than the normal
  // one, so that the normal mechanisms should prevent us from getting here;
  // this limit is really a last resort we want to never reach. Also, increase
  // the chance to emit a null as |nesting| rises, to avoid deep recursive
  // structures.
  //
  // Note that we might have cycles of types where some are non-nullable. We
  // will only stop here when we exceed the nesting and reach a nullable one.
  // (This assumes there is a nullable one, that is, that the types are
  // inhabitable.)
  const auto LIMIT = fuzzParams->NESTING_LIMIT + 1;
  AutoNester nester(*this);
  if (type.isNullable() &&
      (random.finished() || nesting >= LIMIT || oneIn(LIMIT - nesting + 1))) {
    return builder.makeRefNull(heapType);
  }

  // If the type is non-nullable, but we've run out of input, then we need to do
  // something here to avoid infinite recursion. In the worse case we'll emit a
  // cast to non-null of a null, which validates, but it will trap at runtime
  // which is not ideal.
  if (type.isNonNullable() && (random.finished() || nesting >= LIMIT)) {
    // If we have a function context then we can at least emit a local.get,
    // sometimes, which is less bad. Note that we need to check typeLocals
    // manually here to avoid infinite recursion (as makeLocalGet will fall back
    // to us, if there is no local).
    // TODO: we could also look for locals containing subtypes
    if (funcContext) {
      if (!funcContext->typeLocals[type].empty()) {
        return makeLocalGet(type);
      }
      // No local, but we are in a function context so RefAsNonNull is valid.
      return builder.makeRefAs(RefAsNonNull, builder.makeRefNull(heapType));
    }
    // No function context, so we are in quite the pickle. Continue onwards, as
    // we may succeed to emit something more complex (like a struct.new).
  }

  // When we make children, they must be trivial if we are not in a function
  // context.
  auto makeChild = [&](Type type) {
    return funcContext ? make(type) : makeTrivial(type);
  };

  switch (heapType.getKind()) {
    case HeapTypeKind::Func:
      return makeRefFuncConst(type);
    case HeapTypeKind::Struct: {
      auto& fields = heapType.getStruct().fields;
      std::vector<Expression*> values;
      // If there is a nondefaultable field, we must provide the value and not
      // depend on defaults. Also do that randomly half the time.
      if (std::any_of(
            fields.begin(),
            fields.end(),
            [&](const Field& field) { return !field.type.isDefaultable(); }) ||
          oneIn(2)) {
        for (auto& field : fields) {
          values.push_back(makeChild(field.type));
        }
        // Add more nesting manually, as we can easily get exponential blowup
        // here. This nesting makes it much less likely for a recursive data
        // structure to end up as a massive tree of struct.news, since the
        // nesting limitation code at the top of this function will kick in.
        if (!values.empty()) {
          // Subtract 1 since if there is a single value there cannot be
          // exponential blowup.
          nester.add(values.size() - 1);
        }
      }
      Expression* descriptor = nullptr;
      if (auto descType = heapType.getDescriptorType()) {
        descriptor = makeTrappingRefUse(Type(*descType, Nullable, Exact));
      }
      return builder.makeStructNew(heapType, values, descriptor);
    }
    case HeapTypeKind::Array: {
      auto element = heapType.getArray().element;
      Expression* init = nullptr;
      if (!element.type.isDefaultable() || oneIn(2)) {
        init = makeChild(element.type);
      }
      auto* count =
        builder.makeConst(int32_t(upTo(fuzzParams->MAX_ARRAY_SIZE)));
      return builder.makeArrayNew(type.getHeapType(), count, init);
    }
    case HeapTypeKind::Cont: {
      auto funcType = heapType.getContinuation().type;
      return builder.makeContNew(heapType, makeTrappingRefUse(funcType));
    }
    case HeapTypeKind::Basic:
      break;
  }
  WASM_UNREACHABLE("unexpected kind");
}

Expression* TranslateToFuzzReader::makeStringNewArray() {
  auto* array = makeTrappingRefUse(HeapTypes::getMutI16Array());
  auto* start = make(Type::i32);
  auto* end = make(Type::i32);
  return builder.makeStringNew(StringNewWTF16Array, array, start, end);
}

Expression* TranslateToFuzzReader::makeStringNewCodePoint() {
  auto codePoint = make(Type::i32);
  return builder.makeStringNew(StringNewFromCodePoint, codePoint);
}

Expression* TranslateToFuzzReader::makeStringConst() {
  // Construct an interesting WTF-8 string from parts and use string.const.
  std::stringstream wtf8;
  bool lastWasLeadingSurrogate = false;
  for (size_t i = 0, end = upTo(4); i < end; ++i) {
    switch (upTo(6)) {
      case 0:
        // A simple ascii string.
        wtf8 << std::to_string(upTo(1024));
        break;
      case 1:
        // '£'
        wtf8 << "\xC2\xA3";
        break;
      case 2:
        // '€'
        wtf8 << "\xE2\x82\xAC";
        break;
      case 3:
        // '𐍈'
        wtf8 << "\xF0\x90\x8D\x88";
        break;
      case 4:
        // The leading surrogate in '𐍈'
        wtf8 << "\xED\xA0\x80";
        lastWasLeadingSurrogate = true;
        continue;
      case 5:
        if (lastWasLeadingSurrogate) {
          // Avoid invalid WTF-8.
          continue;
        }
        // The trailing surrogate in '𐍈'
        wtf8 << "\xED\xBD\x88";
        break;
    }
    lastWasLeadingSurrogate = false;
  }
  std::stringstream wtf16;
  // TODO: Use wtf16.view() once we have C++20.
  String::convertWTF8ToWTF16(wtf16, wtf8.str());
  return builder.makeStringConst(wtf16.str());
}

Expression* TranslateToFuzzReader::makeStringConcat() {
  auto* left = makeTrappingRefUse(HeapType::string);
  auto* right = makeTrappingRefUse(HeapType::string);
  return builder.makeStringConcat(left, right);
}

Expression* TranslateToFuzzReader::makeStringSlice() {
  auto* ref = makeTrappingRefUse(HeapType::string);
  auto* start = make(Type::i32);
  auto* end = make(Type::i32);
  return builder.makeStringSliceWTF(ref, start, end);
}

Expression* TranslateToFuzzReader::makeStringEq(Type type) {
  assert(type == Type::i32);

  if (oneIn(2)) {
    auto* left = make(Type(HeapType::string, getNullability()));
    auto* right = make(Type(HeapType::string, getNullability()));
    return builder.makeStringEq(StringEqEqual, left, right);
  }

  // string.compare may trap if the either input is null.
  auto* left = makeTrappingRefUse(HeapType::string);
  auto* right = makeTrappingRefUse(HeapType::string);
  return builder.makeStringEq(StringEqCompare, left, right);
}

Expression* TranslateToFuzzReader::makeStringMeasure(Type type) {
  assert(type == Type::i32);

  auto* ref = makeTrappingRefUse(HeapType::string);
  return builder.makeStringMeasure(StringMeasureWTF16, ref);
}

Expression* TranslateToFuzzReader::makeStringGet(Type type) {
  assert(type == Type::i32);

  auto* ref = makeTrappingRefUse(HeapType::string);
  auto* pos = make(Type::i32);
  return builder.makeStringWTF16Get(ref, pos);
}

Expression* TranslateToFuzzReader::makeTrappingRefUse(HeapType type) {
  return makeTrappingRefUse(Type(type, Nullable));
}

Expression* TranslateToFuzzReader::makeTrappingRefUse(Type type) {
  auto percent = upTo(100);
  // Only give a low probability to emit a nullable reference.
  if (percent < 5) {
    return make(type.with(Nullable));
  }
  // Otherwise, usually emit a non-nullable one.
  auto nonNull = type.with(NonNullable);
  if (percent < 70 || !funcContext) {
    return make(nonNull);
  }
  // With significant probability, try to use an existing value, that is, to
  // get a value using local.get, as it is better to have patterns like this:
  //
  //  (local.set $ref (struct.new $..
  //  (struct.get (local.get $ref))
  //
  // Rather than constantly operating on new data each time:
  //
  //  (local.set $ref (struct.new $..
  //  (struct.get (struct.new $..
  //
  // By using local values more, we get more coverage of interesting sequences
  // of reads and writes to the same objects.
  //
  // Note that makeLocalGet will add a local if necessary, and even tee that
  // value so it is usable later as well.
  return makeLocalGet(nonNull);
}

Expression* TranslateToFuzzReader::buildUnary(const UnaryArgs& args) {
  return builder.makeUnary(args.a, args.b);
}

Expression* TranslateToFuzzReader::makeUnary(Type type) {
  assert(!type.isTuple());
  // There are no unary ops for reference types.
  // TODO: not quite true if you count struct.new and array.new.
  if (type.isRef()) {
    return makeTrivial(type);
  }
  switch (type.getBasic()) {
    case Type::i32: {
      auto singleConcreteType = getSingleConcreteType();
      if (singleConcreteType.isRef()) {
        // TODO: Do something more interesting here.
        return makeTrivial(type);
      }
      switch (singleConcreteType.getBasic()) {
        case Type::i32: {
          auto op = pick(
            FeatureOptions<UnaryOp>()
              .add(FeatureSet::MVP, EqZInt32, ClzInt32, CtzInt32, PopcntInt32)
              .add(FeatureSet::SignExt, ExtendS8Int32, ExtendS16Int32));
          return buildUnary({op, make(Type::i32)});
        }
        case Type::i64:
          return buildUnary({pick(EqZInt64, WrapInt64), make(Type::i64)});
        case Type::f32: {
          auto op = pick(FeatureOptions<UnaryOp>()
                           .add(FeatureSet::MVP,
                                TruncSFloat32ToInt32,
                                TruncUFloat32ToInt32,
                                ReinterpretFloat32)
                           .add(FeatureSet::TruncSat,
                                TruncSatSFloat32ToInt32,
                                TruncSatUFloat32ToInt32));
          return buildUnary({op, make(Type::f32)});
        }
        case Type::f64: {
          auto op = pick(
            FeatureOptions<UnaryOp>()
              .add(FeatureSet::MVP, TruncSFloat64ToInt32, TruncUFloat64ToInt32)
              .add(FeatureSet::TruncSat,
                   TruncSatSFloat64ToInt32,
                   TruncSatUFloat64ToInt32));
          return buildUnary({op, make(Type::f64)});
        }
        case Type::v128: {
          assert(wasm.features.hasSIMD());
          auto op = pick(FeatureOptions<UnaryOp>().add(FeatureSet::SIMD,
                                                       AnyTrueVec128,
                                                       AllTrueVecI8x16,
                                                       AllTrueVecI16x8,
                                                       AllTrueVecI32x4,
                                                       AllTrueVecI64x2,
                                                       BitmaskVecI8x16,
                                                       BitmaskVecI16x8,
                                                       BitmaskVecI32x4,
                                                       BitmaskVecI64x2));
          return buildUnary({op, make(Type::v128)});
        }
        case Type::none:
        case Type::unreachable:
          WASM_UNREACHABLE("unexpected type");
      }
      WASM_UNREACHABLE("invalid type");
    }
    case Type::i64: {
      switch (upTo(4)) {
        case 0: {
          auto op =
            pick(FeatureOptions<UnaryOp>()
                   .add(FeatureSet::MVP, ClzInt64, CtzInt64, PopcntInt64)
                   .add(FeatureSet::SignExt,
                        ExtendS8Int64,
                        ExtendS16Int64,
                        ExtendS32Int64));
          return buildUnary({op, make(Type::i64)});
        }
        case 1:
          return buildUnary(
            {pick(ExtendSInt32, ExtendUInt32), make(Type::i32)});
        case 2: {
          auto op = pick(
            FeatureOptions<UnaryOp>()
              .add(FeatureSet::MVP, TruncSFloat32ToInt64, TruncUFloat32ToInt64)
              .add(FeatureSet::TruncSat,
                   TruncSatSFloat32ToInt64,
                   TruncSatUFloat32ToInt64));
          return buildUnary({op, make(Type::f32)});
        }
        case 3: {
          auto op = pick(FeatureOptions<UnaryOp>()
                           .add(FeatureSet::MVP,
                                TruncSFloat64ToInt64,
                                TruncUFloat64ToInt64,
                                ReinterpretFloat64)
                           .add(FeatureSet::TruncSat,
                                TruncSatSFloat64ToInt64,
                                TruncSatUFloat64ToInt64));
          return buildUnary({op, make(Type::f64)});
        }
      }
      WASM_UNREACHABLE("invalid value");
    }
    case Type::f32: {
      switch (upTo(4)) {
        case 0:
          return buildUnary({pick(NegFloat32,
                                  AbsFloat32,
                                  CeilFloat32,
                                  FloorFloat32,
                                  TruncFloat32,
                                  NearestFloat32,
                                  SqrtFloat32),
                             make(Type::f32)});
        case 1:
          return buildUnary({pick(ConvertUInt32ToFloat32,
                                  ConvertSInt32ToFloat32,
                                  ReinterpretInt32),
                             make(Type::i32)});
        case 2:
          return buildUnary(
            {pick(ConvertUInt64ToFloat32, ConvertSInt64ToFloat32),
             make(Type::i64)});
        case 3:
          return buildUnary({DemoteFloat64, make(Type::f64)});
      }
      WASM_UNREACHABLE("invalid value");
    }
    case Type::f64: {
      switch (upTo(4)) {
        case 0:
          return buildUnary({pick(NegFloat64,
                                  AbsFloat64,
                                  CeilFloat64,
                                  FloorFloat64,
                                  TruncFloat64,
                                  NearestFloat64,
                                  SqrtFloat64),
                             make(Type::f64)});
        case 1:
          return buildUnary(
            {pick(ConvertUInt32ToFloat64, ConvertSInt32ToFloat64),
             make(Type::i32)});
        case 2:
          return buildUnary({pick(ConvertUInt64ToFloat64,
                                  ConvertSInt64ToFloat64,
                                  ReinterpretInt64),
                             make(Type::i64)});
        case 3:
          return buildUnary({PromoteFloat32, make(Type::f32)});
      }
      WASM_UNREACHABLE("invalid value");
    }
    case Type::v128: {
      assert(wasm.features.hasSIMD());
      switch (upTo(5)) {
        case 0:
          return buildUnary({pick(SplatVecI8x16, SplatVecI16x8, SplatVecI32x4),
                             make(Type::i32)});
        case 1:
          return buildUnary({SplatVecI64x2, make(Type::i64)});
        case 2:
          return buildUnary({SplatVecF32x4, make(Type::f32)});
        case 3:
          return buildUnary({SplatVecF64x2, make(Type::f64)});
        case 4:
          return buildUnary({pick(FeatureOptions<UnaryOp>()
                                    .add(FeatureSet::SIMD,
                                         NotVec128,
                                         AbsVecI8x16,
                                         AbsVecI16x8,
                                         AbsVecI32x4,
                                         AbsVecI64x2,
                                         PopcntVecI8x16,
                                         NegVecI8x16,
                                         NegVecI16x8,
                                         NegVecI32x4,
                                         NegVecI64x2,
                                         AbsVecF32x4,
                                         NegVecF32x4,
                                         SqrtVecF32x4,
                                         CeilVecF32x4,
                                         FloorVecF32x4,
                                         TruncVecF32x4,
                                         NearestVecF32x4,
                                         AbsVecF64x2,
                                         NegVecF64x2,
                                         SqrtVecF64x2,
                                         CeilVecF64x2,
                                         FloorVecF64x2,
                                         TruncVecF64x2,
                                         NearestVecF64x2,
                                         ExtAddPairwiseSVecI8x16ToI16x8,
                                         ExtAddPairwiseUVecI8x16ToI16x8,
                                         ExtAddPairwiseSVecI16x8ToI32x4,
                                         ExtAddPairwiseUVecI16x8ToI32x4,
                                         TruncSatSVecF32x4ToVecI32x4,
                                         TruncSatUVecF32x4ToVecI32x4,
                                         ConvertSVecI32x4ToVecF32x4,
                                         ConvertUVecI32x4ToVecF32x4,
                                         ExtendLowSVecI8x16ToVecI16x8,
                                         ExtendHighSVecI8x16ToVecI16x8,
                                         ExtendLowUVecI8x16ToVecI16x8,
                                         ExtendHighUVecI8x16ToVecI16x8,
                                         ExtendLowSVecI16x8ToVecI32x4,
                                         ExtendHighSVecI16x8ToVecI32x4,
                                         ExtendLowUVecI16x8ToVecI32x4,
                                         ExtendHighUVecI16x8ToVecI32x4,
                                         ExtendLowSVecI32x4ToVecI64x2,
                                         ExtendHighSVecI32x4ToVecI64x2,
                                         ExtendLowUVecI32x4ToVecI64x2,
                                         ExtendHighUVecI32x4ToVecI64x2,
                                         ConvertLowSVecI32x4ToVecF64x2,
                                         ConvertLowUVecI32x4ToVecF64x2,
                                         TruncSatZeroSVecF64x2ToVecI32x4,
                                         TruncSatZeroUVecF64x2ToVecI32x4,
                                         DemoteZeroVecF64x2ToVecF32x4,
                                         PromoteLowVecF32x4ToVecF64x2)
                                    .add(FeatureSet::RelaxedSIMD,
                                         RelaxedTruncSVecF32x4ToVecI32x4,
                                         RelaxedTruncUVecF32x4ToVecI32x4,
                                         RelaxedTruncZeroSVecF64x2ToVecI32x4,
                                         RelaxedTruncZeroUVecF64x2ToVecI32x4)
                                    .add(FeatureSet::FP16,
                                         AbsVecF16x8,
                                         NegVecF16x8,
                                         SqrtVecF16x8,
                                         CeilVecF16x8,
                                         FloorVecF16x8,
                                         TruncVecF16x8,
                                         NearestVecF16x8,
                                         TruncSatSVecF16x8ToVecI16x8,
                                         TruncSatUVecF16x8ToVecI16x8,
                                         ConvertSVecI16x8ToVecF16x8,
                                         ConvertUVecI16x8ToVecF16x8)),
                             make(Type::v128)});
      }
      WASM_UNREACHABLE("invalid value");
    }
    case Type::none:
    case Type::unreachable:
      WASM_UNREACHABLE("unexpected type");
  }
  WASM_UNREACHABLE("invalid type");
}

Expression* TranslateToFuzzReader::buildBinary(const BinaryArgs& args) {
  return builder.makeBinary(args.a, args.b, args.c);
}

Expression* TranslateToFuzzReader::makeBinary(Type type) {
  assert(!type.isTuple());
  // There are no binary ops for reference types.
  // TODO: Use struct.new
  if (type.isRef()) {
    return makeTrivial(type);
  }
  switch (type.getBasic()) {
    case Type::i32: {
      switch (upTo(4)) {
        case 0:
          return buildBinary({pick(AddInt32,
                                   SubInt32,
                                   MulInt32,
                                   DivSInt32,
                                   DivUInt32,
                                   RemSInt32,
                                   RemUInt32,
                                   AndInt32,
                                   OrInt32,
                                   XorInt32,
                                   ShlInt32,
                                   ShrUInt32,
                                   ShrSInt32,
                                   RotLInt32,
                                   RotRInt32,
                                   EqInt32,
                                   NeInt32,
                                   LtSInt32,
                                   LtUInt32,
                                   LeSInt32,
                                   LeUInt32,
                                   GtSInt32,
                                   GtUInt32,
                                   GeSInt32,
                                   GeUInt32),
                              make(Type::i32),
                              make(Type::i32)});
        case 1:
          return buildBinary({pick(EqInt64,
                                   NeInt64,
                                   LtSInt64,
                                   LtUInt64,
                                   LeSInt64,
                                   LeUInt64,
                                   GtSInt64,
                                   GtUInt64,
                                   GeSInt64,
                                   GeUInt64),
                              make(Type::i64),
                              make(Type::i64)});
        case 2:
          return buildBinary({pick(EqFloat32,
                                   NeFloat32,
                                   LtFloat32,
                                   LeFloat32,
                                   GtFloat32,
                                   GeFloat32),
                              make(Type::f32),
                              make(Type::f32)});
        case 3:
          return buildBinary({pick(EqFloat64,
                                   NeFloat64,
                                   LtFloat64,
                                   LeFloat64,
                                   GtFloat64,
                                   GeFloat64),
                              make(Type::f64),
                              make(Type::f64)});
      }
      WASM_UNREACHABLE("invalid value");
    }
    case Type::i64: {
      return buildBinary({pick(AddInt64,
                               SubInt64,
                               MulInt64,
                               DivSInt64,
                               DivUInt64,
                               RemSInt64,
                               RemUInt64,
                               AndInt64,
                               OrInt64,
                               XorInt64,
                               ShlInt64,
                               ShrUInt64,
                               ShrSInt64,
                               RotLInt64,
                               RotRInt64),
                          make(Type::i64),
                          make(Type::i64)});
    }
    case Type::f32: {
      return buildBinary({pick(AddFloat32,
                               SubFloat32,
                               MulFloat32,
                               DivFloat32,
                               CopySignFloat32,
                               MinFloat32,
                               MaxFloat32),
                          make(Type::f32),
                          make(Type::f32)});
    }
    case Type::f64: {
      return buildBinary({pick(AddFloat64,
                               SubFloat64,
                               MulFloat64,
                               DivFloat64,
                               CopySignFloat64,
                               MinFloat64,
                               MaxFloat64),
                          make(Type::f64),
                          make(Type::f64)});
    }
    case Type::v128: {
      assert(wasm.features.hasSIMD());
      return buildBinary({pick(FeatureOptions<BinaryOp>()
                                 .add(FeatureSet::SIMD,
                                      EqVecI8x16,
                                      NeVecI8x16,
                                      LtSVecI8x16,
                                      LtUVecI8x16,
                                      GtSVecI8x16,
                                      GtUVecI8x16,
                                      LeSVecI8x16,
                                      LeUVecI8x16,
                                      GeSVecI8x16,
                                      GeUVecI8x16,
                                      EqVecI16x8,
                                      NeVecI16x8,
                                      LtSVecI16x8,
                                      LtUVecI16x8,
                                      GtSVecI16x8,
                                      GtUVecI16x8,
                                      LeSVecI16x8,
                                      LeUVecI16x8,
                                      GeSVecI16x8,
                                      GeUVecI16x8,
                                      EqVecI32x4,
                                      NeVecI32x4,
                                      LtSVecI32x4,
                                      LtUVecI32x4,
                                      GtSVecI32x4,
                                      GtUVecI32x4,
                                      LeSVecI32x4,
                                      LeUVecI32x4,
                                      GeSVecI32x4,
                                      GeUVecI32x4,
                                      EqVecI64x2,
                                      NeVecI64x2,
                                      LtSVecI64x2,
                                      GtSVecI64x2,
                                      LeSVecI64x2,
                                      GeSVecI64x2,
                                      EqVecF32x4,
                                      NeVecF32x4,
                                      LtVecF32x4,
                                      GtVecF32x4,
                                      LeVecF32x4,
                                      GeVecF32x4,
                                      EqVecF64x2,
                                      NeVecF64x2,
                                      LtVecF64x2,
                                      GtVecF64x2,
                                      LeVecF64x2,
                                      GeVecF64x2,

                                      // SIMD arithmetic
                                      AndVec128,
                                      OrVec128,
                                      XorVec128,
                                      AndNotVec128,
                                      AddVecI8x16,
                                      AddSatSVecI8x16,
                                      AddSatUVecI8x16,
                                      SubVecI8x16,
                                      SubSatSVecI8x16,
                                      SubSatUVecI8x16,
                                      MinSVecI8x16,
                                      MinUVecI8x16,
                                      MaxSVecI8x16,
                                      MaxUVecI8x16,
                                      AvgrUVecI8x16,
                                      AddVecI16x8,
                                      AddSatSVecI16x8,
                                      AddSatUVecI16x8,
                                      SubVecI16x8,
                                      SubSatSVecI16x8,
                                      SubSatUVecI16x8,
                                      MulVecI16x8,
                                      MinSVecI16x8,
                                      MinUVecI16x8,
                                      MaxSVecI16x8,
                                      MaxUVecI16x8,
                                      AvgrUVecI16x8,
                                      Q15MulrSatSVecI16x8,
                                      ExtMulLowSVecI16x8,
                                      ExtMulHighSVecI16x8,
                                      ExtMulLowUVecI16x8,
                                      ExtMulHighUVecI16x8,
                                      AddVecI32x4,
                                      SubVecI32x4,
                                      MulVecI32x4,
                                      MinSVecI32x4,
                                      MinUVecI32x4,
                                      MaxSVecI32x4,
                                      MaxUVecI32x4,
                                      DotSVecI16x8ToVecI32x4,
                                      ExtMulLowSVecI32x4,
                                      ExtMulHighSVecI32x4,
                                      ExtMulLowUVecI32x4,
                                      ExtMulHighUVecI32x4,
                                      AddVecI64x2,
                                      SubVecI64x2,
                                      MulVecI64x2,
                                      ExtMulLowSVecI64x2,
                                      ExtMulHighSVecI64x2,
                                      ExtMulLowUVecI64x2,
                                      ExtMulHighUVecI64x2,
                                      AddVecF32x4,
                                      SubVecF32x4,
                                      MulVecF32x4,
                                      DivVecF32x4,
                                      MinVecF32x4,
                                      MaxVecF32x4,
                                      PMinVecF32x4,
                                      PMaxVecF32x4,
                                      AddVecF64x2,
                                      SubVecF64x2,
                                      MulVecF64x2,
                                      DivVecF64x2,
                                      MinVecF64x2,
                                      MaxVecF64x2,
                                      PMinVecF64x2,
                                      PMaxVecF64x2,

                                      // SIMD Conversion
                                      NarrowSVecI16x8ToVecI8x16,
                                      NarrowUVecI16x8ToVecI8x16,
                                      NarrowSVecI32x4ToVecI16x8,
                                      NarrowUVecI32x4ToVecI16x8,

                                      // SIMD Swizzle
                                      SwizzleVecI8x16)
                                 .add(FeatureSet::FP16,
                                      EqVecF16x8,
                                      EqVecF16x8,
                                      NeVecF16x8,
                                      LtVecF16x8,
                                      GtVecF16x8,
                                      LeVecF16x8,
                                      GeVecF16x8,
                                      AddVecF16x8,
                                      SubVecF16x8,
                                      MulVecF16x8,
                                      DivVecF16x8,
                                      MinVecF16x8,
                                      MaxVecF16x8,
                                      PMinVecF16x8,
                                      PMaxVecF16x8)),
                          make(Type::v128),
                          make(Type::v128)});
    }
    case Type::none:
    case Type::unreachable:
      WASM_UNREACHABLE("unexpected type");
  }
  WASM_UNREACHABLE("invalid type");
}

Expression* TranslateToFuzzReader::buildSelect(const ThreeArgs& args) {
  return builder.makeSelect(args.a, args.b, args.c);
}

Expression* TranslateToFuzzReader::makeSelect(Type type) {
  Type subType1 = getSubType(type);
  Type subType2 = getSubType(type);
  return buildSelect({make(Type::i32), make(subType1), make(subType2)});
}

Expression* TranslateToFuzzReader::makeSwitch(Type type) {
  assert(type == Type::unreachable);
  if (funcContext->breakableStack.empty()) {
    return make(type);
  }
  // we need to find proper targets to break to; try a bunch
  int tries = fuzzParams->TRIES;
  std::vector<Name> names;
  Type valueType = Type::unreachable;
  while (tries-- > 0) {
    auto* target = pick(funcContext->breakableStack);
    auto name = getTargetName(target);
    auto currValueType = getTargetType(target);
    if (names.empty()) {
      valueType = currValueType;
    } else {
      if (valueType != currValueType) {
        continue; // all values must be the same
      }
    }
    names.push_back(name);
  }
  if (names.size() < 2) {
    // we failed to find enough
    return make(type);
  }
  auto default_ = names.back();
  names.pop_back();
  auto temp1 = make(Type::i32),
       temp2 = valueType.isConcrete() ? make(valueType) : nullptr;
  return builder.makeSwitch(names, default_, temp1, temp2);
}

Expression* TranslateToFuzzReader::makeDrop(Type type) {
  return builder.makeDrop(make(getConcreteType()));
}

Expression* TranslateToFuzzReader::makeReturn(Type type) {
  return builder.makeReturn(funcContext->func->getResults().isConcrete()
                              ? make(funcContext->func->getResults())
                              : nullptr);
}

Expression* TranslateToFuzzReader::makeNop(Type type) {
  assert(type == Type::none);
  return builder.makeNop();
}

Expression* TranslateToFuzzReader::makeUnreachable(Type type) {
  assert(type == Type::unreachable);
  return builder.makeUnreachable();
}

Expression* TranslateToFuzzReader::makeAtomic(Type type) {
  assert(wasm.features.hasAtomics());
  if (!allowMemory) {
    return makeTrivial(type);
  }
  wasm.memories[0]->shared = true;
  if (type == Type::none) {
    return builder.makeAtomicFence();
  }
  if (type == Type::i32 && oneIn(2)) {
    if (ATOMIC_WAITS && oneIn(2)) {
      auto* ptr = makePointer();
      auto expectedType = pick(Type::i32, Type::i64);
      auto* expected = make(expectedType);
      auto* timeout = make(Type::i64);
      return builder.makeAtomicWait(ptr,
                                    expected,
                                    timeout,
                                    expectedType,
                                    logify(get()),
                                    wasm.memories[0]->name);
    } else {
      auto* ptr = makePointer();
      auto* count = make(Type::i32);
      return builder.makeAtomicNotify(
        ptr, count, logify(get()), wasm.memories[0]->name);
    }
  }
  Index bytes;
  switch (type.getBasic()) {
    case Type::i32: {
      switch (upTo(3)) {
        case 0:
          bytes = 1;
          break;
        case 1:
          bytes = pick(1, 2);
          break;
        case 2:
          bytes = pick(1, 2, 4);
          break;
        default:
          WASM_UNREACHABLE("invalide value");
      }
      break;
    }
    case Type::i64: {
      switch (upTo(4)) {
        case 0:
          bytes = 1;
          break;
        case 1:
          bytes = pick(1, 2);
          break;
        case 2:
          bytes = pick(1, 2, 4);
          break;
        case 3:
          bytes = pick(1, 2, 4, 8);
          break;
        default:
          WASM_UNREACHABLE("invalide value");
      }
      break;
    }
    default:
      WASM_UNREACHABLE("unexpected type");
  }
  auto offset = logify(get());
  auto* ptr = makePointer();
  if (oneIn(2)) {
    auto* value = make(type);
    return builder.makeAtomicRMW(
      pick(RMWAdd, RMWSub, RMWAnd, RMWOr, RMWXor, RMWXchg),
      bytes,
      offset,
      ptr,
      value,
      type,
      wasm.memories[0]->name);
  } else {
    auto* expected = make(type);
    auto* replacement = make(type);
    return builder.makeAtomicCmpxchg(
      bytes, offset, ptr, expected, replacement, type, wasm.memories[0]->name);
  }
}

Expression* TranslateToFuzzReader::makeSIMD(Type type) {
  assert(wasm.features.hasSIMD());
  if (type.isRef()) {
    return makeTrivial(type);
  }
  if (type != Type::v128) {
    return makeSIMDExtract(type);
  }
  // TODO: Add SIMDLoadStoreLane once it is generally available
  switch (upTo(7)) {
    case 0:
      return makeUnary(Type::v128);
    case 1:
      return makeBinary(Type::v128);
    case 2:
      return makeSIMDReplace();
    case 3:
      return makeSIMDShuffle();
    case 4:
      return makeSIMDTernary();
    case 5:
      return makeSIMDShift();
    case 6:
      return makeSIMDLoad();
  }
  WASM_UNREACHABLE("invalid value");
}

Expression* TranslateToFuzzReader::makeSIMDExtract(Type type) {
  auto op = static_cast<SIMDExtractOp>(0);
  switch (type.getBasic()) {
    case Type::i32:
      op = pick(ExtractLaneSVecI8x16,
                ExtractLaneUVecI8x16,
                ExtractLaneSVecI16x8,
                ExtractLaneUVecI16x8,
                ExtractLaneVecI32x4);
      break;
    case Type::i64:
      op = ExtractLaneVecI64x2;
      break;
    case Type::f32:
      op = pick(FeatureOptions<SIMDExtractOp>()
                  .add(FeatureSet::SIMD, ExtractLaneVecF32x4)
                  .add(FeatureSet::FP16, ExtractLaneVecF16x8));
      break;
    case Type::f64:
      op = ExtractLaneVecF64x2;
      break;
    case Type::v128:
    case Type::none:
    case Type::unreachable:
      WASM_UNREACHABLE("unexpected type");
  }
  Expression* vec = make(Type::v128);
  uint8_t index = 0;
  switch (op) {
    case ExtractLaneSVecI8x16:
    case ExtractLaneUVecI8x16:
      index = upTo(16);
      break;
    case ExtractLaneSVecI16x8:
    case ExtractLaneUVecI16x8:
    case ExtractLaneVecF16x8:
      index = upTo(8);
      break;
    case ExtractLaneVecI32x4:
    case ExtractLaneVecF32x4:
      index = upTo(4);
      break;
    case ExtractLaneVecI64x2:
    case ExtractLaneVecF64x2:
      index = upTo(2);
      break;
  }
  return builder.makeSIMDExtract(op, vec, index);
}

Expression* TranslateToFuzzReader::makeSIMDReplace() {
  SIMDReplaceOp op =
    pick(FeatureOptions<SIMDReplaceOp>()
           .add(FeatureSet::SIMD,
                ReplaceLaneVecI8x16,
                ReplaceLaneVecI16x8,
                ReplaceLaneVecI32x4,
                ReplaceLaneVecI64x2,
                ReplaceLaneVecF32x4,
                ReplaceLaneVecF64x2)
           .add(FeatureSet::FeatureSet::FP16, ReplaceLaneVecF16x8));
  Expression* vec = make(Type::v128);
  uint8_t index;
  Type lane_t;
  switch (op) {
    case ReplaceLaneVecI8x16:
      index = upTo(16);
      lane_t = Type::i32;
      break;
    case ReplaceLaneVecI16x8:
      index = upTo(8);
      lane_t = Type::i32;
      break;
    case ReplaceLaneVecI32x4:
      index = upTo(4);
      lane_t = Type::i32;
      break;
    case ReplaceLaneVecI64x2:
      index = upTo(2);
      lane_t = Type::i64;
      break;
    case ReplaceLaneVecF16x8:
      index = upTo(8);
      lane_t = Type::f32;
      break;
    case ReplaceLaneVecF32x4:
      index = upTo(4);
      lane_t = Type::f32;
      break;
    case ReplaceLaneVecF64x2:
      index = upTo(2);
      lane_t = Type::f64;
      break;
    default:
      WASM_UNREACHABLE("unexpected op");
  }
  Expression* value = make(lane_t);
  return builder.makeSIMDReplace(op, vec, index, value);
}

Expression* TranslateToFuzzReader::makeSIMDShuffle() {
  Expression* left = make(Type::v128);
  Expression* right = make(Type::v128);
  std::array<uint8_t, 16> mask;
  for (size_t i = 0; i < 16; ++i) {
    mask[i] = upTo(32);
  }
  return builder.makeSIMDShuffle(left, right, mask);
}

Expression* TranslateToFuzzReader::makeSIMDTernary() {
  // TODO: Enable qfma/qfms once it is implemented in V8 and the interpreter
  // SIMDTernaryOp op = pick(Bitselect,
  //                         QFMAF32x4,
  //                         QFMSF32x4,
  //                         QFMAF64x2,
  //                         QFMSF64x2);
  SIMDTernaryOp op = Bitselect;
  Expression* a = make(Type::v128);
  Expression* b = make(Type::v128);
  Expression* c = make(Type::v128);
  return builder.makeSIMDTernary(op, a, b, c);
}

Expression* TranslateToFuzzReader::makeSIMDShift() {
  SIMDShiftOp op = pick(ShlVecI8x16,
                        ShrSVecI8x16,
                        ShrUVecI8x16,
                        ShlVecI16x8,
                        ShrSVecI16x8,
                        ShrUVecI16x8,
                        ShlVecI32x4,
                        ShrSVecI32x4,
                        ShrUVecI32x4,
                        ShlVecI64x2,
                        ShrSVecI64x2,
                        ShrUVecI64x2);
  Expression* vec = make(Type::v128);
  Expression* shift = make(Type::i32);
  return builder.makeSIMDShift(op, vec, shift);
}

Expression* TranslateToFuzzReader::makeSIMDLoad() {
  SIMDLoadOp op = pick(Load8SplatVec128,
                       Load16SplatVec128,
                       Load32SplatVec128,
                       Load64SplatVec128,
                       Load8x8SVec128,
                       Load8x8UVec128,
                       Load16x4SVec128,
                       Load16x4UVec128,
                       Load32x2SVec128,
                       Load32x2UVec128,
                       Load32ZeroVec128,
                       Load64ZeroVec128);
  Address offset = logify(get());
  Address align;
  switch (op) {
    case Load8SplatVec128:
      align = 1;
      break;
    case Load16SplatVec128:
      align = pick(1, 2);
      break;
    case Load32SplatVec128:
      align = pick(1, 2, 4);
      break;
    case Load64SplatVec128:
    case Load8x8SVec128:
    case Load8x8UVec128:
    case Load16x4SVec128:
    case Load16x4UVec128:
    case Load32x2SVec128:
    case Load32x2UVec128:
      align = pick(1, 2, 4, 8);
      break;
    case Load32ZeroVec128:
      align = 4;
      break;
    case Load64ZeroVec128:
      align = 8;
      break;
  }
  Expression* ptr = makePointer();
  return builder.makeSIMDLoad(op, offset, align, ptr, wasm.memories[0]->name);
}

Expression* TranslateToFuzzReader::makeBulkMemory(Type type) {
  if (!allowMemory) {
    return makeTrivial(type);
  }
  assert(wasm.features.hasBulkMemory());
  assert(type == Type::none);
  switch (upTo(4)) {
    case 0:
      return makeMemoryInit();
    case 1:
      return makeDataDrop();
    case 2:
      return makeMemoryCopy();
    case 3:
      return makeMemoryFill();
  }
  WASM_UNREACHABLE("invalid value");
}

Expression* TranslateToFuzzReader::makeTableGet(Type type) {
  // Emit a get from the funcref table (which always exists) or the exnref one
  // (which might not, if EH is disabled).
  auto makeTableGet = [&](Name tableName) {
    auto* table = wasm.getTable(tableName);
    // Usually emit in-bounds gets, to avoid trapping, but rarely allow
    // anything.
    Expression* index;
    if (allowOOB && oneIn(10)) {
      index = make(table->addressType);
    } else {
      index = builder.makeConst(
        Literal::makeFromInt32(upTo(table->initial), table->addressType));
    }
    return builder.makeTableGet(tableName, index, table->type);
  };
  if (type.getHeapType() == HeapType::exn) {
    return makeTableGet(exnrefTableName);
  } else if (type.getHeapType() == HeapType::func) {
    return makeTableGet(funcrefTableName);
  } else {
    WASM_UNREACHABLE("bad TableGet type");
  }
}

Expression* TranslateToFuzzReader::makeTableSet(Type type) {
  assert(type == Type::none);

  // Emit a set to either the funcref table (which always exists) or the exnref
  // one (which might not, if EH is disabled).
  auto makeTableSet = [&](Name tableName) {
    auto* table = wasm.getTable(tableName);
    // Usually emit in-bounds sets, to avoid trapping, but rarely allow
    // anything.
    Expression* index;
    if (allowOOB && oneIn(10)) {
      index = make(table->addressType);
    } else {
      index = builder.makeConst(
        Literal::makeFromInt32(upTo(table->initial), table->addressType));
    }
    auto* value = make(table->type);
    return builder.makeTableSet(tableName, index, value);
  };
  if (exnrefTableName && oneIn(2)) {
    return makeTableSet(exnrefTableName);
  } else {
    assert(funcrefTableName);
    return makeTableSet(funcrefTableName);
  }
}

Expression* TranslateToFuzzReader::makeRefIsNull(Type type) {
  assert(type == Type::i32);
  assert(wasm.features.hasReferenceTypes());
  return builder.makeRefIsNull(make(getReferenceType()));
}

Expression* TranslateToFuzzReader::makeRefEq(Type type) {
  assert(type == Type::i32);
  assert(wasm.features.hasReferenceTypes() && wasm.features.hasGC());
  auto* left = make(getEqReferenceType());
  auto* right = make(getEqReferenceType());
  return builder.makeRefEq(left, right);
}

Expression* TranslateToFuzzReader::makeRefTest(Type type) {
  assert(type == Type::i32);
  assert(wasm.features.hasReferenceTypes() && wasm.features.hasGC());
  // The case of the reference and the cast type having a connection is useful,
  // so give a decent chance for one to be a subtype of the other.
  Type refType, castType;
  switch (upTo(3)) {
    case 0:
      // Totally random.
      refType = getCastableReferenceType();
      castType = getCastableReferenceType();
      // They must share a bottom type in order to validate.
      if (refType.getHeapType().getBottom() ==
          castType.getHeapType().getBottom()) {
        break;
      }
      // Otherwise, fall through and generate things in a way that is
      // guaranteed to validate.
      [[fallthrough]];
    case 1:
      // Cast is a subtype of ref.
      refType = getCastableReferenceType();
      castType = getSubType(refType);
      break;
    case 2:
      // Ref is a subtype of cast.
      castType = getCastableReferenceType();
      refType = getSubType(castType);
      break;
    default:
      // This unreachable avoids a warning on refType being possibly undefined.
      WASM_UNREACHABLE("bad case");
  }
  if (!wasm.features.hasCustomDescriptors()) {
    // Exact cast targets disallowed without custom descriptors.
    castType = castType.with(Inexact);
  }
  return builder.makeRefTest(make(refType), castType);
}

Expression* TranslateToFuzzReader::makeRefCast(Type type) {
  assert(type.isRef());
  assert(wasm.features.hasReferenceTypes() && wasm.features.hasGC());
  assert(type.isInexact() || wasm.features.hasCustomDescriptors());
  // As with RefTest, use possibly related types. Unlike there, we are given the
  // output type, which is the cast type, so just generate the ref's type.
  Type refType;
  switch (upTo(3)) {
    case 0:
      // Totally random.
      refType = getCastableReferenceType();
      // They must share a bottom type in order to validate.
      if (refType.getHeapType().getBottom() == type.getHeapType().getBottom()) {
        break;
      }
      // Otherwise, fall through and generate things in a way that is
      // guaranteed to validate.
      [[fallthrough]];
    case 1: {
      // Cast is a subtype of ref. We can't modify |type|, so find a supertype
      // for the ref.
      refType = getSuperType(type);
      break;
    }
    case 2:
      // Ref is a subtype of cast.
      refType = getSubType(type);
      break;
    default:
      // This unreachable avoids a warning on refType being possibly undefined.
      WASM_UNREACHABLE("bad case");
  }
  auto* ref = make(refType);

  // Emit a non-descriptor cast if we have to, or otherwise half the time.
  auto desc = type.getHeapType().getDescriptorType();
  if (!desc || oneIn(2)) {
    return builder.makeRefCast(ref, type);
  }

  // Emit a descriptor for a descriptor cast.
  auto* descRef = make(type.with(*desc));
  auto* ret = builder.makeRefCast(ref, descRef, type);
  // descRef may be a subtype of the type we asked make() for, and if so then
  // it might have a different described type - perhaps even an unrelated one,
  // if the descriptors subtype but not the describees. Use an exact type to
  // fix that up.
  if (!Type::isSubType(ret->type, type)) {
    descRef = make(type.with(*desc).with(Exact));
    ret = builder.makeRefCast(ref, descRef, type);
  }
  return ret;
}

Expression* TranslateToFuzzReader::makeRefGetDesc(Type type) {
  auto described = type.getHeapType().getDescribedType();
  assert(described);
  auto refType = type.with(*described);
  return builder.makeRefGetDesc(make(refType));
}

Expression* TranslateToFuzzReader::makeBrOn(Type type) {
  if (funcContext->breakableStack.empty()) {
    return makeTrivial(type);
  }
  // We need to find a proper target to break to; try a few times. Finding the
  // target is harder than flowing out the proper type, so focus on the target,
  // and fix up the flowing type later. That is, once we find a target to break
  // to, we can then either drop ourselves or wrap ourselves in a block +
  // another value, so that we return the proper thing here (which is done below
  // in fixFlowingType).
  int tries = fuzzParams->TRIES;
  Name targetName;
  Type targetType;
  while (--tries >= 0) {
    auto* target = pick(funcContext->breakableStack);
    targetName = getTargetName(target);
    targetType = getTargetType(target);
    // We can send any reference type, or no value at all, but nothing else.
    if (targetType.isRef() || targetType == Type::none) {
      break;
    }
  }
  if (tries < 0) {
    return makeTrivial(type);
  }

  auto fixFlowingType = [&](Expression* brOn) -> Expression* {
    if (Type::isSubType(brOn->type, type)) {
      // Already of the proper type.
      return brOn;
    }
    if (type == Type::none) {
      // We just need to drop whatever it is.
      return builder.makeDrop(brOn);
    }
    // We need to replace the type with something else. Drop the BrOn if we need
    // to, and append a value with the proper type.
    if (brOn->type != Type::none) {
      brOn = builder.makeDrop(brOn);
    }
    return builder.makeSequence(brOn, make(type));
  };

  // We found something to break to. Figure out which BrOn variants we can
  // send.
  if (targetType == Type::none) {
    // BrOnNull is the only variant that sends no value.
    return fixFlowingType(
      builder.makeBrOn(BrOnNull, targetName, make(getReferenceType())));
  }

  // We are sending a reference type to the target. All other BrOn variants can
  // do that.
  assert(targetType.isRef());
  // BrOnNonNull can handle sending any reference. The casts are more limited.
  auto op = BrOnNonNull;
  if (targetType.isCastable()) {
    op = pick(BrOnNonNull, BrOnCast, BrOnCastFail);
  }
  Type castType = Type::none;
  Type refType;
  switch (op) {
    case BrOnNonNull: {
      // The sent type is the non-nullable version of the reference, so any ref
      // of that type is ok, nullable or not.
      refType = targetType.with(getNullability());
      break;
    }
    case BrOnCast: {
      // The sent type is the heap type we cast to, with the input type's
      // nullability, so the combination of the two must be a subtype of
      // targetType.
      castType = getSubType(targetType);
      if (castType.isExact() && !wasm.features.hasCustomDescriptors()) {
        // This exact cast is only valid if its input has the same type (or the
        // only possible strict subtype, bottom).
        refType = castType;
      } else {
        // The ref's type must be castable to castType, or we'd not validate.
        // But it can also be a subtype, which will trivially also succeed (so
        // do that more rarely). Pick subtypes rarely, as they make the cast
        // trivial.
        refType = oneIn(5) ? getSubType(castType) : getSuperType(castType);
      }
      if (targetType.isNonNullable()) {
        // And it must have the right nullability for the target, as mentioned
        // above: if the target type is non-nullable then either the ref or the
        // cast types must be.
        if (!refType.isNonNullable() && !castType.isNonNullable()) {
          // Pick one to make non-nullable.
          if (oneIn(2)) {
            refType = Type(refType.getHeapType(), NonNullable);
          } else {
            castType = Type(castType.getHeapType(), NonNullable);
          }
        }
      }
      break;
    }
    case BrOnCastFail: {
      // The sent type is the ref's type, with adjusted nullability (if the cast
      // allows nulls then no null can fail the cast, and what is sent is non-
      // nullable). First, pick a ref type that we can send to the target.
      refType = getSubType(targetType);
      // See above on BrOnCast, but flipped.
      castType = oneIn(5) ? getSuperType(refType) : getSubType(refType);
      castType = castType.withInexactIfNoCustomDescs(wasm.features);
      // There is no nullability to adjust: if targetType is non-nullable then
      // both refType and castType are as well, as subtypes of it. But we can
      // also allow castType to be nullable (it is not sent to the target).
      if (castType.isNonNullable() && oneIn(2)) {
        castType = Type(castType.getHeapType(), Nullable);
      }
    } break;
    default: {
      WASM_UNREACHABLE("bad br_on op");
    }
  }
  return fixFlowingType(
    builder.makeBrOn(op, targetName, make(refType), castType));
}

bool TranslateToFuzzReader::maybeSignedGet(const Field& field) {
  if (field.isPacked()) {
    return oneIn(2);
  }
  return false;
}

Expression* TranslateToFuzzReader::makeStructGet(Type type) {
  auto& structFields = typeStructFields[type];
  assert(!structFields.empty());
  auto [structType, fieldIndex] = pick(structFields);
  auto* ref = makeTrappingRefUse(structType);
  auto signed_ = maybeSignedGet(structType.getStruct().fields[fieldIndex]);
  return builder.makeStructGet(
    fieldIndex, ref, MemoryOrder::Unordered, type, signed_);
}

Expression* TranslateToFuzzReader::makeStructSet(Type type) {
  assert(type == Type::none);
  if (mutableStructFields.empty()) {
    return makeTrivial(type);
  }
  auto [structType, fieldIndex] = pick(mutableStructFields);
  auto fieldType = structType.getStruct().fields[fieldIndex].type;
  auto* ref = makeTrappingRefUse(structType);
  auto* value = make(fieldType);
  return builder.makeStructSet(fieldIndex, ref, value, MemoryOrder::Unordered);
}

// Make a bounds check for an array operation, given a ref + index. An optional
// additional length parameter can be provided, which is added to the index if
// so (that is useful for something like array.fill, which operations on not a
// single item like array.set, but a range).
static auto makeArrayBoundsCheck(Expression* ref,
                                 Expression* index,
                                 Function* func,
                                 Builder& builder,
                                 Expression* length = nullptr) {
  // The reference might be a RefNull, in which case its type is exact. But we
  // want to avoid creating exact-typed locals until we support them more widely
  // in the fuzzer, so adjust the type. TODO: remove this once exact references
  // are better supported.
  Type refType = ref->type;
  if (refType.isExact()) {
    refType = refType.with(Inexact);
  }
  auto tempRef = builder.addVar(func, refType);
  auto tempIndex = builder.addVar(func, index->type);
  auto* teeRef = builder.makeLocalTee(tempRef, ref, refType);
  auto* teeIndex = builder.makeLocalTee(tempIndex, index, index->type);
  auto* getSize = builder.makeArrayLen(teeRef);

  Expression* effectiveIndex = teeIndex;

  Expression* getLength = nullptr;
  if (length) {
    // Store the length so we can reuse it.
    auto tempLength = builder.addVar(func, length->type);
    auto* teeLength = builder.makeLocalTee(tempLength, length, length->type);
    // The effective index will now include the length.
    effectiveIndex = builder.makeBinary(AddInt32, effectiveIndex, teeLength);
    getLength = builder.makeLocalGet(tempLength, length->type);
  }

  struct BoundsCheck {
    // A condition that checks if the index is in bounds.
    Expression* condition;
    // An additional use of the reference (we stored the reference in a local,
    // so this reads from that local).
    Expression* getRef;
    // An additional use of the index (as with the ref, it reads from a local).
    Expression* getIndex;
    // An additional use of the length, if it was provided.
    Expression* getLength = nullptr;
  } result = {builder.makeBinary(LtUInt32, effectiveIndex, getSize),
              builder.makeLocalGet(tempRef, refType),
              builder.makeLocalGet(tempIndex, index->type),
              getLength};
  return result;
}

Expression* TranslateToFuzzReader::makeArrayGet(Type type) {
  auto& arrays = typeArrays[type];
  assert(!arrays.empty());
  auto arrayType = pick(arrays);
  auto* ref = makeTrappingRefUse(arrayType);
  auto* index = make(Type::i32);
  auto signed_ = maybeSignedGet(arrayType.getArray().element);
  // Only rarely emit a plain get which might trap. See related logic in
  // ::makePointer().
  if (allowOOB && oneIn(10)) {
    return builder.makeArrayGet(
      ref, index, MemoryOrder::Unordered, type, signed_);
  }
  // To avoid a trap, check the length dynamically using this pattern:
  //
  //   index < array.len ? array[index] : ..some fallback value..
  //
  auto check = makeArrayBoundsCheck(ref, index, funcContext->func, builder);
  auto* get = builder.makeArrayGet(
    check.getRef, check.getIndex, MemoryOrder::Unordered, type, signed_);
  auto* fallback = makeTrivial(type);
  return builder.makeIf(check.condition, get, fallback);
}

Expression* TranslateToFuzzReader::makeArraySet(Type type) {
  assert(type == Type::none);
  if (mutableArrays.empty()) {
    return makeTrivial(type);
  }
  auto arrayType = pick(mutableArrays);
  auto elementType = arrayType.getArray().element.type;
  auto* index = make(Type::i32);
  auto* ref = makeTrappingRefUse(arrayType);
  auto* value = make(elementType);
  // Only rarely emit a plain get which might trap. See related logic in
  // ::makePointer().
  if (allowOOB && oneIn(10)) {
    return builder.makeArraySet(ref, index, value, MemoryOrder::Unordered);
  }
  // To avoid a trap, check the length dynamically using this pattern:
  //
  //   if (index < array.len) array[index] = value;
  //
  auto check = makeArrayBoundsCheck(ref, index, funcContext->func, builder);
  auto* set = builder.makeArraySet(
    check.getRef, check.getIndex, value, MemoryOrder::Unordered);
  return builder.makeIf(check.condition, set);
}

Expression* TranslateToFuzzReader::makeArrayBulkMemoryOp(Type type) {
  assert(type == Type::none);
  if (mutableArrays.empty()) {
    return makeTrivial(type);
  }
  auto arrayType = pick(mutableArrays);
  auto element = arrayType.getArray().element;
  auto* index = make(Type::i32);
  auto* ref = makeTrappingRefUse(arrayType);
  if (oneIn(2)) {
    // ArrayFill
    auto* value = make(element.type);
    auto* length = make(Type::i32);
    // Only rarely emit a plain get which might trap. See related logic in
    // ::makePointer().
    if (allowOOB && oneIn(10)) {
      return builder.makeArrayFill(ref, index, value, length);
    }
    auto check =
      makeArrayBoundsCheck(ref, index, funcContext->func, builder, length);
    auto* fill = builder.makeArrayFill(
      check.getRef, check.getIndex, value, check.getLength);
    return builder.makeIf(check.condition, fill);
  } else {
    // ArrayCopy. Here we must pick a source array whose element type is a
    // subtype of the destination.
    auto srcArrayType = pick(mutableArrays);
    auto srcElement = srcArrayType.getArray().element;
    if (!Type::isSubType(srcElement.type, element.type) ||
        element.packedType != srcElement.packedType) {
      // TODO: A matrix of which arrays are subtypes of others. For now, if we
      // didn't get what we want randomly, just copy from the same type to
      // itself.
      srcArrayType = arrayType;
      srcElement = element;
    }
    auto* srcIndex = make(Type::i32);
    auto* srcRef = makeTrappingRefUse(srcArrayType);
    auto* length = make(Type::i32);
    if (allowOOB && oneIn(10)) {
      return builder.makeArrayCopy(ref, index, srcRef, srcIndex, length);
    }
    auto check =
      makeArrayBoundsCheck(ref, index, funcContext->func, builder, length);
    auto srcCheck = makeArrayBoundsCheck(
      srcRef, srcIndex, funcContext->func, builder, check.getLength);
    auto* copy = builder.makeArrayCopy(check.getRef,
                                       check.getIndex,
                                       srcCheck.getRef,
                                       srcCheck.getIndex,
                                       srcCheck.getLength);
    return builder.makeIf(check.condition,
                          builder.makeIf(srcCheck.condition, copy));
  }
}

Expression* TranslateToFuzzReader::makeStringEncode(Type type) {
  assert(type == Type::i32);

  auto* ref = makeTrappingRefUse(HeapType::string);
  auto* array = makeTrappingRefUse(HeapTypes::getMutI16Array());
  auto* start = make(Type::i32);

  // Only rarely emit without a bounds check, which might trap. See related
  // logic in other array operations.
  if (allowOOB || oneIn(10)) {
    return builder.makeStringEncode(StringEncodeWTF16Array, ref, array, start);
  }

  // Stash the string reference while computing its length for a bounds check.
  auto refLocal = builder.addVar(funcContext->func, ref->type);
  auto* setRef = builder.makeLocalSet(refLocal, ref);
  auto* strLen = builder.makeStringMeasure(
    StringMeasureWTF16, builder.makeLocalGet(refLocal, ref->type));

  // Do a bounds check on the array.
  auto check =
    makeArrayBoundsCheck(array, start, funcContext->func, builder, strLen);
  array = check.getRef;
  start = check.getIndex;
  auto* getRef = builder.makeLocalGet(refLocal, ref->type);
  auto* encode =
    builder.makeStringEncode(StringEncodeWTF16Array, getRef, array, start);

  // Emit the set of the string reference and then an if that picks which code
  // path to visit, depending on the outcome of the bounds check.
  auto* iff = builder.makeIf(check.condition, encode, make(Type::i32));
  return builder.makeSequence(setRef, iff);
}

Expression* TranslateToFuzzReader::makeI31Get(Type type) {
  assert(type == Type::i32);
  assert(wasm.features.hasReferenceTypes() && wasm.features.hasGC());
  auto* i31 = makeTrappingRefUse(HeapType::i31);
  return builder.makeI31Get(i31, bool(oneIn(2)));
}

Expression* TranslateToFuzzReader::makeThrow(Type type) {
  assert(type == Type::unreachable);
  Tag* tag;
  if (trivialNesting || random.finished()) {
    // We are nested under a makeTrivial call, so only emit something trivial.
    // Get (or create) a trivial tag, so we have no operands (and will not call
    // make(), below). Otherwise, we might recurse very deeply if we threw a
    // tag that contains an exnref (for which we may end up creating yet another
    // throw in a try).
    if (!trivialTag) {
      auto newTag = builder.makeTag(Names::getValidTagName(wasm, "tag$"),
                                    Signature(Type::none, Type::none));
      tag = wasm.addTag(std::move(newTag));
      trivialTag = tag->name;
    } else {
      tag = wasm.getTag(trivialTag);
    }
  } else {
    // Get a random tag, adding a random one if necessary.
    if (exceptionTags.empty()) {
      addTag();
    }
    tag = pick(exceptionTags);
  }
  auto tagType = tag->params();
  std::vector<Expression*> operands;
  for (auto t : tagType) {
    operands.push_back(make(t));
  }
  return builder.makeThrow(tag, operands);
}

Expression* TranslateToFuzzReader::makeThrowRef(Type type) {
  assert(type == Type::unreachable);
  // Use a nullable type here to avoid the risk of trapping (when we find no way
  // to make a non-nullable ref, we end up fixing validation with
  // ref.as_non_null of a null, which validates but traps).
  auto* ref = make(Type(HeapType::exn, Nullable));
  return builder.makeThrowRef(ref);
}

Expression* TranslateToFuzzReader::makeMemoryInit() {
  if (!allowMemory) {
    return makeTrivial(Type::none);
  }
  Index segIdx = upTo(wasm.dataSegments.size());
  Name segment = wasm.dataSegments[segIdx]->name;
  size_t totalSize = wasm.dataSegments[segIdx]->data.size();
  size_t offsetVal = upTo(totalSize);
  size_t sizeVal = upTo(totalSize - offsetVal);
  Expression* dest = makePointer();
  Expression* offset = builder.makeConst(int32_t(offsetVal));
  Expression* size = builder.makeConst(int32_t(sizeVal));
  return builder.makeMemoryInit(
    segment, dest, offset, size, wasm.memories[0]->name);
}

Expression* TranslateToFuzzReader::makeDataDrop() {
  if (!allowMemory) {
    return makeTrivial(Type::none);
  }
  Index segIdx = upTo(wasm.dataSegments.size());
  Name segment = wasm.dataSegments[segIdx]->name;
  return builder.makeDataDrop(segment);
}

Expression* TranslateToFuzzReader::makeMemoryCopy() {
  if (!allowMemory) {
    return makeTrivial(Type::none);
  }
  Expression* dest = makePointer();
  Expression* source = makePointer();
  Expression* size = make(wasm.memories[0]->addressType);
  return builder.makeMemoryCopy(
    dest, source, size, wasm.memories[0]->name, wasm.memories[0]->name);
}

Expression* TranslateToFuzzReader::makeMemoryFill() {
  if (!allowMemory) {
    return makeTrivial(Type::none);
  }
  Expression* dest = makePointer();
  Expression* value = make(Type::i32);
  Expression* size = make(wasm.memories[0]->addressType);
  return builder.makeMemoryFill(dest, value, size, wasm.memories[0]->name);
}

Type TranslateToFuzzReader::getSingleConcreteType() {
  if (wasm.features.hasReferenceTypes() && !interestingHeapTypes.empty() &&
      oneIn(3)) {
    auto heapType = pick(interestingHeapTypes);
    auto nullability = getNullability();
    return Type(heapType, nullability);
  }
  // Skip (ref func|extern|i31|exn) because there is no way to create them in
  // globals. TODO
  using WeightedOption = FeatureOptions<Type>::WeightedOption;
  return pick(FeatureOptions<Type>()
                .add(FeatureSet::MVP,
                     WeightedOption{Type::i32, VeryImportant},
                     WeightedOption{Type::i64, VeryImportant},
                     WeightedOption{Type::f32, VeryImportant},
                     WeightedOption{Type::f64, VeryImportant})
                .add(FeatureSet::SIMD, WeightedOption{Type::v128, Important})
                .add(FeatureSet::ReferenceTypes,
                     Type(HeapType::func, Nullable),
                     Type(HeapType::ext, Nullable))
                .add(FeatureSet::ExceptionHandling,
                     // Type(HeapType::exn, NonNullable),
                     Type(HeapType::exn, Nullable))
                .add(FeatureSet::ReferenceTypes | FeatureSet::GC,
                     // Type(HeapType::func, NonNullable),
                     // Type(HeapType::ext, NonNullable),
                     Type(HeapType::any, Nullable),
                     // Type(HeapType::any, NonNullable),
                     Type(HeapType::eq, Nullable),
                     Type(HeapType::eq, NonNullable),
                     Type(HeapType::i31, Nullable),
                     // Type(HeapType::i31, NonNullable),
                     Type(HeapType::struct_, Nullable),
                     Type(HeapType::struct_, NonNullable),
                     Type(HeapType::array, Nullable),
                     Type(HeapType::array, NonNullable))
                .add(FeatureSet::Strings,
                     Type(HeapType::string, Nullable),
                     Type(HeapType::string, NonNullable)));
}

Type TranslateToFuzzReader::getReferenceType() {
  if (wasm.features.hasReferenceTypes() && !interestingHeapTypes.empty() &&
      oneIn(2)) {
    auto heapType = pick(interestingHeapTypes);
    auto nullability = getNullability();
    return Type(heapType, nullability);
  }
  return pick(FeatureOptions<Type>()
                // TODO: Add externref here.
                .add(FeatureSet::ReferenceTypes, Type(HeapType::func, Nullable))
                .add(FeatureSet::ReferenceTypes | FeatureSet::GC,
                     Type(HeapType::func, NonNullable),
                     Type(HeapType::any, NonNullable),
                     Type(HeapType::eq, Nullable),
                     Type(HeapType::eq, NonNullable),
                     Type(HeapType::i31, Nullable),
                     Type(HeapType::i31, NonNullable),
                     Type(HeapType::struct_, Nullable),
                     Type(HeapType::struct_, NonNullable),
                     Type(HeapType::array, Nullable),
                     Type(HeapType::array, NonNullable))
                .add(FeatureSet::Strings,
                     Type(HeapType::string, Nullable),
                     Type(HeapType::string, NonNullable)));
}

Type TranslateToFuzzReader::getCastableReferenceType() {
  int tries = fuzzParams->TRIES;
  while (tries-- > 0) {
    auto type = getReferenceType();
    if (type.isCastable()) {
      return type;
    }
  }
  // We failed to find a type using fair sampling. Do something simple that must
  // work.
  Type type;
  if (oneIn(4)) {
    type = getSubType(Type(HeapType::func, Nullable));
  } else {
    type = getSubType(Type(HeapType::any, Nullable));
  }
  assert(type.isCastable());
  return type;
}

Type TranslateToFuzzReader::getEqReferenceType() {
  if (oneIn(2) && !interestingHeapTypes.empty()) {
    // Try to find an interesting eq-compatible type.
    auto heapType = pick(interestingHeapTypes);
    if (HeapType::isSubType(heapType, HeapType::eq)) {
      auto nullability = getNullability();
      return Type(heapType, nullability);
    }
    // Otherwise continue below.
  }
  return pick(
    FeatureOptions<Type>().add(FeatureSet::ReferenceTypes | FeatureSet::GC,
                               Type(HeapType::eq, Nullable),
                               Type(HeapType::eq, NonNullable),
                               Type(HeapType::i31, Nullable),
                               Type(HeapType::i31, NonNullable),
                               Type(HeapType::struct_, Nullable),
                               Type(HeapType::struct_, NonNullable),
                               Type(HeapType::array, Nullable),
                               Type(HeapType::array, NonNullable)));
}

Type TranslateToFuzzReader::getMVPType() {
  return pick(Type::i32, Type::i64, Type::f32, Type::f64);
}

Type TranslateToFuzzReader::getTupleType() {
  std::vector<Type> elements;
  size_t maxElements = 2 + upTo(fuzzParams->MAX_TUPLE_SIZE - 1);
  for (size_t i = 0; i < maxElements; ++i) {
    auto type = getSingleConcreteType();
    // Don't add a non-defaultable type into a tuple, as currently we can't
    // spill them into locals (that would require a "let").
    if (type.isDefaultable()) {
      elements.push_back(type);
    }
  }
  while (elements.size() < 2) {
    elements.push_back(getMVPType());
  }
  return Type(elements);
}

Type TranslateToFuzzReader::getConcreteType() {
  if (wasm.features.hasMultivalue() && oneIn(5)) {
    return getTupleType();
  } else {
    return getSingleConcreteType();
  }
}

Type TranslateToFuzzReader::getControlFlowType() {
  if (oneIn(10)) {
    return Type::none;
  } else {
    return getConcreteType();
  }
}

Type TranslateToFuzzReader::getStorableType() {
  return pick(
    FeatureOptions<Type>()
      .add(FeatureSet::MVP, Type::i32, Type::i64, Type::f32, Type::f64)
      .add(FeatureSet::SIMD, Type::v128));
}

Type TranslateToFuzzReader::getLoggableType() { return pick(loggableTypes); }

bool TranslateToFuzzReader::isLoggableType(Type type) {
  return std::find(loggableTypes.begin(), loggableTypes.end(), type) !=
         loggableTypes.end();
}

Nullability TranslateToFuzzReader::getNullability() {
  // Without wasm GC, avoid non-nullable types as we cannot create any values
  // of such types. For example, reference types adds eqref, but there is no
  // way to create such a value, only to receive it from the outside, while GC
  // adds i31/struct/array creation. Without GC, we will likely need to create a
  // null of this type (unless we are lucky enough to have a non-null value
  // arriving from an import), so avoid a non-null type if possible.
  if (wasm.features.hasGC() && oneIn(2)) {
    return NonNullable;
  }
  return Nullable;
}

Exactness TranslateToFuzzReader::getExactness() {
  // Without GC, the only heap types are func and extern, neither of which is
  // exactly inhabitable. To avoid introducing uninhabitable types, only
  // generate exact references when GC is enabled. We don't need custom
  // descriptors to be enabled even though that is the feature that introduces
  // exact references because the binary writer can always generalize the exact
  // reference types away.
  //
  // if (wasm.features.hasGC() && oneIn(8)) {
  //   return Exact;
  // }
  //
  // However, we cannot yet handle creating exact references in general, so for
  // now we always generate inexact references when given the choice. TODO.
  return Inexact;
}

Nullability TranslateToFuzzReader::getSubType(Nullability nullability) {
  if (nullability == NonNullable) {
    return NonNullable;
  }
  return getNullability();
}

Exactness TranslateToFuzzReader::getSubType(Exactness exactness) {
  if (exactness == Exact) {
    return Exact;
  }
  return getExactness();
}

HeapType TranslateToFuzzReader::getSubType(HeapType type) {
  if (oneIn(3)) {
    return type;
  }
  if (type.isBasic() && oneIn(2)) {
    auto share = type.getShared();
    switch (type.getBasic(Unshared)) {
      case HeapType::func:
        // TODO: Typed function references.
        assert(wasm.features.hasReferenceTypes());
        return pick(FeatureOptions<HeapType>()
                      .add(HeapTypes::func)
                      .add(FeatureSet::GC, HeapTypes::nofunc))
          .getBasic(share);
      case HeapType::cont:
        return pick(HeapTypes::cont, HeapTypes::nocont).getBasic(share);
      case HeapType::ext: {
        assert(wasm.features.hasReferenceTypes());
        auto options = FeatureOptions<HeapType>()
                         .add(HeapTypes::ext)
                         .add(FeatureSet::GC, HeapTypes::noext);
        if (share == Unshared) {
          // Shared strings not yet supported.
          options.add(FeatureSet::Strings, HeapType::string);
        }
        return pick(options).getBasic(share);
      }
      case HeapType::any: {
        assert(wasm.features.hasReferenceTypes());
        assert(wasm.features.hasGC());
        return pick(HeapTypes::any,
                    HeapTypes::eq,
                    HeapTypes::i31,
                    HeapTypes::struct_,
                    HeapTypes::array,
                    HeapTypes::none)
          .getBasic(share);
      }
      case HeapType::eq:
        assert(wasm.features.hasReferenceTypes());
        assert(wasm.features.hasGC());
        return pick(HeapTypes::eq,
                    HeapTypes::i31,
                    HeapTypes::struct_,
                    HeapTypes::array,
                    HeapTypes::none)
          .getBasic(share);
      case HeapType::i31:
        return pick(HeapTypes::i31, HeapTypes::none).getBasic(share);
      case HeapType::struct_:
        return pick(HeapTypes::struct_, HeapTypes::none).getBasic(share);
      case HeapType::array:
        return pick(HeapTypes::array, HeapTypes::none).getBasic(share);
      case HeapType::exn:
        assert(share == Unshared);
        return HeapTypes::exn.getBasic(share);
      case HeapType::string:
        assert(share == Unshared);
        return HeapType::string;
      case HeapType::none:
      case HeapType::noext:
      case HeapType::nofunc:
      case HeapType::nocont:
      case HeapType::noexn:
        break;
    }
  }
  // Look for an interesting subtype.
  auto iter = interestingHeapSubTypes.find(type);
  if (iter != interestingHeapSubTypes.end()) {
    auto& subTypes = iter->second;
    if (!subTypes.empty()) {
      return pick(subTypes);
    }
  }
  // Failure to do anything interesting, return the type.
  return type;
}

Type TranslateToFuzzReader::getSubType(Type type) {
  if (type.isTuple()) {
    std::vector<Type> types;
    for (const auto& t : type) {
      types.push_back(getSubType(t));
    }
    return Type(types);
  } else if (type.isRef()) {
    auto heapType = type.getHeapType();
    // Do not generate non-nullable exnrefs in global positions (they cannot be
    // created in wasm, nor imported from JS).
    if (!funcContext && heapType.isMaybeShared(HeapType::exn)) {
      return type;
    }
    if (type.isExact()) {
      // The only other possible heap type is bottom, but we don't want to
      // generate too many bottom types.
      if (!heapType.isBottom() && oneIn(20)) {
        heapType = heapType.getBottom();
      }
    } else {
      heapType = getSubType(heapType);
    }
    auto nullability = getSubType(type.getNullability());
    auto exactness =
      heapType.isBasic() ? Inexact : getSubType(type.getExactness());
    auto subType = Type(heapType, nullability, exactness);
    // We don't want to emit lots of uninhabitable types like (ref none), so
    // avoid them with high probability. Specifically, if the original type was
    // inhabitable then return that; avoid adding more uninhabitability. We can
    // never add new uninhabitability outside of functions, where we cannot
    // use casts to generate something valid.
    if (GCTypeUtils::isUninhabitable(subType) &&
        !GCTypeUtils::isUninhabitable(type) && (!funcContext || !oneIn(20))) {
      return type;
    }
    return subType;
  } else {
    // This is an MVP type without subtypes.
    assert(type.isBasic());
    return type;
  }
}

Nullability TranslateToFuzzReader::getSuperType(Nullability nullability) {
  if (nullability == Nullable) {
    return Nullable;
  }
  return getNullability();
}

HeapType TranslateToFuzzReader::getSuperType(HeapType type) {
  // TODO cache these?
  std::vector<HeapType> supers;
  while (1) {
    supers.push_back(type);
    if (auto super = type.getDeclaredSuperType()) {
      type = *super;
    } else {
      break;
    }
  }
  return pick(supers);
}

Type TranslateToFuzzReader::getSuperType(Type type) {
  if (!type.isRef()) {
    return type;
  }
  auto heapType = getSuperType(type.getHeapType());
  auto nullability = getSuperType(type.getNullability());
  auto superType = Type(heapType, nullability);
  // As with getSubType, we want to avoid returning an uninhabitable type where
  // possible. Here all we can do is flip the super's nullability to nullable.
  if (GCTypeUtils::isUninhabitable(superType)) {
    superType = Type(heapType, Nullable);
  }
  return superType;
}

Name TranslateToFuzzReader::getTargetName(Expression* target) {
  if (auto* block = target->dynCast<Block>()) {
    return block->name;
  } else if (auto* loop = target->dynCast<Loop>()) {
    return loop->name;
  }
  WASM_UNREACHABLE("unexpected expr type");
}

Type TranslateToFuzzReader::getTargetType(Expression* target) {
  if (auto* block = target->dynCast<Block>()) {
    return block->type;
  } else if (target->is<Loop>()) {
    return Type::none;
  }
  WASM_UNREACHABLE("unexpected expr type");
}

} // namespace wasm
