/*
 * 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/eh-utils.h"
#include "ir/gc-type-utils.h"
#include "ir/glbs.h"
#include "ir/iteration.h"
#include "ir/local-structural-dominance.h"
#include "ir/lubs.h"
#include "ir/module-utils.h"
#include "ir/names.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"
#include "wasm-type.h"

namespace wasm {

namespace {

std::vector<Type> getLoggableTypes(const FeatureSet& features) {
  std::vector<Type> loggableTypes = {
    Type::i32, Type::i64, Type::f32, Type::f64};
  if (features.hasSIMD()) {
    loggableTypes.push_back(Type::v128);
  }
  if (features.hasReferenceTypes()) {
    if (features.hasGC()) {
      loggableTypes.push_back(Type(HeapType::any, Nullable));
      loggableTypes.push_back(Type(HeapType::func, Nullable));
      loggableTypes.push_back(Type(HeapType::ext, Nullable));
    }
    // Note: exnref traps on the JS boundary, so we cannot try to log it.
  }

  return loggableTypes;
}

std::vector<MemoryOrder> getMemoryOrders(const FeatureSet& features) {
  return features.hasAcquireReleaseAtomics()
           ? std::vector{MemoryOrder::AcqRel, MemoryOrder::SeqCst}
           : std::vector{MemoryOrder::SeqCst};
}

} // namespace

TranslateToFuzzReader::TranslateToFuzzReader(Module& wasm,
                                             std::vector<char>&& input,
                                             WorldMode worldMode)
  : wasm(wasm), worldMode(worldMode), builder(wasm),
    random(std::move(input), wasm.features), intrinsics(wasm),
    loggableTypes(getLoggableTypes(wasm.features)),
    atomicMemoryOrders(getMemoryOrders(wasm.features)),

    publicTypeValidator(wasm.features) {

  haveInitialFunctions = !wasm.functions.empty();

  // 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,
                                             WorldMode worldMode)
  : TranslateToFuzzReader(
      wasm, read_file<std::vector<char>>(filename, Flags::Binary), worldMode) {}

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.worldMode = WorldMode::Closed;
          worldMode = WorldMode::Closed;

          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.worldMode == WorldMode::Open && oneIn(2)) {
    options.passOptions.worldMode = WorldMode::Closed;
  }

  // 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);

  if (againstJS) {
    mutateJSBoundary();
  }
}

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);
      bool 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 (!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);
        sigConts[type.getContinuation().type].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;
    }
    Expression* init = nullptr;
    if (wasm.features.hasGC() && oneIn(2)) {
      init = builder.makeConstantExpression(Literal::makeNull(HeapType::func));
    }
    auto tablePtr =
      builder.makeTable(Names::getValidTableName(wasm, "fuzzing_table"),
                        funcref,
                        initial,
                        max,
                        addressType,
                        init);
    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->isActive() && 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);
    }
  }
}

bool TranslateToFuzzReader::isImportableGlobalType(Type type) {
  // TODO: Support more types, but this would require being able to reflect on
  // them from JS.
  return type.isRef() && type.getHeapType() == HeapType::ext;
}

bool TranslateToFuzzReader::isImportableGlobal(Global* global) {
  // TODO: Support mutable globals, but this would require being able to reflect
  // on them from JS.
  return global->mutable_ == false && isImportableGlobalType(global->type);
}

void TranslateToFuzzReader::setupGlobals() {
  // If there were initial wasm contents, there may be imported globals. The
  // fuzzer harness cannot provide all types of imports, so make any imports it
  // can't satisfy into declared globals.
  for (auto& global : wasm.globals) {
    if (global->imported()) {
      // TODO: Once we support more importable global types, sometimes choose to
      // make the global non-imported even if we don't have to. (Right now that
      // isn't very interesting because there's no way to materialize an
      // externref except via another imported global.)
      if (!preserveImportsAndExports && !isImportableGlobal(global.get())) {
        // 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 used an imported global that we made
      // non-imported, it can no longer use the same global unless GC is
      // enabled, since before GC Wasm only made imported globals available in
      // constant expressions.
      if (!wasm.features.hasGC()) {
        auto gets = FindAll<GlobalGet>(global->init);
        for (auto& get : gets.list) {
          if (!wasm.getGlobal(get->name)->imported()) {
            global->init = makeConst(global->type);
            break;
          }
        }
      }
    }
  }

  // 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) {
    // Prefer immutable globals as they can be used in global.gets in other
    // globals for more interesting patterns.
    auto mutability = oneIn(3) ? Builder::Mutable : Builder::Immutable;
    auto name = Names::getValidGlobalName(wasm, "global$");
    auto global =
      builder.makeGlobal(name, getConcreteType(), nullptr, mutability);

    // Sometimes make a new imported global if we can import the type and it is
    // valid to do so.
    if (!preserveImportsAndExports && isImportableGlobal(global.get()) &&
        oneIn(2)) {
      global->module = importedGlobalModuleName;
      global->base = name;
    } else {
      // We can only make something trivial (like a constant) in a global
      // initializer.
      global->init = makeTrivial(global->type);

      if (global->type.isTuple() && !global->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.
        global->init = makeConst(global->type);
        assert(global->init->is<TupleMake>());
      }
      if (!FindAll<RefAs>(global->init).list.empty() ||
          !FindAll<ContNew>(global->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.
        global->type = getMVPType();
        global->init = makeConst(global->type);
      }
    }

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

    useGlobalLater(wasm.addGlobal(std::move(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));
  }

  // Export some tags, sometimes.
  if (!preserveImportsAndExports) {
    for (auto& tag : wasm.tags) {
      if (isValidPublicType(tag->type) && oneIn(2)) {
        auto exportName = Names::getValidExportName(wasm, tag->name);
        wasm.addExport(
          Builder::makeExport(exportName, tag->name, ExternalKind::Tag));
      }
    }
  }
}

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->isActive()) {
      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.
        // TODO: It would be better to avoid segment overlap so that
        // MemoryPacking can run.
        for (auto* get : FindAll<GlobalGet>(segment->offset).list) {
          if (!wasm.getGlobal(get->name)->imported()) {
            segment->offset =
              builder.makeConst(Literal::makeFromInt32(0, memory->addressType));
            break;
          }
        }
      }
      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 + (1 << memory->pageSizeLog2) - 1) /
                         (1 << memory->pageSizeLog2)));
    }
  }
  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. Also use
  // the initial memory size as the maximum, if the initial is now larger
  // (which can happen as we compute the initial size, above: this is where we
  // update the maximum to make sense relative to that new initial size).
  if (memory->max == Memory::kUnlimitedSize || memory->max < memory->initial) {
    memory->max = memory->initial;
  }
  if (memory->max == memory->initial && oneIn(2)) {
    // To allow growth to work (which a testcase may assume), try to make the
    // maximum larger than the initial, some of the time.
    // TODO: scan the wasm for grow instructions?
    memory->max = std::min(
      Address(memory->initial + 1),
      Address(memory->is64() ? memory->maxSize64() : memory->maxSize32()));
  }

  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);
      });

    if (table->init) {
      bool hasNonImported = false;
      for (auto* get : FindAll<GlobalGet>(table->init).list) {
        if (!wasm.getGlobal(get->name)->imported()) {
          hasNonImported = true;
          break;
        }
      }
      if (hasNonImported) {
        // Table initializers can't reference module-defined globals.
        table->init = makeConst(table->type);
      }
    }

    // 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();
      if (table->type.isNonNullable()) {
        table->init = makeConst(table->type);
      }
    }
  }
}

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;
  }

  // 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 (wasm.features.hasReferenceTypes()) {
    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);
        }
      }
    }
  }

  // Decide what to do with the start function. Most of the time we remove it,
  // as that is the least risky for fuzzing (any trap in the start will make
  // the entire module not execute), but other cases are important too.
  //
  // When preserving imports and exports, however, we always keep the start
  // function, as it may be important to keep the contract between the Wasm and
  // the outside (even in that mode, though we have a chance to mutate and
  // empty out or replace the current start, though it declines with the amount
  // of mutation, so the user can control it).
  if (!preserveImportsAndExports) {
    switch (upTo(10)) {
      case 0:
        // Do not modify the start, potentially leaving the existing one.
        break;
      case 1:
        // Pick a new start.
        wasm.start = pickStart();
        break;
      default:
        // Remove it.
        wasm.start = Name();
    }
  }

  // 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());
      }
    }
  }

  // Also fix up closed world, if we need to. We must do this at the end, so
  // nothing can break the closed world assumptions after.
  if (worldMode == WorldMode::Closed) {
    for (auto& func : wasm.functions) {
      if (!func->imported()) {
        fixClosedWorld(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++) {
    func->vars.push_back(getConcreteType());
  }
  // 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);
  }

  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,
  // but in closed world must be careful of callRef*, see the jsCalled logic
  // and isValidRefFuncTarget.
  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));
  }

  // Mark some functions as jsCalled. This allows them to be called by
  // reference even in closed world, using the callRef* imports.
  // TODO: We could do this, and exporting above, to initial content too.
  if (oneIn(4)) {
    auto annotations = intrinsics.getAnnotations(func);
    annotations.jsCalled = true;
    intrinsics.setAnnotations(func, annotations);

    // We cannot actually use this as jsCalled if it does not have a type
    // compatible with the callRef* imports. They send a funcref, so we must
    // only send non-shared functions.
    if (!func->type.getHeapType().isShared()) {
      jsCalled.push_back(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::fixClosedWorld(Function* func) {
  assert(worldMode == WorldMode::Closed);

  struct Fixer
    : public ExpressionStackWalker<Fixer, UnifiedExpressionVisitor<Fixer>> {
    TranslateToFuzzReader& parent;

    Fixer(TranslateToFuzzReader& parent) : parent(parent) {}

    void visitCall(Call* curr) {
      // In closed world, the callRef* imports can cause misoptimization later:
      // they send a funcref to JS to call, and in closed world we assume such
      // calls do not happen unless the function is annotated as jsCalled. We
      // must therefore ensure that calls to these imports only send a jsCalled
      // method and nothing else.
      if (!parent.isCallRefImport(curr->target)) {
        return;
      }

      // These imports take a funcref as the first param.
      assert(!curr->operands.empty());
      if (curr->operands[0]->type == Type::unreachable) {
        // This call is not executed anyhow, and we shouldn't replace it, as
        // that could change the type.
        return;
      }

      if (parent.jsCalled.empty()) {
        // There is nothing valid to call at all. Keep the children (we may
        // need them to validate, e.g. if there is a `pop`), but remove the
        // call.
        std::vector<Expression*> list;
        for (auto* child : curr->operands) {
          list.push_back(parent.builder.makeDrop(child));
        }
        list.push_back(parent.makeTrivial(curr->type));
        replaceCurrent(parent.builder.makeBlock(list));
        return;
      }

      // Set something valid. As above, we must keep the old child for
      // validation reasons.
      auto old = parent.builder.makeDrop(curr->operands[0]);
      auto target = parent.pick(parent.jsCalled);
      assert(parent.isValidRefFuncTarget(target));
      auto new_ = parent.builder.makeRefFunc(target);
      curr->operands[0] = parent.builder.makeSequence(old, new_);
    }
  } fixer(*this);

  FunctionCreationContext context(*this, func);
  fixer.walk(func->body);
}

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.contains(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());
    }
  }
}

void TranslateToFuzzReader::mutateJSBoundary() {
  assert(againstJS);

  // Scan to find functions whose address is taken. We cannot modify their
  // signatures at all.

  struct FunctionInfo {
    // Whether there are references to this function itself.
    bool reffed = false;

    // Calls to imports from this function.
    std::vector<Call*> callImports;
  };

  using NameInfoMap = std::unordered_map<Name, FunctionInfo>;

  struct FunctionInfoScanner
    : public WalkerPass<PostWalker<FunctionInfoScanner>> {
    // Not parallel for simplicity, see the map update below.

    bool modifiesBinaryenIR() override { return false; }

    NameInfoMap& map;

    FunctionInfoScanner(NameInfoMap& map) : map(map) {}

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

    void visitCall(Call* curr) {
      if (getModule()->getFunction(curr->target)->imported()) {
        map[curr->target].callImports.push_back(curr);
      }

      // Return calls add a dependency similar to references: we cannot refine
      // the callee without coordination with the caller.
      if (curr->isReturn) {
        map[curr->target].reffed = true;
      }
    }

    void visitRefFunc(RefFunc* curr) { map[curr->func].reffed = true; }
  };

  NameInfoMap map;
  FunctionInfoScanner scanner(map);
  PassRunner runner(&wasm);
  scanner.setModule(&wasm);
  scanner.run(&runner, &wasm);
  scanner.walkModuleCode(&wasm);

  // If a function does not have its address taken, we can refine types. This is
  // safe because we will still send and receive the right number of values (we
  // are not changing the arity, which JS might notice). Each place we may
  // refine, we are given the maximum refinement and pick a random type between
  // it and the old type.
  auto maybeRefine = [&](Type old, Type new_) {
    if (!old.isRef()) {
      return old;
    }

    // If this is unreachable code, we can still refine to the bottom.
    if (new_ == Type::unreachable) {
      new_ = Type(old.getHeapType().getBottom(), NonNullable);
    }
    assert(Type::isSubType(new_, old));

    // Find all heap types between the old and new, starting from new.
    auto oldHeapType = old.getHeapType();
    auto oldExactness = old.getExactness();
    auto newHeapType = new_.getHeapType();
    auto newExactness = new_.getExactness();
    std::vector<std::pair<HeapType, Exactness>> options;
    while (1) {
      options.push_back({newHeapType, newExactness});
      // We cannot look at a bottom type's supers (there can be many, and the
      // getSuperType() API doesn't return them), but can use
      // interestingHeapSubTypes: any subtype of old is valid.
      if (newHeapType.isBottom()) {
        // We can only do this when the old exactness is inexact: if old was
        // (exact $A) then the only valid subtypes are (exact $A) itself, and
        // the bottom type.
        if (oldExactness == Inexact) {
          for (auto type : interestingHeapSubTypes[oldHeapType]) {
            options.push_back({type, Inexact});
            options.push_back({type, Exact});
          }
          options.push_back({oldHeapType, Inexact});
        }
        // Regardless of the old exactness, it is valid to add the old type as
        // exact (unless the old type was a basic type).
        if (!oldHeapType.isBasic()) {
          options.push_back({oldHeapType, Exact});
        }
        break;
      }
      // Continue until we reach the old type and exactness.
      if (newHeapType == oldHeapType && newExactness == oldExactness) {
        break;
      }
      if (newExactness == Exact) {
        // We are not at the old type and exactness yet (or we would have just
        // stopped). Remove exactness, as the only exact result that is valid is
        // newHeapType itself. That is, if the actual output is (exact $B) then
        // we cannot return (exact $A) for some supertype $A, as that would
        // break subtyping.
        newExactness = Inexact;
        continue;
      }
      auto next = newHeapType.getSuperType();
      assert(next);
      newHeapType = *next;
    }
    auto [heapType, exactness] = pick(options);

    // Pick the nullability.
    auto oldNullability = old.getNullability();
    auto newNullability = new_.getNullability();
    if (newNullability != oldNullability) {
      newNullability = getNullability();
    }

    auto refined = Type(heapType, newNullability, exactness);
    assert(Type::isSubType(refined, old));
    return refined;
  };

  // Given a set of types (all params or all results), and an index among them,
  // refine that index if we can. It is possible that no new types exist at all,
  // if the code was unreachable and we noted nothing.
  auto maybeRefineIndex = [&](Type oldTypes, LUBFinder newLUB, Index index) {
    auto lub =
      newLUB.noted() ? newLUB.getLUB()[index] : Type(Type::unreachable);
    return maybeRefine(oldTypes[index], lub);
  };

  // First, refine params sent to imports. Gather the LUB sent to each import,
  // and then refine.
  std::unordered_map<Name, LUBFinder> paramLUBs;
  for (auto& [_, info] : map) {
    for (auto* call : info.callImports) {
      auto declaredParams = wasm.getFunction(call->target)->getParams();
      std::vector<Type> sent;
      for (Index i = 0; i < call->operands.size(); i++) {
        auto type = call->operands[i]->type;
        if (type == Type::unreachable) {
          // Nothing sent here. What we refine to must still validate, even
          // though this call is unreachable. Using the non-nullable bottom type
          // is valid, and has the fewest restrictions.
          type = declaredParams[i];
          if (type.isRef()) {
            type = Type(type.getHeapType().getBottom(), NonNullable);
          }
        }
        sent.push_back(type);
      }
      paramLUBs[call->target].note(Type(sent));
    }
  }

  for (auto& func : wasm.functions) {
    if (!func->imported()) {
      continue;
    }
    // TODO: In the referenced case, we could consider using import/export
    //       wrappers and refining just there.
    if (map[func->name].reffed) {
      continue;
    }
    // Do not alter the signature of configureAll or other VM builtins. Changing
    // these to something the VM does not expect will just cause it to
    // immediately reject the module by trapping.
    if (func->module.startsWith("wasm:")) {
      continue;
    }

    auto oldParams = func->getParams();
    if (oldParams == Type::none) {
      continue;
    }

    // Refine.
    auto lub = paramLUBs[func->name];
    // Either the LUB has the right data shape, or nothing was noted (this is
    // unreachable).
    assert(oldParams.size() == lub.getLUB().size() || !lub.noted());
    std::vector<Type> newParams;
    for (Index i = 0; i < oldParams.size(); i++) {
      newParams.push_back(maybeRefineIndex(oldParams, lub, i));
    }
    func->setParams(Type(newParams));
  }

  // Second, refine results sent from exports.
  for (auto& exp : wasm.exports) {
    if (exp->kind != ExternalKind::Function) {
      continue;
    }
    auto name = *exp->getInternalName();
    if (map[name].reffed) {
      continue;
    }

    auto* func = wasm.getFunction(name);
    auto oldResults = func->getResults();
    if (oldResults == Type::none) {
      continue;
    }

    // Refine.
    auto lub = LUB::getResultsLUB(func, wasm);
    assert(oldResults.size() == lub.getLUB().size() || !lub.noted());
    std::vector<Type> newResults;
    for (Index i = 0; i < oldResults.size(); i++) {
      newResults.push_back(maybeRefineIndex(oldResults, lub, i));
    }
    func->setResults(Type(newResults));
  }

  // Update return types from calls to exports whose results we refined.
  struct CallUpdater : public WalkerPass<PostWalker<CallUpdater>> {
    bool isFunctionParallel() override { return true; }

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

    void visitCall(Call* curr) {
      if (curr->type != Type::unreachable) {
        curr->type = getModule()->getFunction(curr->target)->getResults();
      }
    }
  } updater;
  updater.setModule(&wasm);
  updater.run(&runner, &wasm);

  // Propagate after our changes.
  ReFinalize().run(&runner, &wasm);
}

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 == Type::i64) {
    options.add(FeatureSet::WideArithmetic | FeatureSet::Multivalue,
                &Self::makeWideIntExtract);
  }
  if (type.isTuple()) {
    if (type == Types::getI64Pair() && oneIn(2)) {
      options.add(FeatureSet::WideArithmetic, &Self::makeWideIntExpression);
    } else {
      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()) {
        // Casts are very fundamental to WasmGC, and a potential source of
        // security issues, so we prioritize them as very important.
        options.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
                    WeightedOption{&Self::makeRefCast, VeryImportant});
      }
    }
    if (heapType.getDescribedType()) {
      options.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
                  &Self::makeRefGetDesc);
    }
    if (heapType.isContinuation()) {
      options.add(FeatureSet::ReferenceTypes | FeatureSet::StackSwitching,
                  &Self::makeContBind);
    }
  }
  if (wasm.features.hasGC()) {
    if (typeStructFields.find(type) != typeStructFields.end()) {
      options.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
                  &Self::makeStructGet);
      options.add(FeatureSet::ReferenceTypes | FeatureSet::GC |
                    FeatureSet::Atomics | FeatureSet::SharedEverything,
                  &Self::makeStructRMW);
      options.add(FeatureSet::ReferenceTypes | FeatureSet::GC |
                    FeatureSet::Atomics | FeatureSet::SharedEverything,
                  &Self::makeStructCmpxchg);
    }
    if (typeArrays.find(type) != typeArrays.end()) {
      options.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
                  &Self::makeArrayGet);
      options.add(FeatureSet::ReferenceTypes | FeatureSet::GC |
                    FeatureSet::Atomics | FeatureSet::SharedEverything,
                  &Self::makeArrayRMW);
      options.add(FeatureSet::ReferenceTypes | FeatureSet::GC |
                    FeatureSet::Atomics | FeatureSet::SharedEverything,
                  &Self::makeArrayCmpxchg);
    }
  }
  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.contains(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 (!isValidRefFuncTarget(target->name)) {
      i++;
      continue;
    }
    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) {
    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::makeWideIntAddSub(Type type) {
  assert(wasm.features.hasWideArithmetic());
  assert(type == Types::getI64Pair());
  auto op = oneIn(2) ? AddInt128 : SubInt128;
  auto* leftLow = make(Type::i64);
  auto* leftHigh = make(Type::i64);
  auto* rightLow = make(Type::i64);
  auto* rightHigh = make(Type::i64);
  return builder.makeWideIntAddSub(op, leftLow, leftHigh, rightLow, rightHigh);
}

Expression* TranslateToFuzzReader::makeWideIntMul(Type type) {
  assert(wasm.features.hasWideArithmetic());
  assert(type == Types::getI64Pair());
  auto op = oneIn(2) ? MulWideSInt64 : MulWideUInt64;
  auto* left = make(Type::i64);
  auto* right = make(Type::i64);
  return builder.makeWideIntMul(op, left, right);
}

Expression* TranslateToFuzzReader::makeWideIntExpression(Type type) {
  return oneIn(2) ? makeWideIntAddSub(type) : makeWideIntMul(type);
}

Expression* TranslateToFuzzReader::makeWideIntExtract(Type type) {
  assert(wasm.features.hasWideArithmetic());
  assert(wasm.features.hasMultivalue());
  assert(type == Type::i64);
  auto* child = makeWideIntExpression(Types::getI64Pair());
  Index index = upTo(2);
  return builder.makeTupleExtract(child, index);
}

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->order = pick(atomicMemoryOrders);
  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->order = pick(atomicMemoryOrders);
  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;
      if (isValidRefFuncTarget(target->name)) {
        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) &&
          isValidRefFuncTarget(func->name)) {
        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));
  assert(isValidRefFuncTarget(func->name));
  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));
      }
      // If we can, prefer using an imported global over a null.
      bool canImport =
        !preserveImportsAndExports && isImportableGlobalType(type);
      if (canImport) {
        bool shouldImport;
        if (type.isNonNullable()) {
          // If we are not in a function context, casting a null is not an
          // option, so always use a global. Otherwise very rarely cast a null.
          shouldImport = !funcContext || !oneIn(16);
        } else {
          // Still prefer a global over a null, but allow nulls more since they
          // will not need immediate casts.
          shouldImport = !oneIn(4);
        }
        if (shouldImport) {
          auto [it, inserted] =
            importedImmutableGlobalsByType.insert({type, {}});
          if (inserted) {
            auto name = Names::getValidGlobalName(wasm, "extern$");
            auto global =
              builder.makeGlobal(name, type, nullptr, Builder::Immutable);
            global->module = importedGlobalModuleName;
            global->base = name;
            useGlobalLater(wasm.addGlobal(std::move(global)));
          }
          assert(!it->second.empty());
          auto global = pick(it->second);
          return builder.makeGlobalGet(global, type);
        }
      }
      // Use a null value, making it non-null if necessary.
      auto null = builder.makeRefNull(HeapTypes::ext.getBasic(share));
      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 (!trivialNesting && 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()) {
        return builder.makeRefAs(RefAsNonNull, null);
      }
      return null;
    }

    case HeapType::waitqueue:
    case HeapType::nowaitqueue: {
      WASM_UNREACHABLE("waitqueue is unimplemented in the fuzzer");
    }
  }
  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({pick(FeatureOptions<UnaryOp>()
                                    .add(FeatureSet::SIMD, SplatVecF32x4)
                                    .add(FeatureSet::FP16, SplatVecF16x8)),
                             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,
                                         PromoteLowVecF16x8ToVecF32x4,
                                         DemoteZeroVecF32x4ToVecF16x8,
                                         DemoteZeroVecF64x2ToVecF16x8)),
                             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::RelaxedSIMD,
                                      RelaxedSwizzleVecI8x16,
                                      RelaxedMinVecF32x4,
                                      RelaxedMaxVecF32x4,
                                      RelaxedMinVecF64x2,
                                      RelaxedMaxVecF64x2,
                                      RelaxedQ15MulrSVecI16x8,
                                      RelaxedDotI8x16I7x16SToVecI16x8)
                                 .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(pick(atomicMemoryOrders));
  }
  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("invalid 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("invalid value");
      }
      break;
    }
    default:
      WASM_UNREACHABLE("unexpected type");
  }
  auto offset = logify(get());
  auto* ptr = makePointer();
  if (oneIn(2)) {
    auto* value = make(type);
    auto op = pick(RMWAdd, RMWSub, RMWAnd, RMWOr, RMWXor, RMWXchg);
    auto order = pick(atomicMemoryOrders);
    return builder.makeAtomicRMW(
      op, bytes, offset, ptr, value, type, wasm.memories[0]->name, order);
  } else {
    auto* expected = make(type);
    auto* replacement = make(type);
    return builder.makeAtomicCmpxchg(bytes,
                                     offset,
                                     ptr,
                                     expected,
                                     replacement,
                                     type,
                                     wasm.memories[0]->name,
                                     pick(atomicMemoryOrders));
  }
}

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() {
  SIMDTernaryOp op =
    pick(FeatureOptions<SIMDTernaryOp>()
           .add(FeatureSet::SIMD, Bitselect)
           .add(FeatureSet::RelaxedSIMD,
                RelaxedMaddVecF32x4,
                RelaxedNmaddVecF32x4,
                RelaxedMaddVecF64x2,
                RelaxedNmaddVecF64x2,
                RelaxedLaneselectI8x16,
                RelaxedLaneselectI16x8,
                RelaxedLaneselectI32x4,
                RelaxedLaneselectI64x2,
                RelaxedDotI8x16I7x16AddSToVecI32x4)
           .add(FeatureSet::FP16, MaddVecF16x8, NmaddVecF16x8));
  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");
    }
  }
  auto* ref = make(refType);
  if (op == BrOnCast || op == BrOnCastFail) {
    auto desc = castType.getHeapType().getDescriptorType();
    if (desc && !oneIn(2)) {
      auto descOp = op == BrOnCast ? BrOnCastDescEq : BrOnCastDescEqFail;
      auto descType = Type(*desc, Nullable, castType.getExactness());
      auto* descRef = makeTrappingRefUse(descType);
      auto* brOn = builder.makeBrOn(descOp, targetName, ref, castType, descRef);
      return fixFlowingType(brOn);
    }
  }
  return fixFlowingType(builder.makeBrOn(op, targetName, ref, castType));
}

Expression* TranslateToFuzzReader::makeContBind(Type type) {
  // We must output a signature that corresponds to the type we were given.
  auto outputSigType = type.getHeapType().getContinuation().type;
  auto outputSig = outputSigType.getSignature();
  auto numOutputParams = outputSig.params.size();

  // Look for a compatible signature. Don't always do this, however - we have a
  // few other options below.
  std::optional<HeapType> inputSigType;
  if (!oneIn(4)) {
    auto& funcTypes = interestingHeapSubTypes[HeapTypes::func];
    // Filter out incompatible signatures.
    std::vector<HeapType> relevantFuncTypes;
    for (auto funcType : funcTypes) {
      auto funcSig = funcType.getSignature();
      if (funcSig.results != outputSig.results) {
        // The results must match.
        continue;
      }

      // The params must be compatible. For example, with output params [x,y,z]
      // we'd want an input signature like [a,b,x,y,z] so that we can bind a and
      // b.
      auto numInputParams = funcSig.params.size();
      if (numInputParams < numOutputParams) {
        // Too short.
        continue;
      }
      // Ignoring the input params at the start, compare the tails.
      auto numAddedParams = numInputParams - numOutputParams;
      bool bad = false;
      for (Index i = 0; i < numOutputParams; i++) {
        if (!Type::isSubType(outputSig.params[i],
                             funcSig.params[numAddedParams + i])) {
          bad = true;
          break;
        }
      }
      if (!bad) {
        relevantFuncTypes.push_back(funcType);
      }
    }
    if (!relevantFuncTypes.empty()) {
      inputSigType = pick(relevantFuncTypes);
    }
  }

  Index numAddedParams;
  if (inputSigType) {
    // We picked a signature, above.
    numAddedParams =
      inputSigType->getSignature().params.size() - numOutputParams;
  } else {
    // We failed to find a signature, either use the current one (binding no
    // input params) or invent a input one, adding one param.
    if (oneIn(2)) {
      inputSigType = outputSigType;
      numAddedParams = 0;
    } else {
      std::vector<Type> inputParams;
      for (auto t : outputSig.params) {
        inputParams.push_back(t);
      }
      auto inputParam = getSingleConcreteType();
      inputParams.insert(inputParams.begin(), inputParam);
      inputSigType = Signature(Type(inputParams), outputSig.results);
      numAddedParams = 1;
    }
  }
  auto inputSig = inputSigType->getSignature();

  // Pick a continuation type for the signature. If existing continuations use
  // it, usually pick one of them.
  auto& inputSigConts = sigConts[*inputSigType];
  HeapType inputCont;
  if (!inputSigConts.empty() && !oneIn(5)) {
    inputCont = pick(inputSigConts);
  } else {
    inputCont = Continuation(inputSig);
  }
  Type inputType = Type(inputCont, NonNullable, Exact);

  // Generate the new args and the cont.bind.
  std::vector<Expression*> newArgs;
  for (Index i = 0; i < numAddedParams; i++) {
    newArgs.push_back(make(inputSig.params[i]));
  }
  return builder.makeContBind(type.getHeapType(), newArgs, make(inputType));
}

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]);
  auto order = MemoryOrder::Unordered;
  if (wasm.features.hasAtomics() && wasm.features.hasSharedEverything() &&
      oneIn(2)) {
    order = oneIn(2) ? MemoryOrder::SeqCst : MemoryOrder::AcqRel;
  }
  return builder.makeStructGet(fieldIndex, ref, order, type, signed_);
}

Expression* TranslateToFuzzReader::makeStructRMW(Type type) {
  bool isAny =
    type.isRef() &&
    HeapType(type.getHeapType().getTop()).isMaybeShared(HeapType::any);
  if (type != Type::i32 && type != Type::i64 && !isAny) {
    // Not a valid field type for an RMW operation.
    return makeStructGet(type);
  }
  auto& structFields = typeStructFields[type];
  assert(!structFields.empty());
  auto [structType, fieldIndex] = pick(structFields);
  const auto& field = structType.getStruct().fields[fieldIndex];
  if (field.isPacked() || field.mutable_ == Immutable) {
    // Cannot RMW a packed or immutable field.
    return makeStructGet(type);
  }
  AtomicRMWOp op = RMWXchg;
  if (type == Type::i32 || type == Type::i64) {
    op = pick(RMWAdd, RMWSub, RMWAnd, RMWOr, RMWXor, RMWXchg);
  }
  auto* ref = makeTrappingRefUse(structType);
  auto* value = make(type);
  auto order = oneIn(2) ? MemoryOrder::SeqCst : MemoryOrder::AcqRel;
  return builder.makeStructRMW(op, fieldIndex, ref, value, order);
}

Expression* TranslateToFuzzReader::makeStructCmpxchg(Type type) {
  bool isShared = type.isRef() && type.getHeapType().isShared();
  Type eq(HeapTypes::eq.getBasic(isShared ? Shared : Unshared), Nullable);
  bool isEq = Type::isSubType(type, eq);
  if (type != Type::i32 && type != Type::i64 && !isEq) {
    // Not a valid field type for a cmpxchg operation.
    return makeStructGet(type);
  }
  auto& structFields = typeStructFields[type];
  assert(!structFields.empty());
  auto [structType, fieldIndex] = pick(structFields);
  const auto& field = structType.getStruct().fields[fieldIndex];
  if (field.isPacked() || field.mutable_ == Immutable) {
    // Cannot RMW a packed or immutable field.
    return makeStructGet(type);
  }
  auto* ref = makeTrappingRefUse(structType);
  // For reference fields, expected can be a subtype of eq. Only do use the
  // extra flexibility occasionally because it makes the expected value less
  // likely to be equal to the actual value.
  auto* expected = make(isEq && oneIn(4) ? eq : type);
  auto* replacement = make(type);
  auto order = oneIn(2) ? MemoryOrder::SeqCst : MemoryOrder::AcqRel;
  return builder.makeStructCmpxchg(
    fieldIndex, ref, expected, replacement, order);
}

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);
  auto order = MemoryOrder::Unordered;
  if (wasm.features.hasAtomics() && wasm.features.hasSharedEverything() &&
      oneIn(2)) {
    order = oneIn(2) ? MemoryOrder::SeqCst : MemoryOrder::AcqRel;
  }
  return builder.makeStructSet(fieldIndex, ref, value, order);
}

// 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);
  auto order = MemoryOrder::Unordered;
  if (wasm.features.hasAtomics() && wasm.features.hasSharedEverything() &&
      oneIn(2)) {
    order = oneIn(2) ? MemoryOrder::SeqCst : MemoryOrder::AcqRel;
  }
  // Only rarely emit a plain get which might trap. See related logic in
  // ::makePointer().
  if (allowOOB && oneIn(10)) {
    return builder.makeArrayGet(ref, index, order, 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, order, 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);
  auto order = MemoryOrder::Unordered;
  if (wasm.features.hasAtomics() && wasm.features.hasSharedEverything() &&
      oneIn(2)) {
    order = oneIn(2) ? MemoryOrder::SeqCst : MemoryOrder::AcqRel;
  }
  // Only rarely emit a plain get which might trap. See related logic in
  // ::makePointer().
  if (allowOOB && oneIn(10)) {
    return builder.makeArraySet(ref, index, value, order);
  }
  // To avoid a trap, check the length dynamically.
  auto check = makeArrayBoundsCheck(ref, index, funcContext->func, builder);
  auto* set = builder.makeArraySet(check.getRef, check.getIndex, value, order);
  return builder.makeIf(check.condition, set);
}

Expression* TranslateToFuzzReader::makeArrayRMW(Type type) {
  bool isAny =
    type.isRef() &&
    HeapType(type.getHeapType().getTop()).isMaybeShared(HeapType::any);
  if (type != Type::i32 && type != Type::i64 && !isAny) {
    // Not a valid element type for an RMW operation.
    return makeArrayGet(type);
  }
  auto& arrays = typeArrays[type];
  assert(!arrays.empty());
  auto arrayType = pick(arrays);
  const auto& element = arrayType.getArray().element;
  if (element.isPacked() || element.mutable_ == Immutable) {
    // Cannot RMW a packed or immutable field.
    return makeArrayGet(type);
  }
  AtomicRMWOp op = RMWXchg;
  if (type == Type::i32 || type == Type::i64) {
    op = pick(RMWAdd, RMWSub, RMWAnd, RMWOr, RMWXor, RMWXchg);
  }
  auto* ref = makeTrappingRefUse(arrayType);
  auto* index = make(Type::i32);
  auto* value = make(type);
  auto order = oneIn(2) ? MemoryOrder::SeqCst : MemoryOrder::AcqRel;
  // Only rarely emit a plain operation which might trap. See related logic in
  // ::makePointer().
  if (allowOOB && oneIn(10)) {
    return builder.makeArrayRMW(op, ref, index, value, order);
  }
  // To avoid a trap, check the length dynamically.
  auto check = makeArrayBoundsCheck(ref, index, funcContext->func, builder);
  auto* rmw =
    builder.makeArrayRMW(op, check.getRef, check.getIndex, value, order);
  auto* fallback = makeTrivial(type);
  return builder.makeIf(check.condition, rmw, fallback);
}

Expression* TranslateToFuzzReader::makeArrayCmpxchg(Type type) {
  bool isShared = type.isRef() && type.getHeapType().isShared();
  Type eq(HeapTypes::eq.getBasic(isShared ? Shared : Unshared), Nullable);
  bool isEq = Type::isSubType(type, eq);
  if (type != Type::i32 && type != Type::i64 && !isEq) {
    // Not a valid element type for a cmpxchg operation.
    return makeArrayGet(type);
  }
  auto& arrays = typeArrays[type];
  assert(!arrays.empty());
  auto arrayType = pick(arrays);
  const auto& element = arrayType.getArray().element;
  if (element.isPacked() || element.mutable_ == Immutable) {
    // Cannot RMW a packed or immutable field.
    return makeArrayGet(type);
  }
  auto* ref = makeTrappingRefUse(arrayType);
  auto* index = make(Type::i32);
  // For reference fields, expected can be a subtype of eq. Only use the extra
  // flexibility occasionally because it makes the expected value less likely to
  // be equal to the actual value.
  auto* expected = make(isEq && oneIn(4) ? eq : type);
  auto* replacement = make(type);
  auto order = oneIn(2) ? MemoryOrder::SeqCst : MemoryOrder::AcqRel;
  // Only rarely emit a plain operation which might trap. See related logic in
  // ::makePointer().
  if (allowOOB && oneIn(10)) {
    return builder.makeArrayCmpxchg(ref, index, expected, replacement, order);
  }
  // To avoid a trap, check the length dynamically.
  auto check = makeArrayBoundsCheck(ref, index, funcContext->func, builder);
  auto* cmpxchg = builder.makeArrayCmpxchg(
    check.getRef, check.getIndex, expected, replacement, order);
  auto* fallback = makeTrivial(type);
  return builder.makeIf(check.condition, cmpxchg, fallback);
}

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() {
  // Give a significant chance to an i64 pair, for wide arithmetic.
  if (wasm.features.hasWideArithmetic() && oneIn(5)) {
    return Types::getI64Pair();
  }

  std::vector<Type> elements;
  size_t numElements = 2 + upTo(fuzzParams->MAX_TUPLE_SIZE - 2);
  for (size_t i = 0; i < numElements; ++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) {
  assert(wasm.features.hasReferenceTypes());
  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.
        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: {
        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.hasGC());
        return pick(HeapTypes::any,
                    HeapTypes::eq,
                    HeapTypes::i31,
                    HeapTypes::struct_,
                    HeapTypes::array,
                    HeapTypes::none)
          .getBasic(share);
      }
      case HeapType::eq:
        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;
      case HeapType::waitqueue:
      case HeapType::nowaitqueue: {
        WASM_UNREACHABLE("waitqueue is unimplemented in the fuzzer");
      }
    }
  }
  // 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");
}

bool TranslateToFuzzReader::isValidRefFuncTarget(Name func) {
  // In closed world, we must not take callRef* by reference: if we do, then we
  // might end up calling them indirectly, and with any possible function
  // reference, but in that mode we must only pass in jsCalled functions. We
  // handle direct calls in fixClosedWorld, but cannot handle indirect ones
  // easily, so just disallow taking references of those functions.
  if (worldMode == WorldMode::Open) {
    return true;
  }
  return !isCallRefImport(func);
}

bool TranslateToFuzzReader::isCallRefImport(Name target) {
  // Check the import module and base. Note we do not just compare to
  // callRefImportName / callRefCatchImportName because those are the names of
  // the methods we added, but the initial content may import those methods
  // under other internal names.
  auto* func = wasm.getFunctionOrNull(target);
  if (!func) {
    // We are called while a function is still being constructed. Such a new
    // defined function can never be an import.
    return false;
  }
  return func->imported() && func->module == "fuzzing-support" &&
         func->base.startsWith("call-ref");
}

Name TranslateToFuzzReader::pickStart() {
  // Any none-none function is an option.
  std::vector<Name> options;
  for (auto& func : wasm.functions) {
    if (func->getParams() == Type::none && func->getResults() == Type::none) {
      options.push_back(func->name);
    }
  }
  return options.empty() ? Name() : pick(options);
}

} // namespace wasm
