// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:collection' show LinkedHashMap;

import 'package:kernel/ast.dart';
import 'package:kernel/type_environment.dart';
import 'package:wasm_builder/wasm_builder.dart' as w;

import 'async.dart';
import 'class_info.dart';
import 'closures.dart';
import 'dispatch_table.dart';
import 'dynamic_forwarders.dart';
import 'intrinsics.dart';
import 'param_info.dart';
import 'records.dart';
import 'reference_extensions.dart';
import 'sync_star.dart';
import 'translator.dart';
import 'types.dart';

abstract class CodeGenerator {
  // The two parameters here are used for inlining:
  //
  // If the user
  //
  //   * inlines the code, it will provide locals and a return label
  //
  //   * doesn't inline (i.e. makes new function with this code) it will provide
  //     the parameters of the function and no return label.
  //
  void generate(
      w.InstructionsBuilder b, List<w.Local> paramLocals, w.Label? returnLabel);
}

/// Main code generator for member bodies.
///
/// The [generate] method first collects all local functions and function
/// expressions in the body and then generates code for the body. Code for the
/// local functions and function expressions must be generated separately by
/// calling the [generateLambda] method on all lambdas in [closures].
///
/// A new [CodeGenerator] object must be created for each new member or lambda.
///
/// Every visitor method for an expression takes in the Wasm type that it is
/// expected to leave on the stack (or the special [voidMarker] to indicate that
/// it should leave nothing). It returns what it actually left on the stack. The
/// code generation for every expression or subexpression is done via the
/// [translateExpression] method, which emits appropriate conversion code if the
/// produced type is not a subtype of the expected type.
abstract class AstCodeGenerator
    extends ExpressionVisitor1<w.ValueType, w.ValueType>
    with ExpressionVisitor1DefaultMixin<w.ValueType, w.ValueType>
    implements InitializerVisitor<void>, StatementVisitor<void>, CodeGenerator {
  final Translator translator;
  final w.FunctionType functionType;
  final Member enclosingMember;

  // To be initialized in `generate()`
  late w.InstructionsBuilder b;
  late final List<w.Local> paramLocals;
  late final w.Label? returnLabel;

  late final Intrinsifier intrinsifier = Intrinsifier(this);
  late final StaticTypeContext typeContext =
      StaticTypeContext(enclosingMember, translator.typeEnvironment);

  late final Closures closures;

  bool exceptionLocationPrinted = false;

  final Map<VariableDeclaration, w.Local> locals = {};
  w.Local? thisLocal;
  w.Local? preciseThisLocal;
  w.Local? returnValueLocal;
  final Map<TypeParameter, w.Local> typeLocals = {};

  // Maps a classes' fields to corresponding locals so that we can update the
  // local directly if a field has both a default value and a FieldInitializer.
  final Map<Field, w.Local> fieldLocals = {};

  /// Finalizers to run on `return`.
  final List<TryBlockFinalizer> returnFinalizers = [];

  /// Finalizers to run on a `break`. `breakFinalizers[L].last` (which should
  /// always be present) is the `br` target for the label `L` that will run the
  /// finalizers, or break out of the loop.
  final LinkedHashMap<LabeledStatement, List<w.Label>> breakFinalizers =
      LinkedHashMap();

  final List<({w.Local exceptionLocal, w.Local stackTraceLocal})>
      tryBlockLocals = [];

  final Map<SwitchCase, w.Label> switchLabels = {};

  /// Maps a switch statement to the information used when doing a backward
  /// jump to one of the cases in the switch statement
  final Map<SwitchStatement, SwitchBackwardJumpInfo> switchBackwardJumpInfos =
      {};

  /// Create a code generator for a member or one of its lambdas.
  AstCodeGenerator(this.translator, this.functionType, this.enclosingMember);

  List<w.ValueType> get outputs => functionType.outputs;

  w.ValueType get returnType => translator.outputOrVoid(outputs);

  TranslatorOptions get options => translator.options;

  w.ValueType get voidMarker => translator.voidMarker;

  Types get types => translator.types;

  w.ValueType translateType(DartType type) => translator.translateType(type);

  w.Local addLocal(w.ValueType type, {String? name}) =>
      b.addLocal(type, name: name);

  DartType dartTypeOf(Expression exp) {
    if (exp is ConstantExpression) {
      // For constant expressions `getStaticType` returns often `DynamicType`
      // instead of a more precise type. See http://dartbug.com/60368
      return exp.constant.getType(typeContext);
    }
    return exp.getStaticType(typeContext);
  }

  void unimplemented(
      TreeNode node, Object message, List<w.ValueType> expectedTypes) {
    final text = "Not implemented: $message at ${node.location}";
    print(text);
    b.comment(text);
    b.block(const [], expectedTypes);
    b.unreachable();
    b.end();
  }

  @override
  w.ValueType defaultExpression(Expression node, w.ValueType expectedType) {
    unimplemented(
        node, node.runtimeType, [if (expectedType != voidMarker) expectedType]);
    return expectedType;
  }

  Source? _sourceMapSource;
  int _sourceMapFileOffset = TreeNode.noOffset;

  /// Update the [Source] for the AST nodes being compiled.
  ///
  /// The [Source] is used to resolve [TreeNode.fileOffset]s to file URI, line,
  /// and column numbers, to be able to generate source mappings, in
  /// [setSourceMapFileOffset].
  ///
  /// Setting this `null` disables source mapping for the instructions being
  /// generated.
  ///
  /// This should be called before [setSourceMapFileOffset] as the file offset
  /// passed to that function is resolved using the [Source].
  ///
  /// Returns the old [Source], which can be used to restore the source mapping
  /// after visiting a sub-tree.
  Source? setSourceMapSource(Source? source) {
    final old = _sourceMapSource;
    _sourceMapSource = source;
    return old;
  }

  /// Update the source location of the AST nodes being compiled in the source
  /// map.
  ///
  /// When the offset is [TreeNode.noOffset], this disables mapping the
  /// generated instructions.
  ///
  /// Returns the old file offset, which can be used to restore the source
  /// mapping after vising a sub-tree.
  int setSourceMapFileOffset(int fileOffset) {
    if (!b.recordSourceMaps) {
      final old = _sourceMapFileOffset;
      _sourceMapFileOffset = fileOffset;
      return old;
    }
    if (fileOffset == TreeNode.noOffset) {
      b.stopSourceMapping();
      final old = _sourceMapFileOffset;
      _sourceMapFileOffset = fileOffset;
      return old;
    }
    final source = _sourceMapSource!;
    final fileUri = source.fileUri!;
    final location = source.getLocation(fileUri, fileOffset);
    final old = _sourceMapFileOffset;
    _sourceMapFileOffset = fileOffset;
    b.startSourceMapping(fileUri, location.line - 1, location.column - 1,
        enclosingMember.name.text);
    return old;
  }

  /// Calls [setSourceMapSource] and [setSourceMapFileOffset].
  (Source?, int) setSourceMapSourceAndFileOffset(
      Source? source, int fileOffset) {
    final oldSource = setSourceMapSource(source);
    final oldFileOffset = setSourceMapFileOffset(fileOffset);
    return (oldSource, oldFileOffset);
  }

  /// Generate code while preventing recursive inlining.
  @override
  void generate(w.InstructionsBuilder b, List<w.Local> paramLocals,
      w.Label? returnLabel) {
    this.b = b;
    this.paramLocals = paramLocals;
    this.returnLabel = returnLabel;

    translator.membersBeingGenerated.add(enclosingMember);
    generateInternal();
    translator.membersBeingGenerated.remove(enclosingMember);
  }

  // Generate the body.
  void generateInternal();

  void _setupLocalParameters(Member member, ParameterInfo paramInfo,
      int parameterOffset, int implicitParams,
      {bool isForwarder = false, bool canSafelyOmitImplicitChecks = false}) {
    final memberFunction = member.function!;

    final (
      :typeParameters,
      :typeParametersToTypeCheck,
      :positional,
      :positionalToTypeCheck,
      :named,
      :namedToTypeCheck
    ) = translator.getParametersToCheck(member);

    for (int i = 0; i < typeParameters.length; i++) {
      final typeParameter = typeParameters[i];
      typeLocals[typeParameter] = paramLocals[parameterOffset + i];
    }
    final mayNeedToCheckTypes = translator.needToCheckTypesFor(member);
    if (mayNeedToCheckTypes) {
      for (int i = 0; i < typeParametersToTypeCheck.length; i++) {
        final typeParameter = typeParametersToTypeCheck[i];
        if (translator.needToCheckTypeParameter(typeParameter)) {
          _generateTypeArgumentBoundCheck(typeParameter.name!,
              typeLocals[typeParameter]!, typeParameter.bound);
        }
      }
    }

    void setupParamLocal(
        DartType variableTypeToCheck,
        VariableDeclaration variable,
        int index,
        Constant? defaultValue,
        bool isRequired) {
      final localIndex = implicitParams + index;
      w.Local local = paramLocals[localIndex];
      final variableName = variable.name;
      if (variableName != null) {
        b.localNames[local.index] = variableName;
      }
      if (defaultValue == ParameterInfo.defaultValueSentinel) {
        // The default value for this parameter differs between implementations
        // within the same selector. This means that callers will pass the
        // default value sentinel to indicate that the parameter is not given.
        // The callee must check for the sentinel value and substitute the
        // actual default value.
        //
        // NOTE: The default sentinel is a dummy instance of the wasm type of
        // the parameter in the function signature. This type may be a super
        // type of the kind of arguments we actually see in practice.
        // (e.g. we may know that only nullable one byte strings can flow into
        // the argument, but the wasm type may be of object type). So we first
        // have to handle sentinel before we can downcast the value.
        b.local_get(local);
        translator.constants.instantiateConstant(
            b, ParameterInfo.defaultValueSentinel, local.type);
        b.ref_eq();
        b.if_();
        translateExpression(variable.initializer!, local.type);
        b.local_set(local);
        b.end();
      }
      if (!isForwarder) {
        // TFA may have inferred a very precise type for the incoming arguments,
        // but the wasm function parameter type may not reflect this (e.g. due
        // to upper-bounding in dispatch table row building)
        // => This means, we may need to do a downcast here.
        final incomingArgumentType =
            translator.translateTypeOfParameter(variable, isRequired);
        if (!local.type.isSubtypeOf(incomingArgumentType)) {
          final newLocal = addLocal(incomingArgumentType);
          b.local_get(local);
          translator.convertType(b, local.type, newLocal.type);
          b.local_set(newLocal);
          local = newLocal;
        }
      }
      if (mayNeedToCheckTypes) {
        if (translator.needToCheckParameter(variable,
            uncheckedEntry: canSafelyOmitImplicitChecks)) {
          final boxedType = variable.type.isPotentiallyNullable
              ? translator.topType
              : translator.topTypeNonNullable;
          w.Local operand = local;
          if (!operand.type.isSubtypeOf(boxedType)) {
            final boxedOperand = addLocal(boxedType);
            b.local_get(operand);
            translator.convertType(b, operand.type, boxedOperand.type);
            b.local_set(boxedOperand);
            operand = boxedOperand;
          }
          b.local_get(operand);
          _generateArgumentTypeCheck(
            variable.name!,
            operand.type as w.RefType,
            variableTypeToCheck,
          );
        }
      }
      if (!isForwarder && !variable.isFinal) {
        // We now have a precise local that can contain the values passed by
        // callers, but the body may assign less precise types to this variable,
        // so we may introduce another local variable that is less precise.
        // => Binaryen will simplify the above downcast and this upcast.
        final variableType = translator.translateTypeOfLocalVariable(variable);
        if (!variableType.isSubtypeOf(local.type)) {
          w.Local newLocal = addLocal(variableType);
          b.local_get(local);
          translator.convertType(b, local.type, newLocal.type);
          b.local_set(newLocal);
          local = newLocal;
        }
      }

      locals[variable] = local;
    }

    for (int i = 0; i < positional.length; i++) {
      final bool isRequired = i < memberFunction.requiredParameterCount;
      final typeToCheck = positionalToTypeCheck[i].type;
      setupParamLocal(
          typeToCheck, positional[i], i, paramInfo.positional[i], isRequired);
    }
    for (var param in named) {
      final typeToCheck = identical(named, namedToTypeCheck)
          ? param.type
          : namedToTypeCheck.singleWhere((n) => n.name == param.name).type;
      setupParamLocal(typeToCheck, param, paramInfo.nameIndex[param.name]!,
          paramInfo.named[param.name], param.isRequired);
    }

    // For all parameters whose Wasm type has been forced to `externref` due to
    // this function being an export, internalize and cast the parameter to the
    // canonical representation type for its Dart type.
    locals.forEach((parameter, local) {
      DartType parameterType = parameter.type;
      if (local.type == w.RefType.extern(nullable: true) &&
          !(parameterType is InterfaceType &&
              parameterType.classNode == translator.wasmExternRefClass)) {
        w.Local newLocal =
            addLocal(translateType(parameterType), name: parameter.name);
        b.local_get(local);
        translator.convertType(b, local.type, newLocal.type);
        b.local_set(newLocal);
        locals[parameter] = newLocal;
      }
    });
  }

  void setupParameters(Reference reference,
      {bool isForwarder = false, bool canSafelyOmitImplicitChecks = false}) {
    Member member = reference.asMember;
    ParameterInfo paramInfo = translator.paramInfoForDirectCall(reference);

    int parameterOffset = _initializeThis(reference);
    int implicitParams = parameterOffset + paramInfo.typeParamCount;

    _setupLocalParameters(member, paramInfo, parameterOffset, implicitParams,
        isForwarder: isForwarder,
        canSafelyOmitImplicitChecks: canSafelyOmitImplicitChecks);
  }

  void setupParametersForNormalEntry(Member member) {
    setupParameters(member.reference,
        canSafelyOmitImplicitChecks: !translator.needToCheckTypesFor(member));
  }

  void setupParametersForCheckedEntry(Member member) {
    assert(member.isInstanceMember);
    assert(translator.needToCheckTypesFor(member));
    setupParameters(member.checkedEntryReference,
        canSafelyOmitImplicitChecks: false);
  }

  void setupParametersForUncheckedEntry(Member member) {
    assert(member.isInstanceMember);
    assert(translator.needToCheckTypesFor(member));
    setupParameters(member.uncheckedEntryReference,
        canSafelyOmitImplicitChecks: true);
  }

  void setupContexts(Member member) {
    allocateContext(member.function!);
    captureParameters();
  }

  void _setupDefaultFieldValues(ClassInfo info) {
    fieldLocals.clear();

    for (Field field in info.cls!.fields) {
      if (field.isInstanceMember && field.initializer != null) {
        final source = field.enclosingComponent!.uriToSource[field.fileUri]!;
        final (oldSource, oldFileOffset) =
            setSourceMapSourceAndFileOffset(source, field.fileOffset);

        int fieldIndex = translator.fieldIndex[field]!;
        w.Local local = addLocal(info.struct.fields[fieldIndex].type.unpacked);

        translateExpression(
            field.initializer!, info.struct.fields[fieldIndex].type.unpacked);
        b.local_set(local);
        fieldLocals[field] = local;

        setSourceMapSourceAndFileOffset(oldSource, oldFileOffset);
      }
    }
  }

  List<w.Local> _getConstructorArgumentLocals(Reference target,
      [reverse = false]) {
    Constructor member = target.asConstructor;
    List<w.Local> constructorArgs = [];

    List<TypeParameter> typeParameters = member.enclosingClass.typeParameters;

    for (int i = 0; i < typeParameters.length; i++) {
      constructorArgs.add(typeLocals[typeParameters[i]]!);
    }

    List<VariableDeclaration> positional = member.function.positionalParameters;
    for (VariableDeclaration pos in positional) {
      constructorArgs.add(locals[pos]!);
    }

    Map<String, w.Local> namedArgs = {};
    List<VariableDeclaration> named = member.function.namedParameters;
    for (VariableDeclaration param in named) {
      namedArgs[param.name!] = locals[param]!;
    }

    final ParameterInfo paramInfo = translator.paramInfoForDirectCall(target);

    for (String name in paramInfo.names) {
      w.Local namedLocal = namedArgs[name]!;
      constructorArgs.add(namedLocal);
    }

    if (reverse) {
      return constructorArgs.reversed.toList();
    }

    return constructorArgs;
  }

  void setupLambdaParametersAndContexts(Lambda lambda) {
    FunctionNode functionNode = lambda.functionNode;
    _initializeContextLocals(functionNode);

    int paramIndex = 1;
    for (TypeParameter typeParam in functionNode.typeParameters) {
      typeLocals[typeParam] = paramLocals[paramIndex++];
    }
    for (VariableDeclaration param in functionNode.positionalParameters) {
      locals[param] = paramLocals[paramIndex++];
    }
    for (VariableDeclaration param in functionNode.namedParameters) {
      locals[param] = paramLocals[paramIndex++];
    }

    allocateContext(functionNode);
    captureParameters();
  }

  /// Initialize locals containing `this` in constructors and instance members.
  /// Returns the number of parameter locals taken up by the receiver parameter,
  /// i.e. the parameter offset for the first type parameter (or the first
  /// parameter if there are no type parameters).
  int _initializeThis(Reference reference) {
    Member member = reference.asMember;
    final hasThis =
        member.isInstanceMember || reference.isConstructorBodyReference;
    if (hasThis) {
      thisLocal = paramLocals[0];
      b.localNames[thisLocal!.index] = "this";
      final preciseThisType = translator.preciseThisFor(member);
      if (translator.needsConversion(thisLocal!.type, preciseThisType)) {
        preciseThisLocal = addLocal(preciseThisType, name: "preciseThis");
        b.local_get(thisLocal!);
        translator.convertType(b, thisLocal!.type, preciseThisType);
        b.local_set(preciseThisLocal!);
      } else {
        preciseThisLocal = thisLocal!;
      }
      return 1;
    }
    return 0;
  }

  /// Initialize locals pointing to every context in the context chain of a
  /// closure, plus the locals containing `this` if `this` is captured by the
  /// closure.
  void _initializeContextLocals(TreeNode node, {int contextParamIndex = 0}) {
    Context? context;

    if (node is Constructor) {
      // The context parameter is for the constructor context.
      context = closures.contexts[node];
    } else {
      assert(node is FunctionNode);
      // The context parameter is for the parent context.
      context = closures.contexts[node]?.parent;
    }

    if (context != null) {
      assert(!context.isEmpty);
      w.RefType contextType = w.RefType.def(context.struct, nullable: false);

      b.local_get(paramLocals[contextParamIndex]);
      b.ref_cast(contextType);

      while (true) {
        w.Local contextLocal = addLocal(contextType);
        context!.currentLocal = contextLocal;

        if (context.parent != null || context.containsThis) {
          b.local_tee(contextLocal);
        } else {
          b.local_set(contextLocal);
        }

        if (context.containsThis) {
          thisLocal = addLocal(
              context.struct.fields[context.thisFieldIndex].type.unpacked
                  .withNullability(false),
              name: "this");
          preciseThisLocal = thisLocal;

          b.struct_get(context.struct, context.thisFieldIndex);
          b.ref_as_non_null();
          b.local_set(thisLocal!);

          if (context.parent != null) {
            b.local_get(contextLocal);
          }
        }

        if (context.parent == null) break;

        b.struct_get(context.struct, context.parentFieldIndex);
        b.ref_as_non_null();
        context = context.parent!;
        contextType = w.RefType.def(context.struct, nullable: false);
      }
    }
  }

  void _implicitReturn() {
    if (outputs.isNotEmpty) {
      w.ValueType returnType = outputs.single;
      if (returnType is w.RefType && returnType.nullable) {
        // Dart body may have an implicit return null.
        b.ref_null(returnType.heapType.bottomType);
      } else {
        b.comment("Unreachable implicit return");
        b.unreachable();
      }
    }
  }

  void allocateContext(TreeNode node) {
    Context? context = closures.contexts[node];
    if (context == null || context.isEmpty) return;

    w.Local contextLocal =
        addLocal(w.RefType.def(context.struct, nullable: true));
    context.currentLocal = contextLocal;
    b.struct_new_default(context.struct);
    b.local_set(contextLocal);
    if (context.containsThis) {
      b.local_get(contextLocal);
      b.local_get(preciseThisLocal!);
      b.struct_set(context.struct, context.thisFieldIndex);
    }
    if (context.parent != null) {
      w.Local parentLocal = context.parent!.currentLocal;
      b.local_get(contextLocal);
      b.local_get(parentLocal);
      b.struct_set(context.struct, context.parentFieldIndex);
    }
  }

  void captureParameters() {
    locals.forEach((variable, local) {
      Capture? capture = closures.captures[variable];
      if (capture != null) {
        b.local_get(capture.context.currentLocal);
        b.local_get(local);
        translator.convertType(b, local.type, capture.type);
        b.struct_set(capture.context.struct, capture.fieldIndex);
      }
    });
    typeLocals.forEach((parameter, local) {
      Capture? capture = closures.captures[parameter];
      if (capture != null) {
        b.local_get(capture.context.currentLocal);
        b.local_get(local);
        translator.convertType(b, local.type, capture.type);
        b.struct_set(capture.context.struct, capture.fieldIndex);
      }
    });
  }

  /// Helper function to throw a Wasm ref downcast error.
  void throwWasmRefError(String expected) {
    _emitString(expected);
    call(translator.stackTraceCurrent.reference);
    call(translator.throwWasmRefError.reference);
    b.unreachable();
  }

  /// Generates code for an expression plus conversion code to convert the
  /// result to the expected type if needed. All expression code generation goes
  /// through this method.
  w.ValueType translateExpression(Expression node, w.ValueType expectedType) {
    var sourceUpdated = false;
    Source? oldSource;
    if (node is FileUriNode) {
      final source =
          node.enclosingComponent!.uriToSource[(node as FileUriNode).fileUri]!;
      oldSource = setSourceMapSource(source);
      sourceUpdated = true;
    }
    final oldFileOffset = setSourceMapFileOffset(node.fileOffset);
    try {
      w.ValueType resultType = node.accept1(this, expectedType);
      translator.convertType(b, resultType, expectedType);
      return expectedType;
    } catch (_) {
      _printLocation(node);
      rethrow;
    } finally {
      if (sourceUpdated) {
        setSourceMapSource(oldSource);
      }
      setSourceMapFileOffset(oldFileOffset);
    }
  }

  void translateStatement(Statement node) {
    final oldFileOffset = setSourceMapFileOffset(node.fileOffset);
    try {
      node.accept(this);
    } catch (_) {
      _printLocation(node);
      rethrow;
    } finally {
      setSourceMapFileOffset(oldFileOffset);
    }
  }

  void visitInitializer(Initializer node) {
    try {
      node.accept(this);
    } catch (_) {
      _printLocation(node);
      rethrow;
    }
  }

  void _printLocation(TreeNode node) {
    if (!exceptionLocationPrinted) {
      print("Exception in ${node.runtimeType} at ${node.location}");
      exceptionLocationPrinted = true;
    }
  }

  List<w.ValueType> call(Reference target) {
    return translator.callReference(target, b);
  }

  @override
  void visitInvalidInitializer(InvalidInitializer node) {}

  @override
  void visitAssertInitializer(AssertInitializer node) {
    translateStatement(node.statement);
  }

  @override
  void visitLocalInitializer(LocalInitializer node) {
    translateStatement(node.variable);
  }

  @override
  void visitFieldInitializer(FieldInitializer node) {
    Class cls = (node.parent as Constructor).enclosingClass;
    w.StructType struct = translator.classInfo[cls]!.struct;
    Field field = node.field;
    int fieldIndex = translator.fieldIndex[field]!;

    w.Local? local = fieldLocals[field];

    local ??= addLocal(struct.fields[fieldIndex].type.unpacked);

    translateExpression(node.value, struct.fields[fieldIndex].type.unpacked);
    b.local_set(local);
    fieldLocals[field] = local;
  }

  @override
  void visitRedirectingInitializer(RedirectingInitializer node) {
    Class cls = (node.parent as Constructor).enclosingClass;

    for (TypeParameter typeParam in cls.typeParameters) {
      types.makeType(
          this, TypeParameterType(typeParam, Nullability.nonNullable));
    }

    final targetMember = node.targetReference.asMember;
    final target = targetMember.initializerReference;
    _visitArguments(node.arguments, translator.signatureForDirectCall(target),
        translator.paramInfoForDirectCall(target), cls.typeParameters.length);

    b.comment("Direct call of '$targetMember Redirected Initializer'");
    call(target);
  }

  @override
  void visitSuperInitializer(SuperInitializer node) {
    Supertype? supertype =
        (node.parent as Constructor).enclosingClass.supertype;
    Supertype? supersupertype = node.target.enclosingClass.supertype;

    // Skip calls to the constructor for Object, as this is empty
    if (supersupertype != null) {
      for (DartType typeArg in supertype!.typeArguments) {
        types.makeType(this, typeArg);
      }

      final targetMember = node.targetReference.asMember;
      final target = targetMember.initializerReference;
      _visitArguments(
          node.arguments,
          translator.signatureForDirectCall(target),
          translator.paramInfoForDirectCall(target),
          supertype.typeArguments.length);

      b.comment("Direct call of '$targetMember Initializer'");
      call(target);
    }
  }

  @override
  void visitBlock(Block node) {
    for (Statement statement in node.statements) {
      translateStatement(statement);
    }
  }

  @override
  void visitLabeledStatement(LabeledStatement node) {
    w.Label label = b.block();
    breakFinalizers[node] = <w.Label>[label];
    translateStatement(node.body);
    breakFinalizers.remove(node);
    b.end();
  }

  @override
  void visitBreakStatement(BreakStatement node) {
    b.br(breakFinalizers[node.target]!.last);
  }

  @override
  void visitVariableDeclaration(VariableDeclaration node) {
    final w.ValueType type = translator.translateTypeOfLocalVariable(node);
    w.Local? local;
    Capture? capture = closures.captures[node];
    if (capture == null || !capture.written) {
      local = addLocal(type, name: node.name);
      locals[node] = local;
    }

    // Handle variable initialization. Nullable variables have an implicit
    // initializer.
    if (node.initializer != null ||
        node.type.nullability == Nullability.nullable) {
      Expression initializer =
          node.initializer ?? ConstantExpression(NullConstant());
      if (capture != null) {
        w.ValueType expectedType = capture.written ? capture.type : local!.type;
        b.local_get(capture.context.currentLocal);
        translateExpression(initializer, expectedType);
        if (!capture.written) {
          b.local_tee(local!);
        }
        b.struct_set(capture.context.struct, capture.fieldIndex);
      } else {
        translateExpression(initializer, local!.type);
        b.local_set(local);
      }
    } else if (local != null && !local.type.defaultable) {
      // Uninitialized variable
      translator
          .getDummyValuesCollectorForModule(b.module)
          .instantiateDummyValue(b, local.type);
      b.local_set(local);
    }
  }

  /// Initialize a variable [node] to an initial value which must be left on
  /// the stack by [pushInitialValue].
  ///
  /// This is similar to [visitVariableDeclaration] but it gives more control
  /// over how the variable is initialized.
  void initializeVariable(
      VariableDeclaration node, void Function() pushInitialValue) {
    final w.ValueType type = translator.translateTypeOfLocalVariable(node);
    w.Local? local;
    final Capture? capture = closures.captures[node];
    if (capture == null || !capture.written) {
      local = addLocal(type, name: node.name);
      locals[node] = local;
    }

    if (capture != null) {
      b.local_get(capture.context.currentLocal);
      pushInitialValue();
      if (!capture.written) {
        b.local_tee(local!);
      }
      b.struct_set(capture.context.struct, capture.fieldIndex);
    } else {
      pushInitialValue();
      b.local_set(local!);
    }
  }

  @override
  void visitEmptyStatement(EmptyStatement node) {}

  @override
  void visitAssertStatement(AssertStatement node) {
    if (options.enableAsserts) {
      w.Label assertBlock = b.block();
      translateExpression(node.condition, w.NumType.i32);
      b.br_if(assertBlock);

      Expression? message = node.message;
      if (message != null) {
        translateExpression(message, translator.topType);
      } else {
        b.ref_null(w.HeapType.none);
      }
      final Location? location = node.location;
      final w.RefType stringRefType = translator.stringTypeNullable;
      if (location != null) {
        translator.constants.instantiateConstant(
          b,
          StringConstant(location.file.toString()),
          stringRefType,
        );
        b.i64_const(location.line);
        b.i64_const(location.column);
        final String sourceString =
            node.enclosingComponent!.uriToSource[location.file]!.text;
        final String conditionString = sourceString.substring(
            node.conditionStartOffset, node.conditionEndOffset);
        translator.constants.instantiateConstant(
          b,
          StringConstant(conditionString),
          stringRefType,
        );
      } else {
        b.ref_null(stringRefType.heapType);
        b.i64_const(0);
        b.i64_const(0);
        b.ref_null(stringRefType.heapType);
      }

      call(translator.throwAssertionError.reference);

      b.unreachable();
      b.end();
    }
  }

  @override
  void visitAssertBlock(AssertBlock node) {
    if (!options.enableAsserts) return;

    for (Statement statement in node.statements) {
      translateStatement(statement);
    }
  }

  @override
  void visitTryCatch(TryCatch node) {
    // It is not valid Dart to have a try without a catch.
    assert(node.catches.isNotEmpty);

    final w.RefType exceptionType = translator.topTypeNonNullable;
    final w.RefType stackTraceType = translator.stackTraceType;

    final w.Label wrapperBlock = b.block();

    // Create a block target for each Dart `catch` block, to be able to share
    // code when generating a `catch` and `catch_all` for the same Dart `catch`
    // block, when the block can catch both Dart and JS exceptions.
    // The `end` for the Wasm `try` block works as the first exception handler
    // target.
    List<w.Label> catchBlockLabels = List.generate(node.catches.length - 1,
        (i) => b.block([], [exceptionType, stackTraceType]),
        growable: true);

    w.Label try_ = b.try_([], [exceptionType, stackTraceType]);
    catchBlockLabels.add(try_);

    catchBlockLabels = catchBlockLabels.reversed.toList();

    translateStatement(node.body);
    b.br(wrapperBlock);

    // Stash the original exception in a local so we can push it back onto the
    // stack after each type test. Also, store the stack trace in a local.
    w.Local thrownException = addLocal(exceptionType);
    w.Local thrownStackTrace = addLocal(stackTraceType);

    tryBlockLocals.add(
        (exceptionLocal: thrownException, stackTraceLocal: thrownStackTrace));

    void emitCatchBlock(
        w.Label catchBlockTarget, Catch catch_, bool emitGuard) {
      // For each catch node:
      //   1) Create a block for the catch.
      //   2) Push the caught exception onto the stack.
      //   3) Add a type test based on the guard of the catch.
      //   4) If the test fails, we jump to the next catch. Otherwise, we
      //      jump to the block for the body of the catch.
      w.Label catchBlock = b.block();
      DartType guard = catch_.guard;

      // Only emit the type test if the guard is not [Object].
      if (emitGuard) {
        b.local_get(thrownException);
        types.emitIsTest(this, guard,
            translator.coreTypes.objectNonNullableRawType, catch_.location);
        b.i32_eqz();
        b.br_if(catchBlock);
      }

      b.local_get(thrownException);
      b.local_get(thrownStackTrace);
      b.br(catchBlockTarget);

      b.end(); // end catchBlock.
    }

    // Insert a catch instruction which will catch any thrown Dart
    // exceptions.
    b.catch_legacy(translator.getExceptionTag(b.module));

    b.local_set(thrownStackTrace);
    b.local_set(thrownException);
    for (int catchBlockIndex = 0;
        catchBlockIndex < node.catches.length;
        catchBlockIndex += 1) {
      final catch_ = node.catches[catchBlockIndex];
      // Only insert type checks if the guard is not `Object`
      final bool shouldEmitGuard =
          catch_.guard != translator.coreTypes.objectNonNullableRawType;
      emitCatchBlock(
          catchBlockLabels[catchBlockIndex], catch_, shouldEmitGuard);
      if (!shouldEmitGuard) {
        // If we didn't emit a guard, we won't ever fall through to the
        // following catch blocks.
        break;
      }
    }

    // Rethrow if all the catch blocks fall through
    b.rethrow_(try_);

    // If we have a catches that are generic enough to catch a JavaScript
    // error, we need to put that into a catch_all block.
    if (node.catches
        .any((c) => guardCanMatchJSException(translator, c.guard))) {
      // This catches any objects that aren't dart exceptions, such as
      // JavaScript exceptions or objects.
      b.catch_all_legacy();

      // We can't inspect the thrown object in a catch_all and get a stack
      // trace, so we just attach the current stack trace.
      call(translator.stackTraceCurrent.reference);
      b.local_set(thrownStackTrace);

      // We create a generic JavaScript error in this case.
      call(translator.javaScriptErrorFactory.reference);
      b.local_set(thrownException);

      for (int catchBlockIndex = 0;
          catchBlockIndex < node.catches.length;
          catchBlockIndex += 1) {
        final catch_ = node.catches[catchBlockIndex];
        if (!guardCanMatchJSException(translator, catch_.guard)) {
          continue;
        }
        // Type guards based on a type parameter are special, in that we cannot
        // statically determine whether a JavaScript error will always satisfy
        // the guard, so we should emit the type checking code for it. All
        // other guards will always match a JavaScript error, however, so no
        // need to emit type checks for those.
        final bool shouldEmitGuard = catch_.guard is TypeParameterType;
        emitCatchBlock(
            catchBlockLabels[catchBlockIndex], catch_, shouldEmitGuard);
        if (!shouldEmitGuard) {
          // If we didn't emit a guard, we won't ever fall through to the
          // following catch blocks.
          break;
        }
      }

      // Rethrow if the catch block falls through
      b.rethrow_(try_);
    }

    for (Catch catch_ in node.catches) {
      b.end();
      b.local_set(thrownStackTrace);
      b.local_set(thrownException);

      final VariableDeclaration? exceptionDeclaration = catch_.exception;
      if (exceptionDeclaration != null) {
        initializeVariable(exceptionDeclaration, () {
          b.local_get(thrownException);
          // Type test passed, downcast the exception to the expected type.
          translator.convertType(
            b,
            thrownException.type,
            translator.translateType(exceptionDeclaration.type),
          );
        });
      }

      final VariableDeclaration? stackTraceDeclaration = catch_.stackTrace;
      if (stackTraceDeclaration != null) {
        initializeVariable(
            stackTraceDeclaration, () => b.local_get(thrownStackTrace));
      }

      translateStatement(catch_.body);
      b.br(wrapperBlock);
    }

    tryBlockLocals.removeLast();
    b.end(); // end tryWrapper
  }

  @override
  void visitTryFinally(TryFinally node) {
    // We lower a [TryFinally] to a number of nested blocks, depending on how
    // many different code paths we have that run the finally block.
    //
    // We emit the finalizer once in a catch, to handle the case where the try
    // throws. Once outside of the catch, to handle the case where the try does
    // not throw. If there is a return within the try block, then we emit the
    // finalizer one more time along with logic to continue walking up the
    // stack.
    //
    // A `break L` can run more than one finalizer, and each of those
    // finalizers will need to be run in a different `try` block. So for each
    // wrapping label we generate a block to run the finalizer on `break` and
    // then branch to the right Wasm block to either run the next finalizer or
    // break.

    // The block for the try-finally statement. Used as `br` target in normal
    // execution after the finalizer (no throws, returns, or breaks).
    w.Label tryFinallyBlock = b.block();

    // Create one block for each wrapping label.
    for (final labelBlocks in breakFinalizers.values.toList().reversed) {
      labelBlocks.add(b.block());
    }

    // Continuation of this block runs the finalizer and returns (or jumps to
    // the next finalizer block). Used as `br` target on `return`.
    w.Label returnFinalizerBlock = b.block();
    returnFinalizers.add(TryBlockFinalizer(returnFinalizerBlock));

    w.Label tryBlock = b.try_();
    translateStatement(node.body);

    final bool mustHandleReturn =
        returnFinalizers.removeLast().mustHandleReturn;

    // `break` statements in the current finalizer and the rest will not run
    // the current finalizer, update the `break` targets.
    final removedBreakTargets = <LabeledStatement, w.Label>{};
    for (final breakFinalizerEntry in breakFinalizers.entries) {
      removedBreakTargets[breakFinalizerEntry.key] =
          breakFinalizerEntry.value.removeLast();
    }

    // Handle Dart exceptions.
    b.catch_legacy(translator.getExceptionTag(b.module));
    translateStatement(node.finalizer);
    b.rethrow_(tryBlock);

    // Handle JS exceptions.
    b.catch_all_legacy();
    translateStatement(node.finalizer);
    b.rethrow_(tryBlock);

    b.end(); // tryBlock

    // Run finalizer on normal execution (no breaks, throws, or returns).
    translateStatement(node.finalizer);
    b.br(tryFinallyBlock);
    b.end(); // returnFinalizerBlock

    // Run the finalizer on `return`.
    if (mustHandleReturn) {
      translateStatement(node.finalizer);
      if (returnFinalizers.isNotEmpty) {
        b.br(returnFinalizers.last.label);
      } else {
        if (returnValueLocal != null) {
          b.local_get(returnValueLocal!);
          translator.convertType(b, returnValueLocal!.type, returnType);
        }
        _returnFromFunction();
      }
    }

    // Generate finalizers for `break`s in the `try` block.
    for (final removedBreakTargetEntry in removedBreakTargets.entries) {
      b.end();
      translateStatement(node.finalizer);
      b.br(breakFinalizers[removedBreakTargetEntry.key]!.last);
    }

    b.end(); // tryFinallyBlock
  }

  @override
  void visitExpressionStatement(ExpressionStatement node) {
    translateExpression(node.expression, voidMarker);
  }

  bool _hasLogicalOperator(Expression condition) {
    while (condition is Not) {
      condition = condition.operand;
    }
    return condition is LogicalExpression;
  }

  void branchIf(Expression? condition, w.Label target,
      {required bool negated}) {
    if (condition == null) {
      if (!negated) b.br(target);
      return;
    }
    while (condition is Not) {
      negated = !negated;
      condition = condition.operand;
    }
    if (condition is LogicalExpression) {
      bool isConjunctive =
          (condition.operatorEnum == LogicalExpressionOperator.AND) ^ negated;
      if (isConjunctive) {
        w.Label conditionBlock = b.block();
        branchIf(condition.left, conditionBlock, negated: !negated);
        branchIf(condition.right, target, negated: negated);
        b.end();
      } else {
        branchIf(condition.left, target, negated: negated);
        branchIf(condition.right, target, negated: negated);
      }
    } else {
      translateExpression(condition!, w.NumType.i32);
      if (negated) {
        b.i32_eqz();
      }
      b.br_if(target);
    }
  }

  void _conditional(Expression condition, void Function() then,
      void Function()? otherwise, List<w.ValueType> result) {
    if (!_hasLogicalOperator(condition)) {
      // Simple condition
      translateExpression(condition, w.NumType.i32);
      b.if_(const [], result);
      then();
      if (otherwise != null) {
        b.else_();
        otherwise();
      }
      b.end();
    } else {
      // Complex condition
      w.Label ifBlock = b.block(const [], result);
      if (otherwise != null) {
        w.Label elseBlock = b.block();
        branchIf(condition, elseBlock, negated: true);
        then();
        b.br(ifBlock);
        b.end();
        otherwise();
      } else {
        branchIf(condition, ifBlock, negated: true);
        then();
      }
      b.end();
    }
  }

  @override
  void visitIfStatement(IfStatement node) {
    _conditional(
        node.condition,
        () => translateStatement(node.then),
        node.otherwise != null
            ? () => translateStatement(node.otherwise!)
            : null,
        const []);
  }

  @override
  void visitDoStatement(DoStatement node) {
    w.Label loop = b.loop();
    allocateContext(node);
    translateStatement(node.body);
    branchIf(node.condition, loop, negated: false);
    b.end();
  }

  @override
  void visitWhileStatement(WhileStatement node) {
    w.Label block = b.block();
    w.Label loop = b.loop();
    allocateContext(node);
    branchIf(node.condition, block, negated: true);
    translateStatement(node.body);
    b.br(loop);
    b.end();
    b.end();
  }

  @override
  void visitForStatement(ForStatement node) {
    allocateContext(node);
    for (VariableDeclaration variable in node.variables) {
      translateStatement(variable);
    }
    w.Label block = b.block();
    w.Label loop = b.loop();
    branchIf(node.condition, block, negated: true);
    translateStatement(node.body);

    emitForStatementUpdate(node);

    b.br(loop);
    b.end();
    b.end();
  }

  void emitForStatementUpdate(ForStatement node) {
    Context? context = closures.contexts[node];
    if (context != null && !context.isEmpty) {
      // Create a new context for each iteration of the loop.
      w.Local oldContext = context.currentLocal;
      allocateContext(node);
      w.Local newContext = context.currentLocal;

      // Copy the values of captured loop variables to the new context.
      for (VariableDeclaration variable in node.variables) {
        Capture? capture = closures.captures[variable];
        if (capture != null) {
          assert(capture.context == context);
          b.local_get(newContext);
          b.local_get(oldContext);
          b.struct_get(context.struct, capture.fieldIndex);
          b.struct_set(context.struct, capture.fieldIndex);
        }
      }

      // Update the context local to point to the new context.
      b.local_get(newContext);
      b.local_set(oldContext);
    }

    for (Expression update in node.updates) {
      translateExpression(update, voidMarker);
    }
  }

  @override
  void visitForInStatement(ForInStatement node) {
    throw "ForInStatement should have been desugared: $node";
  }

  /// Handle the return from this function, either by jumping to [returnLabel]
  /// in the case this function was inlined or just inserting a return
  /// instruction.
  void _returnFromFunction() {
    if (returnLabel != null) {
      b.br(returnLabel!);
    } else {
      b.return_();
    }
  }

  @override
  void visitReturnStatement(ReturnStatement node) {
    Expression? expression = node.expression;
    if (expression != null) {
      translateExpression(expression, returnType);
    } else {
      translator.convertType(b, voidMarker, returnType);
    }

    // If we are wrapped in a [TryFinally] node then we have to run finalizers
    // as the stack unwinds. When we get to the top of the finalizer stack, we
    // will handle the return using [returnValueLocal] if this function returns
    // a value.
    if (returnFinalizers.isNotEmpty) {
      for (TryBlockFinalizer finalizer in returnFinalizers) {
        finalizer.mustHandleReturn = true;
      }
      if (returnType != voidMarker) {
        // Since the flow of the return value through the returnValueLocal
        // crosses control-flow constructs, the local needs to always have a
        // defaultable type in order for the Wasm code to validate.
        returnValueLocal ??=
            addLocal(returnType.withNullability(true), name: "returnValue");
        b.local_set(returnValueLocal!);
      }
      b.br(returnFinalizers.last.label);
    } else {
      _returnFromFunction();
    }
  }

  @override
  void visitSwitchStatement(SwitchStatement node) {
    // If we have an empty switch, just evaluate the expression for any
    // potential side effects. In this case, the return type does not matter.
    if (node.cases.isEmpty) {
      translateExpression(node.expression, voidMarker);
      return;
    }

    final switchInfo = SwitchInfo(this, node);

    bool isNullable = dartTypeOf(node.expression).isPotentiallyNullable;

    // When the type is nullable we use two variables: one for the nullable
    // value, one after the null check, with non-nullable type.
    w.Local switchValueNonNullableLocal = addLocal(switchInfo.nonNullableType);
    w.Local? switchValueNullableLocal =
        isNullable ? addLocal(switchInfo.nullableType) : null;

    // Initialize switch value local
    translateExpression(node.expression,
        isNullable ? switchInfo.nullableType : switchInfo.nonNullableType);
    b.local_set(
        isNullable ? switchValueNullableLocal! : switchValueNonNullableLocal);

    // Special cases
    SwitchCase? defaultCase = switchInfo.defaultCase;
    SwitchCase? nullCase = switchInfo.nullCase;

    // Create `loop` for backward jumps
    w.Label loopLabel = b.loop();

    // Set `switchValueLocal` for backward jumps
    w.Local switchValueLocal =
        isNullable ? switchValueNullableLocal! : switchValueNonNullableLocal;

    // Add backward jump info
    switchBackwardJumpInfos[node] =
        SwitchBackwardJumpInfo(switchValueLocal, loopLabel);

    // Set up blocks, in reverse order of cases so they end in forward order
    w.Label doneLabel = b.block();
    for (SwitchCase c in node.cases.reversed) {
      switchLabels[c] = b.block();
    }

    // Compute value and handle null
    if (isNullable) {
      w.Label nullLabel = nullCase != null
          ? switchLabels[nullCase]!
          : defaultCase != null
              ? switchLabels[defaultCase]!
              : doneLabel;
      b.local_get(switchValueNullableLocal!);
      b.br_on_null(nullLabel);
      translator.convertType(b, switchInfo.nullableType.withNullability(false),
          switchInfo.nonNullableType);
      b.local_set(switchValueNonNullableLocal);
    }

    final dynamicTypeGuard = switchInfo.dynamicTypeGuard;
    if (dynamicTypeGuard != null) {
      final success = b.block(const [], [translator.topTypeNonNullable]);
      dynamicTypeGuard(switchValueNonNullableLocal, success);
      b.br(switchLabels[defaultCase] ?? doneLabel);
      b.end();
    }

    final brTable = switchInfo.brTable;
    if (brTable != null) {
      // Map each entry in the range to the appropriate jump table entry.
      final indexBlocks = <w.Label>[];
      final defaultLabel =
          defaultCase != null ? switchLabels[defaultCase]! : doneLabel;
      for (int i = brTable.minValue; i <= brTable.maxValue; ++i) {
        final c = brTable.caseMap[i];
        indexBlocks.add(c == null ? defaultLabel : switchLabels[c]!);
      }

      brTable.emitBrTableExpr(b, switchValueNonNullableLocal);

      b.br_table(indexBlocks, defaultLabel);
    } else {
      // Compare against all case values
      for (SwitchCase c in node.cases) {
        for (Expression exp in c.expressions) {
          if (exp is NullLiteral ||
              exp is ConstantExpression && exp.constant is NullConstant) {
            // Null already checked, skip
          } else {
            switchInfo.compare(
              switchValueNonNullableLocal,
              () => translateExpression(exp, switchInfo.nonNullableType),
            );
            b.br_if(switchLabels[c]!);
          }
        }
      }

      // No explicit cases matched
      if (node.isExplicitlyExhaustive) {
        b.unreachable();
      } else {
        w.Label defaultLabel =
            defaultCase != null ? switchLabels[defaultCase]! : doneLabel;
        b.br(defaultLabel);
      }
    }

    // Emit case bodies
    for (SwitchCase c in node.cases) {
      b.end();
      // Remove backward jump target from forward jump labels
      switchLabels.remove(c);

      // Create a `loop` in default case to allow backward jumps to it
      if (c.isDefault) {
        switchBackwardJumpInfos[node]!.defaultLoopLabel = b.loop();
      }

      translateStatement(c.body);

      if (c.isDefault) {
        b.end(); // defaultLoopLabel
      }

      b.br(doneLabel);
    }
    b.end(); // doneLabel
    b.end(); // loopLabel

    // Remove backward jump info
    final removed = switchBackwardJumpInfos.remove(node);
    assert(removed != null);
  }

  @override
  void visitContinueSwitchStatement(ContinueSwitchStatement node) {
    w.Label? label = switchLabels[node.target];
    if (label != null) {
      b.br(label);
    } else {
      // Backward jump. Find the case literal in jump target, set the switched
      // values to the jump target's value, and loop.
      final SwitchCase targetSwitchCase = node.target;
      final SwitchStatement targetSwitch =
          targetSwitchCase.parent! as SwitchStatement;
      final SwitchBackwardJumpInfo targetInfo =
          switchBackwardJumpInfos[targetSwitch]!;
      if (targetSwitchCase.expressions.isEmpty) {
        // Default case
        assert(targetSwitchCase.isDefault);
        b.br(targetInfo.defaultLoopLabel!);
        return;
      }
      final Expression targetValue =
          targetSwitchCase.expressions[0]; // pick any of the values
      translateExpression(targetValue, targetInfo.switchValueLocal.type);
      b.local_set(targetInfo.switchValueLocal);
      b.br(targetInfo.loopLabel);
    }
  }

  @override
  void visitYieldStatement(YieldStatement node) {
    unimplemented(node, node.runtimeType, const []);
  }

  @override
  w.ValueType visitAwaitExpression(
      AwaitExpression node, w.ValueType expectedType) {
    throw 'Await expression in code generator: $node (${node.location})';
  }

  @override
  w.ValueType visitBlockExpression(
      BlockExpression node, w.ValueType expectedType) {
    translateStatement(node.body);
    return translateExpression(node.value, expectedType);
  }

  @override
  w.ValueType visitLet(Let node, w.ValueType expectedType) {
    translateStatement(node.variable);
    return translateExpression(node.body, expectedType);
  }

  @override
  w.ValueType visitThisExpression(
      ThisExpression node, w.ValueType expectedType) {
    return visitThis(expectedType);
  }

  w.ValueType visitThis(w.ValueType expectedType) {
    w.ValueType thisType = thisLocal!.type;
    w.ValueType preciseThisType = preciseThisLocal!.type;
    assert(!thisType.nullable);
    assert(!preciseThisType.nullable);
    if (thisType.isSubtypeOf(expectedType)) {
      b.local_get(thisLocal!);
      return thisType;
    }
    if (preciseThisType.isSubtypeOf(expectedType)) {
      b.local_get(preciseThisLocal!);
      return preciseThisType;
    }
    // A user of `this` may have more precise type information, in which case
    // we downcast it here.
    b.local_get(thisLocal!);
    translator.convertType(b, thisType, expectedType);
    return expectedType;
  }

  @override
  w.ValueType visitConstructorInvocation(
      ConstructorInvocation node, w.ValueType expectedType) {
    w.ValueType? intrinsicResult =
        intrinsifier.generateConstructorIntrinsic(node);
    if (intrinsicResult != null) return intrinsicResult;

    ClassInfo info = translator.classInfo[node.target.enclosingClass]!;
    translator.functions.recordClassAllocation(info.classId);

    final target = node.targetReference;
    _visitArguments(node.arguments, translator.signatureForDirectCall(target),
        translator.paramInfoForDirectCall(target), 0);

    return call(target).single;
  }

  @override
  w.ValueType visitStaticInvocation(
      StaticInvocation node, w.ValueType expectedType) {
    w.ValueType? intrinsicResult = intrinsifier.generateStaticIntrinsic(node);
    if (intrinsicResult != null) return intrinsicResult;

    final target = node.targetReference;
    _visitArguments(node.arguments, translator.signatureForDirectCall(target),
        translator.paramInfoForDirectCall(target), 0);
    return translator.outputOrVoid(call(target));
  }

  Member _lookupSuperTarget(Member interfaceTarget, {required bool setter}) {
    final staticTarget = translator.hierarchy.getDispatchTarget(
        enclosingMember.enclosingClass!.superclass!, interfaceTarget.name,
        setter: setter);
    if (staticTarget != null) return staticTarget;

    // During dynamic module compilation a mixin might include a super call to
    // an abstract class with no implementations yet.
    assert(translator.dynamicModuleSupportEnabled);
    return interfaceTarget;
  }

  @override
  w.ValueType visitSuperMethodInvocation(
      SuperMethodInvocation node, w.ValueType expectedType) {
    Reference target = translator.getFunctionEntry(
        _lookupSuperTarget(node.interfaceTarget, setter: false).reference,
        uncheckedEntry: true);
    w.FunctionType targetFunctionType =
        translator.signatureForDirectCall(target);
    final w.ValueType receiverType = translator.preciseThisFor(target.asMember);

    // When calling `==` and the argument is potentially nullable, check if the
    // argument is `null`.
    if (node.name.text == '==') {
      assert(node.arguments.positional.length == 1);
      assert(node.arguments.named.isEmpty);
      final argument = node.arguments.positional[0];
      if (dartTypeOf(argument).isPotentiallyNullable) {
        w.Label resultBlock = b.block(const [], const [w.NumType.i32]);

        w.ValueType argumentType = targetFunctionType.inputs[1];
        // `==` arguments are non-nullable.
        assert(argumentType.nullable == false);

        final argumentNullBlock = b.block(const [], const []);

        visitThis(receiverType);
        translateExpression(argument, argumentType.withNullability(true));
        b.br_on_null(argumentNullBlock);

        final resultType = translator.outputOrVoid(call(target));
        // `super ==` should return bool.
        assert(resultType == w.NumType.i32);
        b.br(resultBlock);

        b.end(); // argumentNullBlock

        b.i32_const(0); // false
        b.br(resultBlock);

        b.end(); // resultBlock
        return w.NumType.i32;
      }
    }

    visitThis(receiverType);
    _visitArguments(node.arguments, translator.signatureForDirectCall(target),
        translator.paramInfoForDirectCall(target), 1);
    return translator.outputOrVoid(call(target));
  }

  @override
  w.ValueType visitInstanceInvocation(
      InstanceInvocation node, w.ValueType expectedType) {
    w.ValueType? intrinsicResult = intrinsifier.generateInstanceIntrinsic(node);
    if (intrinsicResult != null) return intrinsicResult;

    final useUncheckedEntry =
        translator.canUseUncheckedEntry(node.receiver, node);

    w.ValueType callWithNullCheck(
        Procedure target, void Function(w.ValueType) onNull) {
      late w.Label done;
      final w.ValueType resultType =
          _virtualCall(node, target, _VirtualCallKind.Call, (signature) {
        done = b.block(const [], signature.outputs);
        final w.Label nullReceiver = b.block();
        translateExpression(node.receiver, translator.topType);
        b.br_on_null(nullReceiver);
      }, (w.FunctionType signature, ParameterInfo paramInfo) {
        _visitArguments(node.arguments, signature, paramInfo, 1);
      }, useUncheckedEntry: useUncheckedEntry);
      b.br(done);
      b.end(); // end nullReceiver
      onNull(resultType);
      b.end();
      return resultType;
    }

    final Procedure target = node.interfaceTarget;
    if (node.kind == InstanceAccessKind.Object) {
      switch (target.name.text) {
        case "toString":
          return callWithNullCheck(
              target,
              (resultType) =>
                  translateExpression(StringLiteral("null"), resultType));
        case "noSuchMethod":
          return callWithNullCheck(target, (resultType) {
            final target = node.interfaceTargetReference;
            final signature = translator.signatureForDirectCall(target);
            final paramInfo = translator.paramInfoForDirectCall(target);

            // Object? receiver
            b.ref_null(translator.topType.heapType);
            // Invocation invocation
            _visitArguments(node.arguments, signature, paramInfo, 1);
            call(translator.noSuchMethodErrorThrowWithInvocation.reference);
          });
        default:
          unimplemented(node, "Nullable invocation of ${target.name.text}",
              [if (expectedType != voidMarker) expectedType]);
          return expectedType;
      }
    }

    Member? singleTarget = translator.singleTarget(node);

    // Custom devirtualization because TFA doesn't correctly devirtualize index
    // accesses on constant lists (see https://dartbug.com/60313)
    if (singleTarget == null &&
        target.kind == ProcedureKind.Operator &&
        target.name.text == '[]') {
      final receiver = node.receiver;
      if (receiver is ConstantExpression && receiver.constant is ListConstant) {
        singleTarget = translator.listBaseIndexOperator;
      }
    }

    if (singleTarget != null) {
      final target = translator.getFunctionEntry(singleTarget.reference,
          uncheckedEntry: useUncheckedEntry);
      final signature = translator.signatureForDirectCall(target);
      final paramInfo = translator.paramInfoForDirectCall(target);
      translateExpression(node.receiver, signature.inputs.first);
      _visitArguments(node.arguments, signature, paramInfo, 1);

      return translator.outputOrVoid(call(target));
    }
    return _virtualCall(
        node,
        target,
        _VirtualCallKind.Call,
        (signature) =>
            translateExpression(node.receiver, signature.inputs.first),
        (w.FunctionType signature, ParameterInfo paramInfo) {
      _visitArguments(node.arguments, signature, paramInfo, 1);
    }, useUncheckedEntry: useUncheckedEntry);
  }

  @override
  w.ValueType visitDynamicInvocation(
      DynamicInvocation node, w.ValueType expectedType) {
    // Call dynamic invocation forwarder
    final receiver = node.receiver;
    final typeArguments = node.arguments.types;
    final positionalArguments = node.arguments.positional;
    final namedArguments = node.arguments.named;
    final memberName = node.name;
    final forwarder = translator
        .getDynamicForwardersForModule(b.module)
        .getDynamicInvocationForwarder(memberName);

    // Evaluate receiver
    translateExpression(receiver, translator.topType);
    final nullableReceiverLocal = addLocal(translator.topType);
    b.local_set(nullableReceiverLocal);

    // Evaluate type arguments.
    final typeArgsLocal = addLocal(
        makeArray(translator.typeArrayType, typeArguments.length,
            (elementType, elementIdx) {
      translator.types.makeType(this, typeArguments[elementIdx]);
    }));
    b.local_set(typeArgsLocal);

    // Evaluate positional arguments
    final positionalArgsLocal = addLocal(makeArray(
        translator.nullableObjectArrayType, positionalArguments.length,
        (elementType, elementIdx) {
      translateExpression(positionalArguments[elementIdx], elementType);
    }));
    b.local_set(positionalArgsLocal);

    // Evaluate named arguments. The arguments need to be evaluated in the
    // order they appear in the AST, but need to be sorted based on names in
    // the argument list passed to the dynamic forwarder. Create a local for
    // each argument to allow adding values to the list in expected order.
    final List<MapEntry<String, w.Local>> namedArgumentLocals = [];
    for (final namedArgument in namedArguments) {
      translateExpression(namedArgument.value, translator.topType);
      final argumentLocal = addLocal(translator.topType);
      b.local_set(argumentLocal);
      namedArgumentLocals.add(MapEntry(namedArgument.name, argumentLocal));
    }
    namedArgumentLocals.sort((e1, e2) => e1.key.compareTo(e2.key));

    // Create named argument array
    final namedArgsLocal = addLocal(
        makeArray(translator.nullableObjectArrayType, namedArguments.length * 2,
            (elementType, elementIdx) {
      if (elementIdx % 2 == 0) {
        final name = namedArgumentLocals[elementIdx ~/ 2].key;
        final w.ValueType symbolValueType =
            translator.classInfo[translator.symbolClass]!.nonNullableType;
        translator.constants.instantiateConstant(b,
            translator.symbols.symbolForNamedParameter(name), symbolValueType);
      } else {
        final local = namedArgumentLocals[elementIdx ~/ 2].value;
        b.local_get(local);
      }
    }));
    b.local_set(namedArgsLocal);

    final nullBlock = b.block([], [translator.topTypeNonNullable]);
    b.local_get(nullableReceiverLocal);
    b.br_on_non_null(nullBlock);
    // Throw `NoSuchMethodError`. Normally this needs to happen via instance
    // invocation of `noSuchMethod` (done in [_callNoSuchMethod]), but we don't
    // have a `Null` class in dart2wasm so we throw directly.
    b.local_get(nullableReceiverLocal);
    createInvocationObject(translator, b, memberName, typeArgsLocal,
        positionalArgsLocal, namedArgsLocal);

    call(translator.noSuchMethodErrorThrowWithInvocation.reference);
    b.unreachable();
    b.end(); // nullBlock

    b.local_get(typeArgsLocal);
    b.local_get(positionalArgsLocal);
    b.local_get(namedArgsLocal);
    translator.callFunction(forwarder.function, b);

    return translator.topType;
  }

  @override
  w.ValueType visitEqualsCall(EqualsCall node, w.ValueType expectedType) {
    w.ValueType? intrinsicResult = intrinsifier.generateEqualsIntrinsic(node);
    if (intrinsicResult != null) return intrinsicResult;

    final leftType = translator.translateType(dartTypeOf(node.left));
    Member? singleTarget = translator.singleTarget(node);
    if (singleTarget == translator.coreTypes.objectEquals ||
        // If leftType is not a Dart type (or builtin value type) then use
        // reference equality (e.g. the vtable type is not a subtype of
        // topType).
        (leftType is w.RefType && !leftType.isSubtypeOf(translator.topType))) {
      // Plain reference comparison
      translateExpression(node.left, w.RefType.eq(nullable: true));
      translateExpression(node.right, w.RefType.eq(nullable: true));
      b.ref_eq();
    } else {
      // Check operands for null, then call implementation
      bool leftNullable = dartTypeOf(node.left).isPotentiallyNullable;
      bool rightNullable = dartTypeOf(node.right).isPotentiallyNullable;
      w.RefType leftType = translator.topType.withNullability(leftNullable);
      w.RefType rightType = translator.topType.withNullability(rightNullable);
      w.Local leftLocal = addLocal(leftType);
      w.Local rightLocal = addLocal(rightType);
      w.Label? operandNull;
      w.Label? done;
      if (leftNullable || rightNullable) {
        done = b.block(const [], const [w.NumType.i32]);
        operandNull = b.block();
      }
      translateExpression(node.left, leftLocal.type);
      b.local_set(leftLocal);
      translateExpression(node.right, rightLocal.type);
      if (rightNullable) {
        b.local_tee(rightLocal);
        b.br_on_null(operandNull!);
        b.drop();
      } else {
        b.local_set(rightLocal);
      }

      void left([_]) {
        b.local_get(leftLocal);
        if (leftNullable) {
          b.br_on_null(operandNull!);
        }
      }

      void right([_, __]) {
        b.local_get(rightLocal);
        if (rightNullable) {
          b.ref_as_non_null();
        }
      }

      final useUncheckedEntry =
          translator.canUseUncheckedEntry(node.left, node);
      if (singleTarget != null) {
        left();
        right();
        call(translator.getFunctionEntry(singleTarget.reference,
            uncheckedEntry: useUncheckedEntry));
      } else {
        _virtualCall(
          node,
          node.interfaceTarget,
          _VirtualCallKind.Call,
          left,
          right,
          useUncheckedEntry: useUncheckedEntry,
        );
      }
      if (leftNullable || rightNullable) {
        b.br(done!);
        b.end(); // operandNull
        if (leftNullable && rightNullable) {
          // Both sides nullable - compare references
          b.local_get(leftLocal);
          b.local_get(rightLocal);
          b.ref_eq();
        } else {
          // Only one side nullable - not equal if one is null
          b.i32_const(0);
        }
        b.end(); // done
      }
    }
    return w.NumType.i32;
  }

  @override
  w.ValueType visitEqualsNull(EqualsNull node, w.ValueType expectedType) {
    translateExpression(node.expression, const w.RefType.any(nullable: true));
    b.ref_is_null();
    return w.NumType.i32;
  }

  w.ValueType _virtualCall(
      TreeNode node,
      Member interfaceTarget,
      _VirtualCallKind kind,
      void Function(w.FunctionType signature) pushReceiver,
      void Function(w.FunctionType signature, ParameterInfo) pushArguments,
      {required bool useUncheckedEntry}) {
    assert(kind != _VirtualCallKind.Get || !useUncheckedEntry);
    final reference = interfaceTarget.referenceAs(
        getter: kind.isGetter, setter: kind.isSetter);
    final dispatchTable = translator.dispatchTableForTarget(reference);
    SelectorInfo selector = dispatchTable.selectorForTarget(reference);
    final signature = selector.signature;
    final name = selector.entryPointName(useUncheckedEntry);
    assert(selector.name == interfaceTarget.name.text);

    pushReceiver(signature);

    final targets = selector.targets(unchecked: useUncheckedEntry);
    List<({Range range, Reference target})> targetRanges = targets.targetRanges;
    List<({Range range, Reference target})> staticDispatchRanges =
        targets.staticDispatchRanges;

    // NOTE: Keep this in sync with
    // `dynamic_forwarders.dart:generateNoSuchMethodCall`.
    final bool noTarget =
        targetRanges.isEmpty && !selector.isDynamicSubmoduleOverridable;
    final bool directCall =
        targetRanges.length == 1 && staticDispatchRanges.length == 1;
    final callPolymorphicDispatcher =
        !directCall && staticDispatchRanges.isNotEmpty;

    if (noTarget) {
      // Unreachable call
      b.comment("Virtual call of $name with no targets"
          " at ${node.location}");
      pushArguments(signature, selector.paramInfo);
      for (int i = 0; i < signature.inputs.length; ++i) {
        b.drop();
      }
      b.block(const [], signature.outputs);
      b.unreachable();
      b.end();
      return translator.outputOrVoid(signature.outputs);
    }
    if (directCall) {
      final target = translator.getFunctionEntry(targetRanges[0].target,
          uncheckedEntry: useUncheckedEntry);
      final directCallSignature = translator.signatureForDirectCall(target);
      final paramInfo = translator.paramInfoForDirectCall(target);
      pushArguments(directCallSignature, paramInfo);
      return translator.outputOrVoid(call(target));
    }

    // Receiver is already on stack.
    w.Local receiverVar = addLocal(signature.inputs.first);
    assert(!receiverVar.type.nullable);
    b.local_tee(receiverVar);
    if (callPolymorphicDispatcher) {
      b.loadClassId(translator, receiverVar.type);
      b.local_get(receiverVar);
    }
    pushArguments(signature, selector.paramInfo);

    if (callPolymorphicDispatcher) {
      b.invoke(translator
          .getPolymorphicDispatchersForModule(b.module)
          .getPolymorphicDispatcher(selector,
              useUncheckedEntry: useUncheckedEntry));
    } else {
      b.comment("Instance $kind of '$name'");
      b.local_get(receiverVar);
      translator.callDispatchTable(b, selector,
          interfaceTarget: reference,
          useUncheckedEntry: useUncheckedEntry,
          table: dispatchTable);
    }

    return translator.outputOrVoid(signature.outputs);
  }

  @override
  w.ValueType visitVariableGet(VariableGet node, w.ValueType expectedType) {
    w.Local? local = locals[node.variable];
    Capture? capture = closures.captures[node.variable];
    if (capture != null) {
      if (!capture.written && local != null) {
        b.local_get(local);
        return local.type;
      } else {
        b.local_get(capture.context.currentLocal);
        b.struct_get(capture.context.struct, capture.fieldIndex);
        return capture.type;
      }
    } else {
      if (local == null) {
        throw "Read of undefined variable ${node.variable}";
      }
      b.local_get(local);
      return local.type;
    }
  }

  @override
  w.ValueType visitVariableSet(VariableSet node, w.ValueType expectedType) {
    w.Local? local = locals[node.variable];
    Capture? capture = closures.captures[node.variable];
    bool preserved = expectedType != voidMarker;
    if (capture != null) {
      assert(capture.written);
      b.local_get(capture.context.currentLocal);
      translateExpression(node.value, capture.type);
      if (preserved) {
        w.Local temp = addLocal(capture.type);
        b.local_tee(temp);
        b.struct_set(capture.context.struct, capture.fieldIndex);
        b.local_get(temp);
        return temp.type;
      } else {
        b.struct_set(capture.context.struct, capture.fieldIndex);
        return voidMarker;
      }
    } else {
      if (local == null) {
        throw "Write of undefined variable ${node.variable}";
      }
      translateExpression(node.value, local.type);
      if (preserved) {
        b.local_tee(local);
        return local.type;
      } else {
        b.local_set(local);
        return voidMarker;
      }
    }
  }

  @override
  w.ValueType visitStaticGet(StaticGet node, w.ValueType expectedType) {
    w.ValueType? intrinsicResult =
        intrinsifier.generateStaticGetterIntrinsic(node);
    if (intrinsicResult != null) return intrinsicResult;

    return translator.outputOrVoid(call(node.targetReference));
  }

  @override
  w.ValueType visitStaticTearOff(StaticTearOff node, w.ValueType expectedType) {
    translator.constants.instantiateConstant(
        b, StaticTearOffConstant(node.target), expectedType);
    return expectedType;
  }

  @override
  w.ValueType visitStaticSet(StaticSet node, w.ValueType expectedType) {
    bool preserved = expectedType != voidMarker;
    Member target = node.target;
    final reference =
        target is Field ? target.setterReference! : target.reference;
    w.ValueType paramType =
        translator.signatureForDirectCall(reference).inputs.single;
    translateExpression(node.value, paramType);
    if (!preserved) {
      call(node.targetReference);
      return voidMarker;
    }
    w.Local temp = addLocal(paramType);
    b.local_tee(temp);

    call(reference);
    b.local_get(temp);
    return temp.type;
  }

  @override
  w.ValueType visitSuperPropertyGet(
      SuperPropertyGet node, w.ValueType expectedType) {
    Member target = _lookupSuperTarget(node.interfaceTarget, setter: false);
    if (target is Procedure && !target.isGetter) {
      // Super tear-off
      w.StructType closureStruct = _pushClosure(
          translator.getTearOffClosure(target, b.module),
          translator.getTearOffType(target),
          () => visitThis(w.RefType.struct(nullable: false)));
      return w.RefType.def(closureStruct, nullable: false);
    }
    return _directGet(target, ThisExpression());
  }

  @override
  w.ValueType visitSuperPropertySet(
      SuperPropertySet node, w.ValueType expectedType) {
    Member target = _lookupSuperTarget(node.interfaceTarget, setter: true);
    return _directSet(target, ThisExpression(), node.value,
        preserved: expectedType != voidMarker, useUncheckedEntry: true);
  }

  @override
  w.ValueType visitInstanceGet(InstanceGet node, w.ValueType expectedType) {
    Member target = node.interfaceTarget;
    if (node.kind == InstanceAccessKind.Object) {
      late w.Label doneLabel;
      w.ValueType resultType =
          _virtualCall(node, target, _VirtualCallKind.Get, (signature) {
        doneLabel = b.block(const [], signature.outputs);
        w.Label nullLabel = b.block();
        translateExpression(node.receiver, translator.topType);
        b.br_on_null(nullLabel);
      }, (_, __) {}, useUncheckedEntry: false);
      b.br(doneLabel);
      b.end(); // nullLabel
      switch (target.name.text) {
        case "hashCode":
          b.i64_const(2011);
          break;
        case "runtimeType":
          translateExpression(
              ConstantExpression(TypeLiteralConstant(NullType())), resultType);
          break;
        default:
          unimplemented(
              node, "Nullable get of ${target.name.text}", [resultType]);
          break;
      }
      b.end(); // doneLabel
      return resultType;
    }

    Member? singleTarget = translator.singleTarget(node);
    if (singleTarget != null) {
      final intrinsic = intrinsifier.generateInstanceGetterIntrinsic(node);
      if (intrinsic != null) return intrinsic;

      return _directGet(singleTarget, node.receiver);
    } else {
      return _virtualCall(
          node,
          target,
          _VirtualCallKind.Get,
          (signature) =>
              translateExpression(node.receiver, signature.inputs.first),
          (_, __) {},
          useUncheckedEntry: false);
    }
  }

  @override
  w.ValueType visitDynamicGet(DynamicGet node, w.ValueType expectedType) {
    final receiver = node.receiver;
    final memberName = node.name;
    final forwarder = translator
        .getDynamicForwardersForModule(b.module)
        .getDynamicGetForwarder(memberName);

    // Evaluate receiver
    translateExpression(receiver, translator.topType);
    final nullableReceiverLocal = addLocal(translator.topType);
    b.local_set(nullableReceiverLocal);

    final nullBlock = b.block([], [translator.topTypeNonNullable]);
    b.local_get(nullableReceiverLocal);
    b.br_on_non_null(nullBlock);
    // Throw `NoSuchMethodError`. Normally this needs to happen via instance
    // invocation of `noSuchMethod` (done in [_callNoSuchMethod]), but we don't
    // have a `Null` class in dart2wasm so we throw directly.
    b.local_get(nullableReceiverLocal);
    createGetterInvocationObject(translator, b, memberName);

    call(translator.noSuchMethodErrorThrowWithInvocation.reference);
    b.unreachable();
    b.end(); // nullBlock

    // Call get forwarder
    translator.callFunction(forwarder.function, b);

    return translator.topType;
  }

  @override
  w.ValueType visitDynamicSet(DynamicSet node, w.ValueType expectedType) {
    final receiver = node.receiver;
    final value = node.value;
    final memberName = node.name;
    final forwarder = translator
        .getDynamicForwardersForModule(b.module)
        .getDynamicSetForwarder(memberName);

    // Evaluate receiver
    translateExpression(receiver, translator.topType);
    final nullableReceiverLocal = addLocal(translator.topType);
    b.local_set(nullableReceiverLocal);

    // Evaluate positional arg
    translateExpression(value, translator.topType);
    final positionalArgLocal = addLocal(translator.topType);
    b.local_set(positionalArgLocal);

    final nullBlock = b.block([], [translator.topTypeNonNullable]);
    b.local_get(nullableReceiverLocal);
    b.br_on_non_null(nullBlock);
    // Throw `NoSuchMethodError`. Normally this needs to happen via instance
    // invocation of `noSuchMethod` (done in [_callNoSuchMethod]), but we don't
    // have a `Null` class in dart2wasm so we throw directly.
    b.local_get(nullableReceiverLocal);
    createSetterInvocationObject(translator, b, memberName, positionalArgLocal);

    call(translator.noSuchMethodErrorThrowWithInvocation.reference);
    b.unreachable();
    b.end(); // nullBlock

    // Call set forwarder
    b.local_get(positionalArgLocal);
    translator.callFunction(forwarder.function, b);

    return translator.topType;
  }

  w.ValueType _directGet(Member target, Expression receiver) {
    if (target is Field) {
      ClassInfo info = translator.classInfo[target.enclosingClass]!;
      int fieldIndex = translator.fieldIndex[target]!;
      w.ValueType receiverType = info.nonNullableType;
      w.ValueType fieldType = info.struct.fields[fieldIndex].type.unpacked;
      translateExpression(receiver, receiverType);
      b.struct_get(info.struct, fieldIndex);
      return fieldType;
    } else {
      // Instance call of getter
      assert(target is Procedure && target.isGetter);
      w.FunctionType targetFunctionType =
          translator.signatureForDirectCall(target.reference);
      translateExpression(receiver, targetFunctionType.inputs.single);
      return translator.outputOrVoid(call(target.reference));
    }
  }

  @override
  w.ValueType visitInstanceTearOff(
      InstanceTearOff node, w.ValueType expectedType) {
    Member target = node.interfaceTarget;

    if (node.kind == InstanceAccessKind.Object) {
      late w.Label doneLabel;
      w.ValueType resultType =
          _virtualCall(node, target, _VirtualCallKind.Get, (signature) {
        doneLabel = b.block(const [], signature.outputs);
        w.Label nullLabel = b.block();
        translateExpression(node.receiver, translator.topType);
        b.br_on_null(nullLabel);
        translator.convertType(b, translator.topType, signature.inputs[0]);
      }, (_, __) {}, useUncheckedEntry: false);
      b.br(doneLabel);
      b.end(); // nullLabel
      switch (target.name.text) {
        case "toString":
          translateExpression(
              ConstantExpression(
                  StaticTearOffConstant(translator.nullToString)),
              resultType);
          break;
        case "noSuchMethod":
          translateExpression(
              ConstantExpression(
                  StaticTearOffConstant(translator.nullNoSuchMethod)),
              resultType);
          break;
        default:
          unimplemented(
              node, "Nullable tear-off of ${target.name.text}", [resultType]);
          break;
      }
      b.end(); // doneLabel
      return resultType;
    }

    return _virtualCall(
        node,
        target,
        _VirtualCallKind.Get,
        (signature) =>
            translateExpression(node.receiver, signature.inputs.first),
        (_, __) {},
        useUncheckedEntry: false);
  }

  @override
  w.ValueType visitInstanceSet(InstanceSet node, w.ValueType expectedType) {
    bool preserved = expectedType != voidMarker;
    w.Local? temp;
    Member? singleTarget = translator.singleTarget(node);
    final useUncheckedEntry =
        translator.canUseUncheckedEntry(node.receiver, node);
    if (singleTarget != null) {
      return _directSet(singleTarget, node.receiver, node.value,
          preserved: preserved, useUncheckedEntry: useUncheckedEntry);
    } else {
      _virtualCall(
          node,
          node.interfaceTarget,
          _VirtualCallKind.Set,
          (signature) =>
              translateExpression(node.receiver, signature.inputs.first),
          (signature, _) {
        w.ValueType paramType = signature.inputs.last;
        translateExpression(node.value, paramType);
        if (preserved) {
          temp = addLocal(paramType);
          b.local_tee(temp!);
        }
      }, useUncheckedEntry: useUncheckedEntry);
      if (preserved) {
        b.local_get(temp!);
        return temp!.type;
      } else {
        return voidMarker;
      }
    }
  }

  w.ValueType _directSet(Member target, Expression receiver, Expression value,
      {required bool preserved, required bool useUncheckedEntry}) {
    w.Local? temp;
    final Reference reference = translator.getFunctionEntry(
        (target is Field)
            ? target.setterReference!
            : (target as Procedure).reference,
        uncheckedEntry: useUncheckedEntry);
    final w.FunctionType targetFunctionType =
        translator.signatureForDirectCall(reference);
    final w.ValueType paramType = targetFunctionType.inputs.last;
    translateExpression(receiver, targetFunctionType.inputs.first);
    translateExpression(value, paramType);
    if (preserved) {
      temp = addLocal(paramType);
      b.local_tee(temp);
    }
    call(reference);
    if (preserved) {
      b.local_get(temp!);
      return temp.type;
    } else {
      return voidMarker;
    }
  }

  @override
  void visitFunctionDeclaration(FunctionDeclaration node) {
    Capture? capture = closures.captures[node.variable];
    bool locallyClosurized = closures.closurizedFunctions.contains(node);
    if (capture != null || locallyClosurized) {
      if (capture != null) {
        b.local_get(capture.context.currentLocal);
      }
      w.StructType struct = _instantiateClosure(node.function);
      if (locallyClosurized) {
        w.Local local = addLocal(w.RefType.def(struct, nullable: false));
        locals[node.variable] = local;
        if (capture != null) {
          b.local_tee(local);
        } else {
          b.local_set(local);
        }
      }
      if (capture != null) {
        b.struct_set(capture.context.struct, capture.fieldIndex);
      }
    }
  }

  @override
  w.ValueType visitFunctionExpression(
      FunctionExpression node, w.ValueType expectedType) {
    w.StructType struct = _instantiateClosure(node.function);
    return w.RefType.def(struct, nullable: false);
  }

  w.StructType _instantiateClosure(FunctionNode functionNode) {
    Lambda lambda = closures.lambdas[functionNode]!;
    ClosureImplementation closure = translator.getClosure(
        functionNode,
        lambda.function,
        b.module,
        ParameterInfo.fromLocalFunction(functionNode),
        "closure wrapper at ${functionNode.location}");
    return _pushClosure(
        closure,
        functionNode.computeFunctionType(Nullability.nonNullable),
        () => _pushContext(functionNode));
  }

  w.StructType _pushClosure(ClosureImplementation closure,
      DartType functionType, void Function() pushContext) {
    w.StructType struct = closure.representation.closureStruct;

    ClassInfo info = translator.closureInfo;
    translator.functions.recordClassAllocation(info.classId);

    b.pushObjectHeaderFields(translator, info);
    pushContext();
    translator.globals.readGlobal(b, closure.vtable);
    types.makeType(this, functionType);
    b.struct_new(struct);

    return struct;
  }

  void _pushContext(FunctionNode functionNode) {
    Context? context = closures.contexts[functionNode]?.parent;
    if (context != null) {
      assert(!context.isEmpty);
      b.local_get(context.currentLocal);
      if (context.currentLocal.type.nullable) {
        b.ref_as_non_null();
      }
    } else {
      translator.globals.readGlobal(
          b,
          translator
              .getDummyValuesCollectorForModule(b.module)
              .dummyStructGlobal); // Dummy context
    }
  }

  @override
  w.ValueType visitFunctionInvocation(
      FunctionInvocation node, w.ValueType expectedType) {
    w.ValueType? intrinsicResult =
        intrinsifier.generateFunctionCallIntrinsic(node);
    if (intrinsicResult != null) return intrinsicResult;

    if (node.kind == FunctionAccessKind.Function ||
        translator.dynamicModuleSupportEnabled) {
      // Type of function is `Function`, without the argument types.
      return visitDynamicInvocation(
          DynamicInvocation(DynamicAccessKind.Dynamic, node.receiver, node.name,
              node.arguments),
          expectedType);
    }

    List<String> argNames = node.arguments.named.map((a) => a.name).toList()
      ..sort();
    ClosureRepresentation? representation = translator.closureLayouter
        .getClosureRepresentation(node.arguments.types.length,
            node.arguments.positional.length, argNames);
    if (representation == null) {
      // This is a dynamic function call with a signature that matches no
      // functions in the program.
      b.unreachable();
      return translator.topType;
    }

    final SingleClosureTarget? directClosureCall =
        translator.singleClosureTarget(node, representation, typeContext);

    if (directClosureCall != null) {
      return _generateDirectClosureCall(
          node, representation, directClosureCall);
    }

    return _generateClosureInvocation(node, representation);
  }

  w.ValueType _generateDirectClosureCall(FunctionInvocation node,
      ClosureRepresentation representation, SingleClosureTarget closureTarget) {
    final closureStruct = representation.closureStruct;
    final closureStructRef = w.RefType.def(closureStruct, nullable: false);
    final signature = closureTarget.signature;
    final paramInfo = closureTarget.paramInfo;
    final member = closureTarget.member;
    final lambdaFunction = closureTarget.lambdaFunction;

    if (lambdaFunction == null) {
      if (paramInfo.takesContextOrReceiver) {
        translateExpression(node.receiver, closureStructRef);
        b.struct_get(closureStruct, FieldIndex.closureContext);
        translator.convertType(b, closureContextFieldType, signature.inputs[0]);
        _visitArguments(node.arguments, signature, paramInfo, 1);
      } else {
        _visitArguments(node.arguments, signature, paramInfo, 0);
      }
      return translator.outputOrVoid(call(translator
          .getFunctionEntry(member.reference, uncheckedEntry: false)));
    } else {
      assert(paramInfo.takesContextOrReceiver);
      translateExpression(node.receiver, closureStructRef);
      b.struct_get(closureStruct, FieldIndex.closureContext);
      translator.convertType(b, closureContextFieldType, signature.inputs[0]);
      _visitArguments(node.arguments, signature, paramInfo, 1);
      return translator
          .outputOrVoid(translator.callFunction(lambdaFunction, b));
    }
  }

  w.ValueType _generateClosureInvocation(
      FunctionInvocation node, ClosureRepresentation representation) {
    final closureStruct = representation.closureStruct;

    // Evaluate receiver
    w.Local closureLocal =
        addLocal(w.RefType.def(closureStruct, nullable: false));
    translateExpression(node.receiver, closureLocal.type);
    b.local_tee(closureLocal);
    b.struct_get(closureStruct, FieldIndex.closureContext);

    // Type arguments
    for (DartType typeArg in node.arguments.types) {
      types.makeType(this, typeArg);
    }

    // Positional arguments
    for (Expression arg in node.arguments.positional) {
      translateExpression(arg, translator.topType);
    }

    // Named arguments
    final List<String> argNames =
        node.arguments.named.map((a) => a.name).toList()..sort();
    final Map<String, w.Local> namedLocals = {};
    for (final namedArg in node.arguments.named) {
      final w.Local namedLocal = addLocal(translator.topType);
      namedLocals[namedArg.name] = namedLocal;
      translateExpression(namedArg.value, namedLocal.type);
      b.local_set(namedLocal);
    }
    for (String name in argNames) {
      b.local_get(namedLocals[name]!);
    }

    final int vtableFieldIndex = representation.fieldIndexForSignature(
        node.arguments.positional.length, argNames);
    final w.FunctionType functionType =
        representation.getVtableFieldType(vtableFieldIndex);

    // Call entry point in vtable
    b.local_get(closureLocal);
    b.struct_get(closureStruct, FieldIndex.closureVtable);
    b.struct_get(representation.vtableStruct, vtableFieldIndex);
    b.call_ref(functionType);

    return translator.topType;
  }

  @override
  w.ValueType visitLocalFunctionInvocation(
      LocalFunctionInvocation node, w.ValueType expectedType) {
    var decl = node.variable.parent as FunctionDeclaration;
    Lambda lambda = closures.lambdas[decl.function]!;
    _pushContext(decl.function);
    Arguments arguments = node.arguments;
    _visitArguments(arguments, lambda.function.type,
        ParameterInfo.fromLocalFunction(decl.function), 1);
    b.comment("Local call of ${decl.variable.name}");
    translator.callFunction(lambda.function, b);
    return translator.outputOrVoid(lambda.function.type.outputs);
  }

  @override
  w.ValueType visitInstantiation(Instantiation node, w.ValueType expectedType) {
    DartType type = dartTypeOf(node.expression);
    if (type is FunctionType) {
      int typeCount = type.typeParameters.length;
      int posArgCount = type.positionalParameters.length;
      List<String> argNames = type.namedParameters.map((a) => a.name).toList();
      ClosureRepresentation representation = translator.closureLayouter
          .getClosureRepresentation(typeCount, posArgCount, argNames)!;

      // Operand closure
      w.RefType closureType =
          w.RefType.def(representation.closureStruct, nullable: false);
      w.Local closureTemp = addLocal(closureType);
      translateExpression(node.expression, closureType);
      b.local_tee(closureTemp);

      // Type arguments
      for (DartType typeArg in node.typeArguments) {
        types.makeType(this, typeArg);
      }

      // Instantiation function
      b.local_get(closureTemp);
      b.struct_get(representation.closureStruct, FieldIndex.closureVtable);
      b.struct_get(
          representation.vtableStruct, FieldIndex.vtableInstantiationFunction);

      // Call instantiation function
      b.call_ref(representation.instantiationFunctionType);
      return representation.instantiationFunctionType.outputs.single;
    } else {
      // Only other alternative is `NeverType`.
      assert(type is NeverType);
      b.unreachable();
      return voidMarker;
    }
  }

  @override
  w.ValueType visitLogicalExpression(
      LogicalExpression node, w.ValueType expectedType) {
    _conditional(node, () => b.i32_const(1), () => b.i32_const(0),
        const [w.NumType.i32]);
    return w.NumType.i32;
  }

  @override
  w.ValueType visitNot(Not node, w.ValueType expectedType) {
    translateExpression(node.operand, w.NumType.i32);
    b.i32_eqz();
    return w.NumType.i32;
  }

  @override
  w.ValueType visitConditionalExpression(
      ConditionalExpression node, w.ValueType expectedType) {
    _conditional(
        node.condition,
        () => translateExpression(node.then, expectedType),
        () => translateExpression(node.otherwise, expectedType),
        [if (expectedType != voidMarker) expectedType]);
    return expectedType;
  }

  @override
  w.ValueType visitNullCheck(NullCheck node, w.ValueType expectedType) {
    w.ValueType operandType =
        translator.translateType(dartTypeOf(node.operand));
    w.ValueType nonNullOperandType = operandType.withNullability(false);

    // In rare cases the operand is non-nullable but TFA doesn't optimize away
    // the null check. If the operand is an unboxed type, the br_on_non_null
    // would fail to compile.
    if (!operandType.nullable) {
      translateExpression(node.operand, operandType);
      return nonNullOperandType;
    }
    w.Label nullCheckBlock = b.block(const [], [nonNullOperandType]);
    translateExpression(node.operand, operandType);

    // We lower a null check to a br_on_non_null, throwing a [TypeError] in
    // the null case.
    b.br_on_non_null(nullCheckBlock);
    call(translator.throwNullCheckErrorWithCurrentStack.reference);
    b.unreachable();
    b.end();
    return nonNullOperandType;
  }

  void _visitArguments(Arguments node, w.FunctionType signature,
      ParameterInfo paramInfo, int signatureOffset) {
    // Type arguments
    for (int i = 0; i < node.types.length; i++) {
      types.makeType(this, node.types[i]);
    }
    signatureOffset += node.types.length;

    // Positional arguments
    for (int i = 0; i < node.positional.length; i++) {
      translateExpression(
          node.positional[i], signature.inputs[signatureOffset + i]);
    }
    // Push default values for optional positional parameters.
    for (int i = node.positional.length; i < paramInfo.positional.length; i++) {
      final w.ValueType type = signature.inputs[signatureOffset + i];
      translator.constants
          .instantiateConstant(b, paramInfo.positional[i]!, type);
    }

    // Named arguments. Store evaluated arguments in locals to be able to
    // re-order them based on the `ParameterInfo`.
    final Map<String, w.Local> namedLocals = {};
    for (var namedArg in node.named) {
      final w.ValueType type = signature
          .inputs[signatureOffset + paramInfo.nameIndex[namedArg.name]!];
      final w.Local namedLocal = addLocal(type);
      namedLocals[namedArg.name] = namedLocal;
      translateExpression(namedArg.value, namedLocal.type);
      b.local_set(namedLocal);
    }
    // Re-order named arguments and push default values for optional named
    // parameters.
    for (String name in paramInfo.names) {
      w.Local? namedLocal = namedLocals[name];
      final w.ValueType type =
          signature.inputs[signatureOffset + paramInfo.nameIndex[name]!];
      if (namedLocal != null) {
        b.local_get(namedLocal);
      } else {
        translator.constants
            .instantiateConstant(b, paramInfo.named[name]!, type);
      }
    }
  }

  @override
  w.ValueType visitStringConcatenation(
      StringConcatenation node, w.ValueType expectedType) {
    bool isConstantString(Expression expr) =>
        expr is StringLiteral ||
        (expr is ConstantExpression && expr.constant is StringConstant);

    String extractConstantString(Expression expr) {
      if (expr is StringLiteral) {
        return expr.value;
      } else {
        return ((expr as ConstantExpression).constant as StringConstant).value;
      }
    }

    final expressions = node.expressions;
    if (expressions.every(isConstantString)) {
      StringBuffer result = StringBuffer();
      for (final expr in expressions) {
        result.write(extractConstantString(expr));
      }
      final expr = StringLiteral(result.toString());
      return visitStringLiteral(expr, expectedType);
    }

    late final Procedure target;

    // We have special cases for 1/2/3/4 arguments.
    if (expressions.length <= 4) {
      final nullableObjectType =
          translator.translateType(translator.coreTypes.objectNullableRawType);
      for (final expression in expressions) {
        translateExpression(expression, nullableObjectType);
      }
      if (expressions.length == 1) {
        target = translator.jsStringInterpolate1;
      } else if (expressions.length == 2) {
        target = translator.jsStringInterpolate2;
      } else if (expressions.length == 3) {
        target = translator.jsStringInterpolate3;
      } else {
        assert(expressions.length == 4);
        target = translator.jsStringInterpolate4;
      }
    } else {
      final nullableObjectType = translator.coreTypes.objectNullableRawType;
      makeArrayFromExpressions(expressions, nullableObjectType);
      target = translator.jsStringInterpolate;
    }
    return translator.outputOrVoid(call(target.reference));
  }

  @override
  w.ValueType visitThrow(Throw node, w.ValueType expectedType) {
    // Front-end wraps the argument with `as Object` when necessary, so we can
    // assume non-nullable here.
    assert(!dartTypeOf(node.expression).isPotentiallyNullable);
    translateExpression(node.expression, translator.topTypeNonNullable);
    call(translator.errorThrowWithCurrentStackTrace.reference);
    b.unreachable();
    return expectedType;
  }

  @override
  w.ValueType visitRethrow(Rethrow node, w.ValueType expectedType) {
    final exceptionLocals = tryBlockLocals.last;
    b.local_get(exceptionLocals.exceptionLocal);
    b.local_get(exceptionLocals.stackTraceLocal);
    b.throw_(translator.getExceptionTag(b.module));
    return expectedType;
  }

  @override
  w.ValueType visitConstantExpression(
      ConstantExpression node, w.ValueType expectedType) {
    translator.constants.instantiateConstant(b, node.constant, expectedType);
    return expectedType;
  }

  @override
  w.ValueType visitNullLiteral(NullLiteral node, w.ValueType expectedType) {
    translator.constants.instantiateConstant(b, NullConstant(), expectedType);
    return expectedType;
  }

  @override
  w.ValueType visitStringLiteral(StringLiteral node, w.ValueType expectedType) {
    translator.constants
        .instantiateConstant(b, StringConstant(node.value), expectedType);
    return expectedType;
  }

  @override
  w.ValueType visitBoolLiteral(BoolLiteral node, w.ValueType expectedType) {
    translator.constants
        .instantiateConstant(b, BoolConstant(node.value), expectedType);
    return expectedType;
  }

  @override
  w.ValueType visitIntLiteral(IntLiteral node, w.ValueType expectedType) {
    translator.constants
        .instantiateConstant(b, IntConstant(node.value), expectedType);
    return expectedType;
  }

  @override
  w.ValueType visitDoubleLiteral(DoubleLiteral node, w.ValueType expectedType) {
    translator.constants
        .instantiateConstant(b, DoubleConstant(node.value), expectedType);
    return expectedType;
  }

  @override
  w.ValueType visitListLiteral(ListLiteral node, w.ValueType expectedType) {
    final useSharedCreator = types.isTypeConstant(node.typeArgument);

    final passType = !useSharedCreator;
    final passArray = node.expressions.isNotEmpty;

    final targetReference = passArray
        ? translator.growableListFromWasmArray.reference
        : translator.growableListEmpty.reference;

    final target = useSharedCreator
        ? translator
            .getPartialInstantiatorForModule(b.module)
            .getOneTypeArgumentForwarder(targetReference, node.typeArgument,
                'create${passArray ? '' : 'Empty'}List<${node.typeArgument}>')
        : translator.functions.getFunction(targetReference);

    if (passType) {
      types.makeType(this, node.typeArgument);
    }
    if (passArray) {
      makeArrayFromExpressions(node.expressions,
          translator.coreTypes.objectRawType(Nullability.nullable));
    }

    translator.callFunction(target, b);

    return target.type.outputs.single;
  }

  w.ValueType makeArrayFromExpressions(
      List<Expression> expressions, InterfaceType elementType) {
    return makeArray(
        translator.arrayTypeForDartType(elementType, mutable: true),
        expressions.length, (w.ValueType type, int i) {
      translateExpression(expressions[i], type);
    });
  }

  w.ValueType makeArray(w.ArrayType arrayType, int length,
      void Function(w.ValueType, int) generateItem) {
    return translator.makeArray(b, arrayType, length, generateItem);
  }

  @override
  w.ValueType visitMapLiteral(MapLiteral node, w.ValueType expectedType) {
    final useSharedCreator = types.isTypeConstant(node.keyType) &&
        types.isTypeConstant(node.valueType);

    final passTypes = !useSharedCreator;
    final passArray = node.entries.isNotEmpty;

    final targetReference = passArray
        ? translator.mapFromWasmArray.reference
        : translator.mapFactory.reference;

    final target = useSharedCreator
        ? translator
            .getPartialInstantiatorForModule(b.module)
            .getTwoTypeArgumentForwarder(
                targetReference,
                node.keyType,
                node.valueType,
                'create${passArray ? '' : 'Empty'}'
                'Map<${node.keyType}, ${node.valueType}>')
        : translator.functions.getFunction(targetReference);

    if (passTypes) {
      types.makeType(this, node.keyType);
      types.makeType(this, node.valueType);
    }
    if (passArray) {
      makeArray(translator.nullableObjectArrayType, 2 * node.entries.length,
          (elementType, elementIndex) {
        final index = elementIndex ~/ 2;
        final entry = node.entries[index];
        if (elementIndex % 2 == 0) {
          translateExpression(entry.key, elementType);
        } else {
          translateExpression(entry.value, elementType);
        }
      });
    }
    translator.callFunction(target, b);

    return target.type.outputs.single;
  }

  @override
  w.ValueType visitSetLiteral(SetLiteral node, w.ValueType expectedType) {
    final useSharedCreator = types.isTypeConstant(node.typeArgument);

    final passType = !useSharedCreator;
    final passArray = node.expressions.isNotEmpty;

    final targetReference = passArray
        ? translator.setFromWasmArray.reference
        : translator.setFactory.reference;

    final target = useSharedCreator
        ? translator
            .getPartialInstantiatorForModule(b.module)
            .getOneTypeArgumentForwarder(targetReference, node.typeArgument,
                'create${passArray ? '' : 'Empty'}Set<${node.typeArgument}>')
        : translator.functions.getFunction(targetReference);

    if (passType) {
      types.makeType(this, node.typeArgument);
    }
    if (passArray) {
      makeArrayFromExpressions(node.expressions,
          translator.coreTypes.objectRawType(Nullability.nullable));
    }
    translator.callFunction(target, b);

    return target.type.outputs.single;
  }

  @override
  w.ValueType visitTypeLiteral(TypeLiteral node, w.ValueType expectedType) {
    return types.makeType(this, node.type);
  }

  @override
  w.ValueType visitIsExpression(IsExpression node, w.ValueType expectedType) {
    final operandType = dartTypeOf(node.operand);
    final boxedOperandType = operandType.isPotentiallyNullable
        ? translator.topType
        : translator.topTypeNonNullable;
    translateExpression(node.operand, boxedOperandType);
    types.emitIsTest(this, node.type, operandType, node.location);
    return w.NumType.i32;
  }

  @override
  w.ValueType visitAsExpression(AsExpression node, w.ValueType expectedType) {
    final isImplicitCheck =
        (node.isTypeError || node.isCovarianceCheck || node.isForDynamic);
    if (node.isUnchecked ||
        (translator.options.omitImplicitTypeChecks && isImplicitCheck) ||
        (translator.options.omitExplicitTypeChecks && !isImplicitCheck)) {
      return translateExpression(node.operand, expectedType);
    }

    final operandType = dartTypeOf(node.operand);
    final boxedOperandType = operandType.isPotentiallyNullable
        ? translator.topType
        : translator.topTypeNonNullable;
    translateExpression(node.operand, boxedOperandType);
    return types.emitAsCheck(this, node.isCovarianceCheck, node.type,
        operandType, boxedOperandType, node.location);
  }

  @override
  w.ValueType visitLoadLibrary(LoadLibrary node, w.ValueType expectedType) {
    throw UnsupportedError(
        'LoadLibrary should be lowered by modular transformer.');
  }

  @override
  w.ValueType visitCheckLibraryIsLoaded(
      CheckLibraryIsLoaded node, w.ValueType expectedType) {
    throw UnsupportedError(
        'CheckLibraryIsLoaded should be lowered by modular transformer.');
  }

  /// Pushes the `_Type` object for a function or class type parameter to the
  /// stack and returns the value type of the object.
  w.ValueType instantiateTypeParameter(TypeParameter parameter) {
    w.ValueType resultType;

    w.Local? local = typeLocals[parameter];
    Capture? capture = closures.captures[parameter];
    if (local != null) {
      b.local_get(local);
      resultType = local.type;
    } else if (capture != null) {
      Capture capture = closures.captures[parameter]!;
      b.local_get(capture.context.currentLocal);
      b.struct_get(capture.context.struct, capture.fieldIndex);
      resultType = capture.type;
    } else {
      Class cls = parameter.declaration as Class;
      ClassInfo info = translator.classInfo[cls]!;
      int fieldIndex = translator.typeParameterIndex[parameter]!;
      visitThis(info.nonNullableType);
      b.struct_get(info.struct, fieldIndex);
      resultType = info.struct.fields[fieldIndex].type.unpacked;
    }

    translator.convertType(b, resultType, types.nonNullableTypeType);
    return types.nonNullableTypeType;
  }

  @override
  w.ValueType visitRecordLiteral(RecordLiteral node, w.ValueType expectedType) {
    final ClassInfo recordClassInfo =
        translator.getRecordClassInfo(node.recordType);
    translator.functions.recordClassAllocation(recordClassInfo.classId);

    b.pushObjectHeaderFields(translator, recordClassInfo);
    for (Expression positional in node.positional) {
      translateExpression(positional, translator.topType);
    }
    for (NamedExpression named in node.named) {
      translateExpression(named.value, translator.topType);
    }
    b.struct_new(recordClassInfo.struct);

    return recordClassInfo.nonNullableType;
  }

  @override
  w.ValueType visitRecordIndexGet(
      RecordIndexGet node, w.ValueType expectedType) {
    final RecordShape recordShape = RecordShape.fromType(node.receiverType);
    final ClassInfo recordClassInfo =
        translator.getRecordClassInfo(node.receiverType);

    translateExpression(node.receiver, translator.topTypeNonNullable);
    b.ref_cast(w.RefType(recordClassInfo.struct, nullable: false));
    b.struct_get(
        recordClassInfo.struct, recordShape.getPositionalIndex(node.index));

    return translator.topType;
  }

  @override
  w.ValueType visitRecordNameGet(RecordNameGet node, w.ValueType expectedType) {
    final RecordShape recordShape = RecordShape.fromType(node.receiverType);
    final ClassInfo recordClassInfo =
        translator.getRecordClassInfo(node.receiverType);

    translateExpression(node.receiver, translator.topTypeNonNullable);
    b.ref_cast(w.RefType(recordClassInfo.struct, nullable: false));
    b.struct_get(recordClassInfo.struct, recordShape.getNameIndex(node.name));

    return translator.topType;
  }

  @override
  w.ValueType visitFileUriExpression(
      FileUriExpression node, w.ValueType expectedType) {
    return translateExpression(node.expression, expectedType);
  }

  /// Generate code that checks type of an argument against an expected type
  /// and throws a `TypeError` on failure.
  ///
  /// Expects a boxed object (whose type is to be checked) on the stack.
  ///
  /// [argName] is used in the type error as the name of the argument that
  /// doesn't match the expected type.
  void _generateArgumentTypeCheck(
    String argName,
    w.RefType argumentType,
    DartType testedAgainstType,
  ) {
    if (translator.options.minify) {
      // We don't need to include the name in the error message, so we can use
      // the optimized `as` checks.
      types.emitAsCheck(this, false, testedAgainstType,
          translator.coreTypes.objectNullableRawType, argumentType);
      b.drop();
    } else {
      final argLocal = b.addLocal(argumentType);
      b.local_tee(argLocal);
      types.emitIsTest(
          this, testedAgainstType, translator.coreTypes.objectNullableRawType);
      b.i32_eqz();
      b.if_();
      b.local_get(argLocal);
      types.makeType(this, testedAgainstType);
      _emitString(argName);
      call(translator.stackTraceCurrent.reference);
      call(translator.throwArgumentTypeCheckError.reference);
      b.unreachable();
      b.end();
    }
  }

  void _generateTypeArgumentBoundCheck(
    String argName,
    w.Local typeLocal,
    DartType bound,
  ) {
    b.local_get(typeLocal);
    final boundLocal = b.addLocal(translator.runtimeTypeType);
    types.makeType(this, bound);
    b.local_tee(boundLocal);
    call(translator.isTypeSubtype.reference);

    b.i32_eqz();
    b.if_();
    // Type check failed
    b.local_get(typeLocal);
    b.local_get(boundLocal);
    _emitString(argName);
    call(translator.stackTraceCurrent.reference);
    call(translator.throwTypeArgumentBoundCheckError.reference);
    b.unreachable();
    b.end();
  }

  void _emitString(String str) => translateExpression(StringLiteral(str),
      translator.translateType(translator.coreTypes.stringNonNullableRawType));

  @override
  void visitPatternSwitchStatement(PatternSwitchStatement node) {
    // This node is internal to the front end and removed by the constant
    // evaluator.
    throw UnsupportedError("CodeGenerator.visitPatternSwitchStatement");
  }

  @override
  void visitPatternVariableDeclaration(PatternVariableDeclaration node) {
    // This node is internal to the front end and removed by the constant
    // evaluator.
    throw UnsupportedError("CodeGenerator.visitPatternVariableDeclaration");
  }

  @override
  void visitIfCaseStatement(IfCaseStatement node) {
    // This node is internal to the front end and removed by the constant
    // evaluator.
    throw UnsupportedError("CodeGenerator.visitIfCaseStatement");
  }

  void debugRuntimePrint(String s) {
    final printFunction =
        translator.functions.getFunction(translator.printToConsole.reference);
    translator.constants.instantiateConstant(
        b, StringConstant(s), printFunction.type.inputs[0]);
    translator.callFunction(printFunction, b);
  }

  @override
  void visitAuxiliaryStatement(AuxiliaryStatement node) {
    throw UnsupportedError(
        "Unsupported auxiliary statement $node (${node.runtimeType}).");
  }

  @override
  void visitAuxiliaryInitializer(AuxiliaryInitializer node) {
    throw UnsupportedError(
        "Unsupported auxiliary initializer $node (${node.runtimeType}).");
  }

  void emitUnimplementedExternalError(Member member) {
    b.comment("Unimplemented external member $member at ${member.location}");
    if (member.isInstanceMember) {
      b.local_get(paramLocals[0]);
    } else {
      b.ref_null(w.HeapType.none);
    }
    translator.constants.instantiateConstant(
        b,
        translator.symbols.methodSymbolFromName(member.name),
        translator.classInfo[translator.symbolClass]!.nonNullableType);
    call(translator
        .noSuchMethodErrorThrowUnimplementedExternalMemberError.reference);
    b.unreachable();
  }
}

CodeGenerator getMemberCodeGenerator(Translator translator,
    w.FunctionBuilder functionBuilder, Reference memberReference) {
  final member = memberReference.asMember;
  final asyncMarker = member.function?.asyncMarker ?? AsyncMarker.Sync;
  final codeGen = getInlinableMemberCodeGenerator(
      translator, asyncMarker, functionBuilder.type, memberReference);
  if (codeGen != null) return codeGen;

  final procedure = member as Procedure;

  if (asyncMarker == AsyncMarker.SyncStar) {
    return SyncStarProcedureCodeGenerator(
        translator, functionBuilder, procedure);
  }
  assert(asyncMarker == AsyncMarker.Async);
  return AsyncProcedureCodeGenerator(translator, functionBuilder, procedure);
}

CodeGenerator getLambdaCodeGenerator(Translator translator, Lambda lambda,
    Member enclosingMember, Closures enclosingMemberClosures) {
  final asyncMarker = lambda.functionNode.asyncMarker;

  if (asyncMarker == AsyncMarker.Async) {
    return AsyncLambdaCodeGenerator(
        translator, enclosingMember, lambda, enclosingMemberClosures);
  }
  if (asyncMarker == AsyncMarker.SyncStar) {
    return SyncStarLambdaCodeGenerator(
        translator, enclosingMember, lambda, enclosingMemberClosures);
  }
  assert(asyncMarker == AsyncMarker.Sync);
  return SynchronousLambdaCodeGenerator(
      translator, enclosingMember, lambda, enclosingMemberClosures);
}

/// Returns a [CodeGenerator] for the given member iff that member can be
/// inlined.
CodeGenerator? getInlinableMemberCodeGenerator(Translator translator,
    AsyncMarker asyncMarker, w.FunctionType functionType, Reference reference) {
  final Member member = reference.asMember;

  if (reference.isTearOffReference) {
    return TearOffCodeGenerator(translator, functionType, member);
  }
  if (reference.isTypeCheckerReference) {
    return TypeCheckerCodeGenerator(translator, functionType, member);
  }

  if (member is Constructor) {
    if (reference.isConstructorBodyReference) {
      return ConstructorCodeGenerator(translator, functionType, member);
    } else if (reference.isInitializerReference) {
      return InitializerListCodeGenerator(translator, functionType, member);
    } else {
      return ConstructorAllocatorCodeGenerator(
          translator, functionType, member);
    }
  }

  if (member is Field) {
    if (member.isStatic) {
      if (reference.isImplicitGetter || reference.isImplicitSetter) {
        return StaticFieldImplicitAccessorCodeGenerator(
            translator, functionType, member, reference.isImplicitGetter);
      }
      return StaticFieldInitializerCodeGenerator(
          translator, functionType, member);
    }
    final useUncheckedEntry = reference.isUncheckedEntryReference;
    return ImplicitFieldAccessorCodeGenerator(translator, functionType, member,
        reference.isImplicitGetter, useUncheckedEntry);
  }

  if (member is Procedure && asyncMarker == AsyncMarker.Sync) {
    return SynchronousProcedureCodeGenerator(
        translator, functionType, member, reference.entryKind);
  }
  assert(
      asyncMarker == AsyncMarker.SyncStar || asyncMarker == AsyncMarker.Async);
  return null;
}

class SynchronousProcedureCodeGenerator extends AstCodeGenerator {
  final Procedure member;
  final EntryPoint kind;

  SynchronousProcedureCodeGenerator(Translator translator,
      w.FunctionType functionType, this.member, this.kind)
      : super(translator, functionType, member) {
    assert(
        !translator.needToCheckTypesFor(member) || kind != EntryPoint.normal);
  }

  @override
  void generateInternal() {
    final source = member.enclosingComponent!.uriToSource[member.fileUri]!;
    setSourceMapSourceAndFileOffset(source, member.fileOffset);

    if (intrinsifier.generateMemberIntrinsic(
        member.reference, functionType, paramLocals, returnLabel)) {
      b.end();
      return;
    }

    if (member.isExternal) {
      emitUnimplementedExternalError(member);
      b.end();
      return;
    }

    closures = translator.getClosures(member);

    switch (kind) {
      case EntryPoint.normal:
        b.comment('Normal Entry');
        _makeNonMultiEntryPointFunction();
      case EntryPoint.checked:
        b.comment('Checked Entry');
        _makeMultipleEntryPoint(true);
      case EntryPoint.unchecked:
        b.comment('Unchecked Entry');
        _makeMultipleEntryPoint(false);
      case EntryPoint.body:
        b.comment('Body for Checked & Unchecked Entry');
        _makeMultipleEntryPointSharedBody();
        break;
    }
  }

  void _makeMultipleEntryPoint(bool checked) {
    final function = member.function;
    final signature = translator.signatureForDirectCall(member.bodyReference);
    if (checked) {
      setupParametersForCheckedEntry(member);
    } else {
      setupParametersForUncheckedEntry(member);
    }

    int arg = 0;
    visitThis(signature.inputs[arg++]);
    for (final parameter in function.typeParameters) {
      final r = instantiateTypeParameter(parameter);
      translator.convertType(b, r, signature.inputs[arg++]);
    }
    for (final parameter in function.positionalParameters) {
      final local = locals[parameter]!;
      b.local_get(local);
      translator.convertType(b, local.type, signature.inputs[arg++]);
    }
    for (final parameter in function.namedParameters) {
      final local = locals[parameter]!;
      b.local_get(local);
      translator.convertType(b, local.type, signature.inputs[arg++]);
    }

    final outputs = call(member.bodyReference);
    if (outputs.isNotEmpty) {
      translator.convertType(b, outputs.single, functionType.outputs.single);
    }
    _returnFromFunction();
    b.end();
  }

  void _makeMultipleEntryPointSharedBody() {
    final function = member.function;
    final typeParameters = function.typeParameters;
    final positionals = function.positionalParameters;
    final named = function.namedParameters;

    int param = _initializeThis(member.reference);

    for (int i = 0; i < typeParameters.length; i++) {
      final typeParameter = typeParameters[i];
      typeLocals[typeParameter] = paramLocals[param++];
    }
    void setupParameter(VariableDeclaration parameter) {
      // The body may assign less precise types to the parameter variable than
      // what the caller provides.
      w.Local local = paramLocals[param++];
      if (translator.typeOfCheckedParameterVariable(parameter) !=
          parameter.type) {
        final newLocal = addLocal(translator.translateType(parameter.type));
        b.local_get(local);
        translator.convertType(b, local.type, newLocal.type);
        b.local_set(newLocal);
        local = newLocal;
      }
      locals[parameter] = local;
    }

    for (int i = 0; i < positionals.length; i++) {
      setupParameter(positionals[i]);
    }
    for (int i = 0; i < named.length; i++) {
      setupParameter(named[i]);
    }

    setupContexts(member);
    Statement? body = member.function.body;
    if (body != null) {
      translateStatement(body);
    }

    _implicitReturn();
    b.end();
  }

  void _makeNonMultiEntryPointFunction() {
    setupParametersForNormalEntry(member);
    setupContexts(member);
    Statement? body = member.function.body;
    if (body != null) {
      translateStatement(body);
    }
    _implicitReturn();
    b.end();
    return;
  }
}

class TearOffCodeGenerator extends AstCodeGenerator {
  final Member member;

  TearOffCodeGenerator(
      Translator translator, w.FunctionType functionType, this.member)
      : super(translator, functionType, member);

  @override
  void generateInternal() {
    // Initialize [Closures] without [Closures.captures]: [Closures.captures] is
    // used by `makeType` below, when generating runtime types of type
    // parameters of the function type, but the type parameters are not
    // captured, always loaded from the `this` struct.
    closures = translator.getClosures(member, findCaptures: false);

    _initializeThis(member.reference);
    Procedure procedure = member as Procedure;
    DartType functionType = translator.getTearOffType(procedure);
    ClosureImplementation closure =
        translator.getTearOffClosure(procedure, b.module);
    w.StructType struct = closure.representation.closureStruct;

    ClassInfo info = translator.closureInfo;
    translator.functions.recordClassAllocation(info.classId);

    b.pushObjectHeaderFields(translator, info);
    b.local_get(paramLocals[0]); // `this` as context
    // The closure requires a struct value so box `this` if necessary.
    translator.convertType(b, paramLocals[0].type,
        struct.fields[FieldIndex.closureContext].type.unpacked);
    translator.globals.readGlobal(b, closure.vtable);
    types.makeType(this, functionType);
    b.struct_new(struct);
    b.end();
  }
}

class TypeCheckerCodeGenerator extends AstCodeGenerator {
  final Member member;

  TypeCheckerCodeGenerator(
      Translator translator, w.FunctionType functionType, this.member)
      : super(translator, functionType, member);

  @override
  void generateInternal() {
    // Initialize [Closures] without [Closures.captures]: Similar to
    // [TearOffCodeGenerator], type parameters will be loaded from the `this`
    // struct.
    closures = translator.getClosures(member, findCaptures: false);
    if (member is Field ||
        (member is Procedure && (member as Procedure).isSetter)) {
      _generateFieldSetterTypeCheckerMethod();
    } else {
      _generateProcedureTypeCheckerMethod();
    }
  }

  /// Generate type checker method for a method.
  ///
  /// This function will be called by an invocation forwarder in a dynamic
  /// invocation to type check parameters before calling the actual method.
  void _generateProcedureTypeCheckerMethod() {
    final receiverLocal = paramLocals[0];
    final typeArgsLocal = paramLocals[1];
    final positionalArgsLocal = paramLocals[2];
    final namedArgsLocal = paramLocals[3];

    _initializeThis(member.reference);

    final typeType =
        translator.classInfo[translator.typeClass]!.nonNullableType;

    final target =
        translator.getFunctionEntry(member.reference, uncheckedEntry: false);
    final targetParamInfo = translator.paramInfoForDirectCall(target);

    final procedure = member as Procedure;

    // Bind type parameters
    final memberTypeParams = procedure.function.typeParameters;
    assert(memberTypeParams.length == targetParamInfo.typeParamCount);

    if (memberTypeParams.isNotEmpty) {
      // Type argument list is either empty or have the right number of types
      // (checked by the forwarder).
      b.local_get(typeArgsLocal);
      b.array_len();
      b.i32_eqz();
      b.if_([], List.generate(memberTypeParams.length, (_) => typeType));
      // No type arguments passed, initialize with defaults
      for (final typeParam in memberTypeParams) {
        types.makeType(this, typeParam.defaultType);
      }
      b.else_();
      for (int typeParamIdx = 0;
          typeParamIdx < memberTypeParams.length;
          typeParamIdx += 1) {
        b.local_get(typeArgsLocal);
        b.i32_const(typeParamIdx);
        b.array_get(translator.typeArrayType);
      }
      b.end();

      // Create locals for type parameters. These will be used by `makeType`
      // below when generating types of parameters, for type checks, and when
      // pushing the type parameters when calling the actual member.
      for (int typeParamIdx = memberTypeParams.length - 1;
          typeParamIdx >= 0;
          typeParamIdx -= 1) {
        final local = addLocal(typeType);
        b.local_set(local);
        typeLocals[memberTypeParams[typeParamIdx]] = local;
      }
    }

    if (!translator.options.omitImplicitTypeChecks) {
      // Check type parameter bounds
      for (TypeParameter typeParameter in memberTypeParams) {
        if (typeParameter.bound != translator.coreTypes.objectNullableRawType) {
          _generateTypeArgumentBoundCheck(typeParameter.name!,
              typeLocals[typeParameter]!, typeParameter.bound);
        }
      }

      // Check positional argument types
      final List<VariableDeclaration> memberPositionalParams =
          procedure.function.positionalParameters;

      for (int positionalParamIdx = 0;
          positionalParamIdx < memberPositionalParams.length;
          positionalParamIdx += 1) {
        final param = memberPositionalParams[positionalParamIdx];
        b.local_get(positionalArgsLocal);
        b.i32_const(positionalParamIdx);
        b.array_get(translator.nullableObjectArrayType);
        _generateArgumentTypeCheck(param.name!, translator.topType, param.type);
      }

      // Check named argument types
      final memberNamedParams = procedure.function.namedParameters;

      /// Maps a named parameter in the member's signature to the parameter's
      /// index in the array [namedArgsLocal].
      int mapNamedParameterToArrayIndex(String name) {
        int? idx;
        for (int i = 0; i < targetParamInfo.names.length; i += 1) {
          if (targetParamInfo.names[i] == name) {
            idx = i;
            break;
          }
        }
        return idx!;
      }

      for (int namedParamIdx = 0;
          namedParamIdx < memberNamedParams.length;
          namedParamIdx += 1) {
        final param = memberNamedParams[namedParamIdx];
        b.local_get(namedArgsLocal);
        b.i32_const(mapNamedParameterToArrayIndex(param.name!));
        b.array_get(translator.nullableObjectArrayType);
        _generateArgumentTypeCheck(param.name!, translator.topType, param.type);
      }
    }

    // Argument types are as expected, call the member function
    final w.FunctionType memberWasmFunctionType =
        translator.signatureForDirectCall(target);
    final List<w.ValueType> memberWasmInputs = memberWasmFunctionType.inputs;

    b.local_get(receiverLocal);
    translator.convertType(b, receiverLocal.type, memberWasmInputs[0]);

    for (final typeParam in memberTypeParams) {
      b.local_get(typeLocals[typeParam]!);
    }

    int memberParamIdx =
        1 + targetParamInfo.typeParamCount; // skip receiver and type args

    void pushArgument(w.Local listLocal, int listIdx, int wasmInputIdx) {
      b.local_get(listLocal);
      b.i32_const(listIdx);
      b.array_get(translator.nullableObjectArrayType);
      translator.convertType(
          b, translator.topType, memberWasmInputs[wasmInputIdx]);
    }

    for (int positionalParamIdx = 0;
        positionalParamIdx < targetParamInfo.positional.length;
        positionalParamIdx += 1) {
      pushArgument(positionalArgsLocal, positionalParamIdx, memberParamIdx);
      memberParamIdx += 1;
    }

    for (int namedParamIdx = 0;
        namedParamIdx < targetParamInfo.names.length;
        namedParamIdx += 1) {
      pushArgument(namedArgsLocal, namedParamIdx, memberParamIdx);
      memberParamIdx += 1;
    }

    call(target);

    translator.convertType(
        b,
        translator.outputOrVoid(memberWasmFunctionType.outputs),
        translator.topType);

    b.return_();
    b.end();
  }

  /// Generate type checker method for a setter.
  ///
  /// This function will be called by a setter forwarder in a dynamic set to
  /// type check the setter argument before calling the actual setter.
  void _generateFieldSetterTypeCheckerMethod() {
    final receiverLocal = paramLocals[0];
    final positionalArgLocal = paramLocals[1];

    _initializeThis(member.reference);

    final member_ = member;
    DartType paramType;
    if (member_ is Field) {
      paramType = member_.type;
    } else {
      paramType = (member_ as Procedure).setterType;
    }

    if (!translator.options.omitImplicitTypeChecks) {
      b.local_get(positionalArgLocal);
      _generateArgumentTypeCheck(
        member.name.text,
        positionalArgLocal.type as w.RefType,
        paramType,
      );
    }

    ClassInfo info = translator.classInfo[member_.enclosingClass]!;
    if (member_ is Field) {
      int fieldIndex = translator.fieldIndex[member_]!;
      b.local_get(receiverLocal);
      translator.convertType(b, receiverLocal.type, info.nonNullableType);
      b.local_get(positionalArgLocal);
      translator.convertType(b, positionalArgLocal.type,
          info.struct.fields[fieldIndex].type.unpacked);
      b.struct_set(info.struct, fieldIndex);
    } else {
      final setterProcedure = member_ as Procedure;
      final target = translator.getFunctionEntry(setterProcedure.reference,
          uncheckedEntry: false);
      final setterProcedureWasmType = translator.signatureForDirectCall(target);
      final setterWasmInputs = setterProcedureWasmType.inputs;
      assert(setterWasmInputs.length == 2);
      b.local_get(receiverLocal);
      translator.convertType(b, receiverLocal.type, setterWasmInputs[0]);
      b.local_get(positionalArgLocal);
      translator.convertType(b, positionalArgLocal.type, setterWasmInputs[1]);
      call(target);
    }

    b.local_get(positionalArgLocal);
    b.end(); // end function
  }
}

class InitializerListCodeGenerator extends AstCodeGenerator {
  final Constructor member;

  InitializerListCodeGenerator(
      Translator translator, w.FunctionType functionType, this.member)
      : super(translator, functionType, member);

  @override
  void generateInternal() {
    // Closures are built when constructor functions are added to worklist.
    closures = translator.constructorClosures[member.reference]!;

    final source = member.enclosingComponent!.uriToSource[member.fileUri]!;
    setSourceMapSourceAndFileOffset(source, member.fileOffset);

    if (member.isExternal) {
      emitUnimplementedExternalError(member);
    } else {
      generateInitializerList();
    }
    b.end();
  }

  // Generates a constructor's initializer list method, and returns:
  // 1. Arguments and contexts returned from a super or redirecting initializer
  //    method (in reverse order).
  // 2. Arguments for this constructor (in reverse order).
  // 3. A reference to the context for this constructor (or null if there is no
  //    context).
  // 4. Class fields (including superclass fields, excluding class id and
  //    identity hash).
  void generateInitializerList() {
    _setupInitializerListParametersAndContexts();

    Class cls = member.enclosingClass;
    ClassInfo info = translator.classInfo[cls]!;

    List<w.Local> initializedFields = _generateInitializers(member);
    bool containsSuperInitializer = false;
    bool containsRedirectingInitializer = false;

    for (Initializer initializer in member.initializers) {
      if (initializer is SuperInitializer) {
        containsSuperInitializer = true;
      } else if (initializer is RedirectingInitializer) {
        containsRedirectingInitializer = true;
      }
    }

    if (cls.superclass != null && !containsRedirectingInitializer) {
      // checks if a SuperInitializer was dropped because the constructor body
      // throws an error
      if (!containsSuperInitializer) {
        b.unreachable();
        return;
      }

      // checks if a FieldInitializer was dropped because the constructor body
      // throws an error
      for (Field field in info.cls!.fields) {
        if (field.isInstanceMember && !fieldLocals.containsKey(field)) {
          b.unreachable();
          return;
        }
      }
    }

    // push constructor arguments
    List<w.Local> constructorArgs =
        _getConstructorArgumentLocals(member.reference, true);

    for (w.Local arg in constructorArgs) {
      b.local_get(arg);
    }

    // push reference to context
    Context? context = closures.contexts[member];
    if (context != null) {
      assert(!context.isEmpty);
      b.local_get(context.currentLocal);
    }

    // push initialized fields
    for (w.Local field in initializedFields) {
      b.local_get(field);
    }
  }

  void _setupInitializerListParametersAndContexts() {
    setupParameters(member.initializerReference, isForwarder: true);
    allocateContext(member);
    captureParameters();
  }

  List<w.Local> _generateInitializers(Constructor member) {
    Class cls = member.enclosingClass;
    ClassInfo info = translator.classInfo[cls]!;
    List<w.Local> superclassFields = [];

    _setupDefaultFieldValues(info);

    // Generate initializer list
    for (Initializer initializer in member.initializers) {
      visitInitializer(initializer);

      if (initializer is SuperInitializer) {
        // Save super classes' fields to locals
        ClassInfo superInfo = info.superInfo!;

        for (w.ValueType outputType
            in superInfo.getClassFieldTypes().reversed) {
          w.Local local = addLocal(outputType);
          b.local_set(local);
          superclassFields.add(local);
        }
      } else if (initializer is RedirectingInitializer) {
        // Save redirected classes' fields to locals
        List<w.Local> redirectedFields = [];

        for (w.ValueType outputType in info.getClassFieldTypes().reversed) {
          w.Local local = addLocal(outputType);
          b.local_set(local);
          redirectedFields.add(local);
        }

        return redirectedFields.reversed.toList();
      }
    }

    List<w.Local> typeFields = [];

    for (TypeParameter typeParam in cls.typeParameters) {
      TypeParameter? match = info.typeParameterMatch[typeParam];

      if (match == null) {
        // Type is not contained in super class' fields
        typeFields.add(typeLocals[typeParam]!);
      }
    }

    List<w.Local> orderedFieldLocals = Map.fromEntries(
            fieldLocals.entries.toList()
              ..sort((x, y) => translator.fieldIndex[x.key]!
                  .compareTo(translator.fieldIndex[y.key]!)))
        .values
        .toList();

    return superclassFields.reversed.toList() + typeFields + orderedFieldLocals;
  }
}

class ConstructorAllocatorCodeGenerator extends AstCodeGenerator {
  final Constructor member;

  ConstructorAllocatorCodeGenerator(
      Translator translator, w.FunctionType functionType, this.member)
      : super(translator, functionType, member);

  @override
  void generateInternal() {
    // Closures are built when constructor functions are added to worklist.
    closures = translator.constructorClosures[member.reference]!;

    final source = member.enclosingComponent!.uriToSource[member.fileUri]!;
    setSourceMapSourceAndFileOffset(source, member.fileOffset);

    generateConstructorAllocator();
  }

  // Generates a function for allocating an object. This calls the separate
  // initializer list and constructor body methods, and allocates a struct for
  // the object.
  void generateConstructorAllocator() {
    setupParameters(member.reference, isForwarder: true);

    w.FunctionType initializerMethodType =
        translator.signatureForDirectCall(member.initializerReference);

    List<w.Local> constructorArgs =
        _getConstructorArgumentLocals(member.reference);

    for (w.Local local in constructorArgs) {
      b.local_get(local);
    }

    b.comment("Direct call of '$member Initializer'");
    call(member.initializerReference);

    ClassInfo info = translator.classInfo[member.enclosingClass]!;

    // Add evaluated fields to locals
    List<w.Local> orderedFieldLocals = [];

    List<w.FieldType> fieldTypes = info.struct.fields
        .sublist(FieldIndex.objectFieldBase)
        .reversed
        .toList();

    for (w.FieldType field in fieldTypes) {
      w.Local local = addLocal(field.type.unpacked);
      orderedFieldLocals.add(local);
      b.local_set(local);
    }

    Context? context = closures.contexts[member];
    w.Local? contextLocal;

    bool hasContext = context != null;

    if (hasContext) {
      assert(!context.isEmpty);
      w.ValueType contextRef = w.RefType.struct(nullable: true);
      contextLocal = addLocal(contextRef);
      b.local_set(contextLocal);
    }

    List<w.ValueType> initializerOutputTypes = initializerMethodType.outputs;
    int numConstructorBodyArgs = initializerOutputTypes.length -
        fieldTypes.length -
        (hasContext ? 1 : 0);

    // Pop all arguments to constructor body
    List<w.ValueType> constructorArgTypes =
        initializerOutputTypes.sublist(0, numConstructorBodyArgs);

    List<w.Local> constructorArguments = [];

    for (w.ValueType argType in constructorArgTypes.reversed) {
      w.Local local = addLocal(argType);
      b.local_set(local);
      constructorArguments.add(local);
    }

    // Set field values
    b.pushObjectHeaderFields(translator, info);

    for (w.Local local in orderedFieldLocals.reversed) {
      b.local_get(local);
    }

    // create new struct with these fields and set to local
    w.Local temp = addLocal(info.nonNullableType);
    b.struct_new(info.struct);
    b.local_tee(temp);

    // Push context local if it is present
    if (contextLocal != null) {
      b.local_get(contextLocal);
    }

    // Push all constructor arguments
    for (w.Local constructorArg in constructorArguments) {
      b.local_get(constructorArg);
    }

    b.comment("Direct call of $member Constructor Body");
    call(member.constructorBodyReference);

    b.local_get(temp);
    b.end();
  }
}

class ConstructorCodeGenerator extends AstCodeGenerator {
  final Constructor member;

  ConstructorCodeGenerator(
      Translator translator, w.FunctionType functionType, this.member)
      : super(translator, functionType, member);

  @override
  void generateInternal() {
    // Closures are built when constructor functions are added to worklist.
    closures = translator.constructorClosures[member.reference]!;

    final source = member.enclosingComponent!.uriToSource[member.fileUri]!;
    setSourceMapSourceAndFileOffset(source, member.fileOffset);

    generateConstructorBody();
  }

  // Generates a function for a constructor's body, where the allocated struct
  // object is passed to this function.
  void generateConstructorBody() {
    _setupConstructorBodyParametersAndContexts();

    int getStartIndexForSuperOrRedirectedConstructorArguments() {
      // Skips the receiver param and the current constructor's context
      // (if it exists)
      Context? context = closures.contexts[member];
      bool hasContext = context != null;

      if (hasContext) {
        assert(!context.isEmpty);
      }

      int numSkippedParams = hasContext ? 2 : 1;

      // Skips the current constructor's arguments
      int numConstructorArgs =
          _getConstructorArgumentLocals(member.constructorBodyReference).length;

      return numSkippedParams + numConstructorArgs;
    }

    // Call super class' constructor body, or redirected constructor
    for (Initializer initializer in member.initializers) {
      if (initializer is SuperInitializer ||
          initializer is RedirectingInitializer) {
        Constructor target = initializer is SuperInitializer
            ? initializer.target
            : (initializer as RedirectingInitializer).target;

        Supertype? supersupertype = target.enclosingClass.supertype;

        if (supersupertype == null) {
          break;
        }

        int startIndex =
            getStartIndexForSuperOrRedirectedConstructorArguments();

        List<w.Local> superOrRedirectedConstructorArgs =
            paramLocals.sublist(startIndex);

        w.Local object = thisLocal!;
        b.local_get(object);

        for (w.Local local in superOrRedirectedConstructorArgs) {
          b.local_get(local);
        }

        call(target.constructorBodyReference);
        break;
      }
    }

    Statement? body = member.function.body;

    if (body != null) {
      translateStatement(body);
    }

    b.end();
  }

  void _setupConstructorBodyParametersAndContexts() {
    ParameterInfo paramInfo =
        translator.paramInfoForDirectCall(member.constructorBodyReference);

    // For constructor body functions, the first parameter is always the
    // receiver parameter, and the second parameter is a reference to the
    // current context (if it exists).
    Context? context = closures.contexts[member];
    bool hasConstructorContext = context != null;

    if (hasConstructorContext) {
      assert(!context.isEmpty);
      _initializeContextLocals(member, contextParamIndex: 1);
    }

    // Skips the receiver param (_initializeThis will return 1), and the
    // context param if this exists.
    int parameterOffset = _initializeThis(member.constructorBodyReference) +
        (hasConstructorContext ? 1 : 0);
    int implicitParams = parameterOffset + paramInfo.typeParamCount;

    _setupLocalParameters(member, paramInfo, parameterOffset, implicitParams);
    allocateContext(member.function);
  }
}

class StaticFieldInitializerCodeGenerator extends AstCodeGenerator {
  final Field field;

  StaticFieldInitializerCodeGenerator(
      Translator translator, w.FunctionType functionType, this.field)
      : super(translator, functionType, field);

  @override
  void generateInternal() {
    final source = field.enclosingComponent!.uriToSource[field.fileUri]!;
    setSourceMapSourceAndFileOffset(source, field.fileOffset);

    // Static field initializer function
    closures = translator.getClosures(field);

    w.Global global = translator.globals.getGlobalForStaticField(field);
    w.Global? flag = translator.globals.getGlobalInitializedFlag(field);
    translateExpression(field.initializer!, global.type.type);
    b.global_set(global);
    if (flag != null) {
      b.i32_const(1);
      b.global_set(flag);
    }
    b.global_get(global);
    translator.convertType(b, global.type.type, outputs.single);
    b.end();
  }
}

/// Will eagerly initialize a static field as part of the module's start
/// function.
class EagerStaticFieldInitializerCodeGenerator extends AstCodeGenerator {
  final Field field;
  final w.Global global;

  EagerStaticFieldInitializerCodeGenerator(
      Translator translator, this.field, this.global)
      : super(translator, w.FunctionType([], []), field);

  @override
  void generateInternal() {
    final source = field.enclosingComponent!.uriToSource[field.fileUri]!;
    setSourceMapSourceAndFileOffset(source, field.fileOffset);

    translateExpression(field.initializer!, global.type.type);
    b.global_set(global);
  }
}

class StaticFieldImplicitAccessorCodeGenerator extends AstCodeGenerator {
  final Field field;
  final bool isImplicitGetter;

  StaticFieldImplicitAccessorCodeGenerator(Translator translator,
      w.FunctionType functionType, this.field, this.isImplicitGetter)
      : super(translator, functionType, field);

  @override
  void generateInternal() {
    final global = translator.globals.getGlobalForStaticField(field);
    final flag = translator.globals.getGlobalInitializedFlag(field);
    if (isImplicitGetter) {
      final initFunction =
          translator.functions.getExistingFunction(field.fieldReference);
      _generateGetter(global, flag, initFunction);
    } else {
      _generateSetter(global, flag);
    }
    b.end();
  }

  void _generateGetter(
      w.Global global, w.Global? flag, w.BaseFunction? initFunction) {
    if (initFunction == null) {
      // Statically initialized
      b.global_get(global);
    } else {
      if (flag != null) {
        // Explicit initialization flag
        b.global_get(flag);
        b.if_(const [], [global.type.type]);
        b.global_get(global);
        b.else_();
        translator.callFunction(initFunction, b);
        b.end();
      } else {
        // Null signals uninitialized
        w.Label block = b.block(const [], [initFunction.type.outputs.single]);
        b.global_get(global);
        b.br_on_non_null(block);
        translator.callFunction(initFunction, b);
        b.end();
      }
    }
  }

  void _generateSetter(w.Global global, w.Global? flag) {
    b.local_get(paramLocals.single);
    b.global_set(global);
    if (flag != null) {
      b.i32_const(1); // true
      b.global_set(flag);
    }
  }
}

class ImplicitFieldAccessorCodeGenerator extends AstCodeGenerator {
  final Field field;
  final bool isImplicitGetter;
  final bool useUncheckedEntry;

  ImplicitFieldAccessorCodeGenerator(
    Translator translator,
    w.FunctionType functionType,
    this.field,
    this.isImplicitGetter,
    this.useUncheckedEntry,
  ) : super(translator, functionType, field);

  @override
  void generateInternal() {
    thisLocal = preciseThisLocal = paramLocals[0];

    // Conceptually not needed for implicit accessors, but currently the code
    // that instantiates types uses closure information to see whether a type
    // parameter was captured (and loads it from context chain) or not (and
    // loads it directly from `this`).
    closures = translator.getClosures(field, findCaptures: false);

    final source = field.enclosingComponent!.uriToSource[field.fileUri]!;
    setSourceMapSourceAndFileOffset(source, field.fileOffset);

    // Implicit getter or setter
    w.StructType struct = translator.classInfo[field.enclosingClass!]!.struct;
    w.RefType structType = w.RefType.def(struct, nullable: false);
    int fieldIndex = translator.fieldIndex[field]!;
    w.ValueType fieldType = struct.fields[fieldIndex].type.unpacked;

    void getThis() {
      w.Local thisLocal = paramLocals[0];
      b.local_get(thisLocal);
      translator.convertType(b, thisLocal.type, structType);
    }

    if (isImplicitGetter) {
      // Implicit getter
      getThis();
      b.struct_get(struct, fieldIndex);
      translator.convertType(b, fieldType, returnType);
    } else {
      // Implicit setter
      w.Local valueLocal = paramLocals[1];
      getThis();

      if (translator.needToCheckTypesFor(field) &&
          translator.needToCheckImplicitSetterValue(field,
              uncheckedEntry: useUncheckedEntry)) {
        final boxedType = field.type.isPotentiallyNullable
            ? translator.topType
            : translator.topTypeNonNullable;
        w.Local operand = valueLocal;
        if (!operand.type.isSubtypeOf(boxedType)) {
          final boxedOperand = addLocal(boxedType);
          b.local_get(operand);
          translator.convertType(b, operand.type, boxedOperand.type);
          b.local_set(boxedOperand);
          operand = boxedOperand;
        }
        b.local_get(operand);
        _generateArgumentTypeCheck(
          field.name.text,
          operand.type as w.RefType,
          field.type,
        );
      }

      b.local_get(valueLocal);
      translator.convertType(b, valueLocal.type, fieldType);
      b.struct_set(struct, fieldIndex);
      assert(functionType.outputs.isEmpty);
    }
    b.end();
  }
}

class SynchronousLambdaCodeGenerator extends AstCodeGenerator {
  final Lambda lambda;
  final Closures enclosingMemberClosures;

  SynchronousLambdaCodeGenerator(Translator translator, Member enclosingMember,
      this.lambda, this.enclosingMemberClosures)
      : super(translator, lambda.function.type, enclosingMember);

  @override
  void generateInternal() {
    closures = enclosingMemberClosures;

    setSourceMapSource(lambda.functionNodeSource);

    assert(lambda.functionNode.asyncMarker != AsyncMarker.Async);

    setupLambdaParametersAndContexts(lambda);

    translateStatement(lambda.functionNode.body!);
    _implicitReturn();
    b.end();
  }
}

class TryBlockFinalizer {
  /// `br` target to run the finalizer
  final w.Label label;

  /// Whether the last finalizer in the chain should return. When this is
  /// `false` the block won't be used, as the block is for running finalizers
  /// when returning.
  bool mustHandleReturn = false;

  TryBlockFinalizer(this.label);
}

/// Holds information of a switch statement, to be used when doing a backward
/// jump to it
class SwitchBackwardJumpInfo {
  /// Wasm local for the value of the switched expression. For example, in a
  /// `switch` like:
  ///
  /// ```
  /// switch (expr) {
  ///   ...
  /// }
  /// ```
  ///
  /// This local holds the value of `expr`.
  ///
  /// This local is updated with a new value when doing backward jumps.
  final w.Local switchValueLocal;

  /// Label of the `loop` to use when doing backward jumps
  final w.Label loopLabel;

  /// When compiling a `default` case, label of the `loop` in the case body, to
  /// use when doing backward jumps to the same case.
  w.Label? defaultLoopLabel;

  SwitchBackwardJumpInfo(this.switchValueLocal, this.loopLabel)
      : defaultLoopLabel = null;
}

/// Info needed to represent a switch statement using a br_table instruction.
///
/// This is used for switches on integers and enums (using their indicies). We
/// map each option to an index in the jump table and then jump directly to the
/// target case. This is much faster than iteratively comparing each cases's
/// expression to the switch expression.
///
/// Sometimes switches over ranges of ints are sparse enough that a table would
/// bloat the code compared to the iterative comparison.
class BrTableInfo {
  // At least 50% of the [min, max] must be occupied for us to use `br_table`.
  static const double _minimumTableOccupancy = 0.5;
  // This is the maximum size where it's always worth it to use a br_table.
  // If the br_table is bigger than this then we start to check sparseness.
  // Below this point we always accept the potential code size hit.
  static const int _maxSparseSize = 50;

  int get rangeSize => _rangeSize(minValue, maxValue);
  final int minValue;
  final int maxValue;
  final void Function(w.Local switchExprLocal) _brTableExpr;
  final Map<int, SwitchCase> caseMap;

  BrTableInfo._(this.minValue, this.maxValue, this.caseMap, this._brTableExpr)
      : assert(!_isTooSparse(minValue, maxValue, caseMap));

  /// Heuristically validate whether the provided table would be too sparse and
  /// if so return null. Otherwise return the expected table.
  static BrTableInfo? build(Map<int, SwitchCase> caseMap,
      void Function(w.Local switchExprLocal) brTableExpr,
      {required int minValue, required int maxValue}) {
    // Validate the table density and size is worth putting into a br_table.
    if (_isTooSparse(minValue, maxValue, caseMap)) return null;

    return BrTableInfo._(minValue, maxValue, caseMap, brTableExpr);
  }

  static bool _isTooSparse(int min, int max, Map<int, SwitchCase> caseMap) {
    int rangeSize = _rangeSize(min, max);
    return (caseMap.length / rangeSize) < _minimumTableOccupancy &&
        rangeSize > _maxSparseSize;
  }

  static int _rangeSize(int min, int max) => max - min + 1;

  void emitBrTableExpr(w.InstructionsBuilder b, w.Local switchExprLocal) {
    _brTableExpr(switchExprLocal);
    // Normalize on 0.
    if (minValue != 0) {
      b.i64_const(minValue);
      b.i64_sub();
    }
    // Now that we've normalized on 0 it should be safe to switch to i32.
    b.i32_wrap_i64();
  }
}

class SwitchInfo {
  /// Non-nullable Wasm type of the `switch` expression. Used when the
  /// expression is not nullable, and after the null check.
  late final w.ValueType nullableType;

  /// Nullable Wasm type of the `switch` expression. Only used when the
  /// expression is nullable.
  late final w.ValueType nonNullableType;

  /// Generates code that will br on [successLabel] if [switchExprLocal] has the
  /// correct type for the case checks on this switch. Only set for switches
  /// where the switch expression is dynamic.
  void Function(w.Local switchExprLocal, w.Label successLabel)?
      dynamicTypeGuard;

  /// Generates code that compares value of a `case` expression with the
  /// `switch` expression's value. Calls [pushCaseExpr] once.
  late final void Function(
      w.Local switchExprLocal, w.ValueType Function() pushCaseExpr) compare;

  /// The `default: ...` case, if exists.
  late final SwitchCase? defaultCase;

  /// The `null: ...` case, if exists.
  late final SwitchCase? nullCase;

  /// Info needed to compile this switch statement into a wasm br_table. If null
  /// this switch statement should not use a br_table and should use comparison
  /// based case matching instead.
  BrTableInfo? brTable;

  SwitchInfo(AstCodeGenerator codeGen, SwitchStatement node) {
    final translator = codeGen.translator;

    final switchExprType = codeGen.dartTypeOf(node.expression);

    final switchExprClass = translator.classForType(switchExprType);

    bool check<L extends Expression, C extends Constant>() =>
        node.cases.expand((c) => c.expressions).every((e) =>
            e is L ||
            e is NullLiteral ||
            (e is ConstantExpression &&
                ((e.constant is C &&
                        (translator.hierarchy.isSubInterfaceOf(
                            translator.classForType(codeGen.dartTypeOf(e)),
                            switchExprClass))) ||
                    e.constant is NullConstant)));

    // Type objects should be compared using `==` rather than identity even
    // though the specification is not very clear about it. In language versions
    // >=3.0 CFE would desugar such switches to a sequence of `if` statements
    // using `==`, but for language versions <3.0 it would simply emit
    // `SwitchStatement` and expect back-end to handle types specially if
    // required. See #60375 for more details.
    bool canInvokeTypeEquality() =>
        translator.typeEnvironment.isSubtypeOf(
            switchExprType, translator.coreTypes.typeNullableRawType) ||
        node.cases.expand((c) => c.expressions).any((e) =>
            translator.typeEnvironment.isSubtypeOf(codeGen.dartTypeOf(e),
                translator.coreTypes.typeNonNullableRawType));

    if (node.cases.every((c) =>
        c.expressions.isEmpty && c.isDefault ||
        c.expressions.every((e) =>
            e is NullLiteral ||
            e is ConstantExpression && e.constant is NullConstant))) {
      // default-only switch
      nonNullableType = w.RefType.eq(nullable: false);
      nullableType = w.RefType.eq(nullable: true);
      compare = (switchExprLocal, pushCaseExpr) =>
          throw "Comparison in default-only switch";
    } else if (canInvokeTypeEquality()) {
      nonNullableType = translator.runtimeTypeType;
      nullableType = translator.runtimeTypeTypeNullable;
      compare = (switchExprLocal, pushCaseExpr) {
        // Virtual call to `Type.==`.
        codeGen._virtualCall(
            node, translator.coreTypes.objectEquals, _VirtualCallKind.Call,
            (functionType) {
          codeGen.b.local_get(switchExprLocal);
        }, (functionType, paramInfo) {
          pushCaseExpr();
        }, useUncheckedEntry: false);
      };
    } else if (switchExprType is DynamicType) {
      // Per spec, compare with `<case expr> == <switch expr>`. For performance,
      // if we know that the cases all have the same type, we call the case
      // expression's `==` implementation directly (instead of virtually calling
      // `Object.==`).
      //
      // Note: this could be improved by directly calling a different `==` in
      // each of the cases based on the case value. For now we only directly
      // call a `==` if all of the cases have a compatible type.
      nonNullableType = translator.topTypeNonNullable;
      nullableType = translator.topType;
      final Member equalsMember;
      if (check<BoolLiteral, BoolConstant>()) {
        equalsMember = translator.boxedBoolEquals;
      } else if (check<IntLiteral, IntConstant>()) {
        equalsMember = translator.boxedIntEquals;
      } else if (check<StringLiteral, StringConstant>()) {
        equalsMember = translator.jsStringEquals;
      } else {
        compare = (switchExprLocal, pushCaseExpr) {
          // Virtual call to `Object.==`.
          codeGen._virtualCall(node, codeGen.translator.coreTypes.objectEquals,
              _VirtualCallKind.Call, (functionType) {
            codeGen.b.local_get(switchExprLocal);
          }, (functionType, paramInfo) {
            pushCaseExpr();
          }, useUncheckedEntry: false);
        };
        _initializeSpecialCases(node);
        return;
      }

      final equalsMemberSignature =
          translator.signatureForDirectCall(equalsMember.reference);

      // Per spec, `==` can't have type, or extra (optional) positional and
      // named arguments. So we don't have to check `ParamInfo` for it and
      // add missing optional parameters.
      assert(equalsMemberSignature.inputs.length == 2);

      dynamicTypeGuard = (switchExprLocal, successLabel) {
        codeGen.b.local_get(switchExprLocal);
        codeGen.b.br_on_cast(
            successLabel,
            switchExprLocal.type as w.RefType,
            equalsMemberSignature.inputs[0]
                .withNullability(switchExprLocal.type.nullable) as w.RefType);
        codeGen.b.drop();
      };

      compare = (switchExprLocal, pushCaseExpr) {
        final caseExprType = pushCaseExpr();
        translator.convertType(
            codeGen.b, caseExprType, equalsMemberSignature.inputs[0]);

        codeGen.b.local_get(switchExprLocal);
        translator.convertType(
            codeGen.b, switchExprLocal.type, equalsMemberSignature.inputs[1]);

        codeGen.call(equalsMember.reference);
      };
    } else if (check<BoolLiteral, BoolConstant>()) {
      // bool switch
      nonNullableType = w.NumType.i32;
      nullableType =
          translator.classInfo[translator.boxedBoolClass]!.nullableType;
      compare = (switchExprLocal, pushCaseExpr) {
        codeGen.b.local_get(switchExprLocal);
        pushCaseExpr();
        codeGen.b.i32_eq();
      };
    } else if (check<IntLiteral, IntConstant>()) {
      // int switch
      nonNullableType = w.NumType.i64;
      nullableType =
          translator.classInfo[translator.boxedIntClass]!.nullableType;

      // Calculate the range covered by the cases and create the jump table.
      int? minValue;
      int? maxValue;
      Map<int, SwitchCase> caseMap = {};
      for (final c in node.cases) {
        for (final e in c.expressions) {
          final value = e is IntLiteral
              ? e.value
              : ((e as ConstantExpression).constant as IntConstant).value;
          caseMap[value] = c;
          if (minValue == null || value < minValue) minValue = value;
          if (maxValue == null || value > maxValue) maxValue = value;
        }
      }
      if (maxValue != null) {
        brTable = BrTableInfo.build(
            minValue: minValue!,
            maxValue: maxValue,
            caseMap, (switchExprLocal) {
          codeGen.b.local_get(switchExprLocal);
        });
      }

      // Provide a compare as a fallback in case the range is too sparse.
      compare = (switchExprLocal, pushCaseExpr) {
        codeGen.b.local_get(switchExprLocal);
        pushCaseExpr();
        codeGen.b.i64_eq();
      };
    } else if (check<StringLiteral, StringConstant>()) {
      // String switch
      nonNullableType = translator.stringType;
      nullableType = translator.stringTypeNullable;
      compare = (switchExprLocal, pushCaseExpr) {
        codeGen.b.local_get(switchExprLocal);
        pushCaseExpr();
        codeGen.call(translator.jsStringEquals.reference);
      };
    } else if (switchExprClass.isEnum) {
      // If this is an applicable switch over enums, create a jump table.
      bool isValid = true;
      var caseMap = <int, SwitchCase>{};
      int? minIndex;
      int? maxIndex;
      outer:
      for (final c in node.cases) {
        for (final e in c.expressions) {
          if (e is! ConstantExpression) {
            isValid = false;
            break outer;
          }
          final constant = e.constant;
          if (constant is! InstanceConstant) {
            isValid = false;
            break outer;
          }
          if (constant.classNode != switchExprClass) {
            isValid = false;
            break outer;
          }
          final enumIndex =
              (constant.fieldValues[translator.enumIndexField.fieldReference]
                      as IntConstant)
                  .value;
          caseMap[enumIndex] = c;
          if (maxIndex == null || enumIndex > maxIndex) maxIndex = enumIndex;
          if (minIndex == null || enumIndex < minIndex) minIndex = enumIndex;
        }
      }

      if (isValid && maxIndex != null) {
        brTable = BrTableInfo.build(
            minValue: minIndex!,
            maxValue: maxIndex,
            caseMap, (switchExprLocal) {
          codeGen.b.local_get(switchExprLocal);
          codeGen.call(translator.enumIndexField.getterReference);
        });
      }

      if (brTable == null) {
        // Object identity switch
        nonNullableType = translator.topTypeNonNullable;
        nullableType = translator.topType;
      } else {
        nonNullableType =
            translator.classInfo[switchExprClass]!.nonNullableType;
        nullableType = translator.classInfo[switchExprClass]!.nullableType;
      }

      // Set compare anyway for state machine handling
      compare = (switchExprLocal, pushCaseExpr) {
        codeGen.b.local_get(switchExprLocal);
        pushCaseExpr();
        codeGen.call(translator.coreTypes.identicalProcedure.reference);
      };
    } else {
      // Object identity switch
      nonNullableType = translator.topTypeNonNullable;
      nullableType = translator.topType;
      compare = (switchExprLocal, pushCaseExpr) {
        codeGen.b.local_get(switchExprLocal);
        pushCaseExpr();
        codeGen.call(translator.coreTypes.identicalProcedure.reference);
      };
    }

    _initializeSpecialCases(node);
  }

  void _initializeSpecialCases(SwitchStatement node) {
    // Special cases
    defaultCase = node.cases
        .cast<SwitchCase?>()
        .firstWhere((c) => c!.isDefault, orElse: () => null);

    nullCase = node.cases.cast<SwitchCase?>().firstWhere(
        (c) => c!.expressions.any((e) =>
            e is NullLiteral ||
            e is ConstantExpression && e.constant is NullConstant),
        orElse: () => null);
  }
}

enum _VirtualCallKind {
  Get,
  Set,
  Call;

  @override
  String toString() {
    return switch (this) {
      _VirtualCallKind.Get => "get",
      _VirtualCallKind.Set => "set",
      _VirtualCallKind.Call => "call"
    };
  }

  bool get isGetter => this == _VirtualCallKind.Get;

  bool get isSetter => this == _VirtualCallKind.Set;
}

extension MacroAssembler on w.InstructionsBuilder {
  /// If the given [outputs] of a call contain bottom types then we will emit an
  /// `unreachable` instruction.
  ///
  /// This can help wasm compilers / wasm runtimes to optimize things more as
  /// they know control flow has ended here.
  List<w.ValueType> emitUnreachableIfNoResult(List<w.ValueType> outputs) {
    for (int i = 0; i < outputs.length; ++i) {
      final output = outputs[i];
      if (output is w.RefType &&
          output.heapType == w.HeapType.none &&
          !output.nullable) {
        unreachable();
        break;
      }
    }
    return outputs;
  }

  void incrementingLoop(
      {required void Function() pushStart,
      required void Function() pushLimit,
      required void Function(w.Local) genBody,
      int step = 1}) {
    final endLoop = block();
    final limitVar = addLocal(w.NumType.i32);
    final loopVar = addLocal(w.NumType.i32);
    pushLimit();
    local_set(limitVar);
    pushStart();
    local_set(loopVar);

    final loopLabel = loop();
    local_get(loopVar);
    local_get(limitVar);
    i32_ge_u();
    br_if(endLoop);

    genBody(loopVar);
    local_get(loopVar);
    i32_const(step);
    i32_add();
    local_set(loopVar);
    br(loopLabel);
    end();
    end();
  }

  /// [ref Array] [ref Array] -> [ref Array]
  ///
  /// Takes the two arrays on the stack and concatenates them into a single
  /// array. They both must have the same type provided as [arrayRefType].
  /// Uses [pushDefaultElement] as the filler element that holds space in the
  /// array until values are copied over.
  void concatenateWasmArrays(w.ArrayType arrayType,
      {required void Function(
              w.InstructionsBuilder b, w.Local oldArray, w.Local newArray)
          pushDefaultElement}) {
    final arrayRefType = w.RefType(arrayType, nullable: false);
    final newArray = addLocal(arrayRefType);
    final oldArray = addLocal(arrayRefType);
    final newArrayLen = addLocal(w.NumType.i32);
    final oldArrayLen = addLocal(w.NumType.i32);
    final joinedArray = addLocal(arrayRefType);

    local_set(newArray);
    local_set(oldArray);
    pushDefaultElement(this, oldArray, newArray);
    local_get(newArray);
    array_len();
    local_set(newArrayLen);
    local_get(oldArray);
    array_len();
    local_tee(oldArrayLen);
    local_get(newArrayLen);
    i32_add();
    array_new(arrayType);
    local_tee(joinedArray);
    i32_const(0);
    local_get(oldArray);
    i32_const(0);
    local_get(oldArrayLen);
    array_copy(arrayType, arrayType);
    local_get(joinedArray);
    local_get(oldArrayLen);
    local_get(newArray);
    i32_const(0);
    local_get(newArrayLen);
    array_copy(arrayType, arrayType);
    local_get(joinedArray);
    end();
  }

  /// `[i32] -> [i32]`
  ///
  /// Consumes a `i32` class ID, leaves an `i32` as `bool` for whether
  /// the class ID is in the given list of ranges.
  void emitClassIdRangeCheck(List<Range> ranges) {
    final rangeValues = ranges.map((r) => (range: r, value: null)).toList();
    classIdSearch<Null>(rangeValues, [w.NumType.i32], (_) {
      i32_const(1);
    }, () {
      i32_const(0);
    });
  }

  /// `[i32] -> [outputs]`
  ///
  /// Consumes a `i32` class ID and checks whether it lies within one of the
  /// given [ranges] using a linear or binary search.
  ///
  /// The [ranges] have to be non-empty, non-overlapping and sorted.
  ///
  /// Calls [match] on a matching value and [miss] if provided and no match was
  /// found.
  ///
  /// Assumes [match] and [miss] leave [outputs] on the stack.
  void classIdSearch<T>(
      List<({Range range, T value})> ranges,
      List<w.ValueType> outputs,
      void Function(T) match,
      void Function()? miss) {
    final bool linearSearch = ranges.length <= 3;
    if (traceEnabled) {
      comment('Class id ${linearSearch ? 'linear' : 'binary'} search:');
      for (final (:range, :value) in ranges) {
        comment('  - $range -> $value');
      }
    }
    if (linearSearch) {
      _linearClassIdSearch<T>(ranges, outputs, match, miss);
    } else {
      _binaryClassIdSearch<T>(ranges, outputs, match, miss);
    }
  }

  void _binaryClassIdSearch<T>(
      List<({Range range, T value})> ranges,
      List<w.ValueType> outputs,
      void Function(T) match,
      void Function()? miss) {
    assert(ranges.isNotEmpty || miss != null);
    if (miss != null && ranges.isEmpty) {
      drop();
      miss();
      return;
    }

    w.Local classId = addLocal(w.NumType.i32);
    local_set(classId);

    final done = block([], outputs);
    final fail = block();
    void search(int left, int right, Range searchArea) {
      if (left == right) {
        final entry = ranges[left];
        final range = entry.range;
        assert(searchArea.containsRange(range));
        if (miss == null || range.containsRange(searchArea)) {
          match(entry.value);
          br(done);
          return;
        }
        local_get(classId);
        if (range.length == 1) {
          i32_const(range.start);
          i32_eq();
        } else {
          if (searchArea.end <= range.end) {
            i32_const(range.start);
            i32_ge_u();
          } else if (range.start <= searchArea.start) {
            i32_const(range.end);
            i32_le_u();
          } else {
            i32_const(range.start);
            i32_sub();
            i32_const(range.length);
            i32_lt_u();
          }
        }
        if_();
        match(entry.value);
        br(done);
        end();
        br(fail);
        return;
      }
      final mid = (left + right) ~/ 2;
      final midRange = ranges[mid].range;

      local_get(classId);
      i32_const(midRange.end);
      i32_le_u();
      if_();
      search(left, mid, Range(searchArea.start, midRange.end));
      end();
      search(mid + 1, right, Range(midRange.end + 1, searchArea.end));
    }

    search(0, ranges.length - 1, Range(0, 0xffffffff));
    end(); // fail
    if (miss != null) {
      miss();
      br(done);
    } else {
      unreachable();
    }
    end(); // done
  }

  void _linearClassIdSearch<T>(
      List<({Range range, T value})> ranges,
      List<w.ValueType> outputs,
      void Function(T) match,
      void Function()? miss) {
    assert(ranges.isNotEmpty || miss != null);
    if (miss != null && ranges.isEmpty) {
      drop();
      miss();
      return;
    }

    w.Local classId = addLocal(w.NumType.i32);
    local_set(classId);
    final done = block([], outputs);
    for (final (:range, :value) in ranges) {
      local_get(classId);
      i32_const(range.start);
      if (range.length == 1) {
        i32_eq();
      } else {
        i32_sub();
        i32_const(range.length);
        i32_lt_u();
      }
      if_();
      match(value);
      br(done);
      end();
    }
    if (miss != null) {
      miss();
      br(done);
    } else {
      unreachable();
    }
    end(); // done
  }

  /// `[ref _Closure] -> [i32]`
  ///
  /// Given a closure reference returns whether the closure is an
  /// instantiation.
  void emitInstantiationClosureCheck(Translator translator) {
    ref_cast(w.RefType(translator.closureLayouter.closureBaseStruct,
        nullable: false));
    struct_get(translator.closureLayouter.closureBaseStruct,
        FieldIndex.closureContext);
    ref_test(w.RefType(
        translator.closureLayouter.instantiationContextBaseStruct,
        nullable: false));
  }

  /// `[ref _Closure] -> [ref #ClosureBase]`
  ///
  /// Given an instantiation closure returns the instantiated closure.
  void emitGetInstantiatedClosure(Translator translator) {
    // instantiation.context
    ref_cast(w.RefType(translator.closureLayouter.closureBaseStruct,
        nullable: false));
    struct_get(translator.closureLayouter.closureBaseStruct,
        FieldIndex.closureContext);

    // instantiation.context.inner
    ref_cast(w.RefType(
        translator.closureLayouter.instantiationContextBaseStruct,
        nullable: false));
    struct_get(translator.closureLayouter.instantiationContextBaseStruct,
        FieldIndex.instantiationContextInner);
  }

  /// `[ref _Closure] -> [i32]`
  ///
  /// Given a closure returns whether the closure is a tear-off.
  void emitTearOffCheck(Translator translator) {
    ref_cast(w.RefType(translator.closureLayouter.closureBaseStruct,
        nullable: false));
    struct_get(translator.closureLayouter.closureBaseStruct,
        FieldIndex.closureContext);
    ref_test(translator.topTypeNonNullable);
  }

  /// `[ref _Closure] -> [ref #Top]`
  ///
  /// Given a closure returns the receiver of the closure.
  void emitGetTearOffReceiver(Translator translator) {
    ref_cast(w.RefType(translator.closureLayouter.closureBaseStruct,
        nullable: false));
    struct_get(translator.closureLayouter.closureBaseStruct,
        FieldIndex.closureContext);
    ref_cast(translator.topTypeNonNullable);
  }

  /// `[ref _Closure] -> [ref Any]
  ///
  /// Given a closure returns the vtable of the closure.
  void emitGetClosureVtable(Translator translator) {
    ref_cast(w.RefType(translator.closureLayouter.closureBaseStruct,
        nullable: false));
    struct_get(
        translator.closureLayouter.closureBaseStruct, FieldIndex.closureVtable);
  }

  /// Will restore all context locals and `this` from a suspend state.
  void restoreSuspendStateContext(
      w.Local suspendStateLocal,
      w.StructType suspendStateStruct,
      int suspendStateContextField,
      Closures closures,
      Context? context,
      w.Local? thisLocal,
      {FunctionNode? cloneContextFor}) {
    if (context != null) {
      assert(!context.isEmpty);
      local_get(suspendStateLocal);
      struct_get(suspendStateStruct, suspendStateContextField);
      ref_cast(context.currentLocal.type as w.RefType);
      local_set(context.currentLocal);
      if (context.owner == cloneContextFor) {
        context.currentLocal =
            cloneFunctionLevelContext(closures, context, cloneContextFor!);
      }
      restoreThisAndContextChain(context, thisLocal);
    }
  }

  /// Will restore the parent context chain and `this` (if captured)
  ///
  /// Assumes the innermost context is already loaded.
  void restoreThisAndContextChain(
      Context innermostContext, w.Local? thisLocal) {
    bool restoredThis = false;

    Context? context = innermostContext;
    while (context != null) {
      if (context.containsThis) {
        assert(!restoredThis);
        local_get(context.currentLocal);
        struct_get(context.struct, context.thisFieldIndex);
        ref_as_non_null();
        local_set(thisLocal!);
        restoredThis = true;
      }

      final parent = context.parent;
      if (parent != null) {
        assert(!parent.isEmpty);
        local_get(context.currentLocal);
        struct_get(context.struct, context.parentFieldIndex);
        ref_as_non_null();
        local_set(parent.currentLocal);
      }
      context = parent;
    }
  }

  /// Clones the [context] and returns a local to the clone it.
  ///
  /// It is assumed that the context is a function-level context.
  w.Local cloneFunctionLevelContext(
      Closures closures, Context context, FunctionNode functionNode) {
    final w.Local srcContext = context.currentLocal;
    final w.Local destContext = addLocal(context.currentLocal.type);

    struct_new_default(context.struct);
    local_set(destContext);

    void copyCapture(TreeNode node) {
      Capture? capture = closures.captures[node];
      if (capture != null) {
        assert(capture.context == context);
        local_get(destContext);
        local_get(srcContext);
        struct_get(context.struct, capture.fieldIndex);
        struct_set(context.struct, capture.fieldIndex);
      }
    }

    if (context.containsThis) {
      local_get(destContext);
      local_get(srcContext);
      struct_get(context.struct, context.thisFieldIndex);
      struct_set(context.struct, context.thisFieldIndex);
    }
    if (context.parent != null) {
      local_get(destContext);
      local_get(srcContext);
      struct_get(context.struct, context.parentFieldIndex);
      struct_set(context.struct, context.parentFieldIndex);
    }
    functionNode.positionalParameters.forEach(copyCapture);
    functionNode.namedParameters.forEach(copyCapture);
    functionNode.typeParameters.forEach(copyCapture);

    return destContext;
  }

  List<w.ValueType> invoke(CallTarget target, {bool forceInline = false}) {
    if (target.supportsInlining && (target.shouldInline || forceInline)) {
      final List<w.Local> inlinedLocals =
          target.signature.inputs.map((t) => addLocal(t)).toList();
      for (w.Local local in inlinedLocals.reversed) {
        local_set(local);
      }
      final w.Label callBlock = block(const [], target.signature.outputs);
      comment('Inlined ${target.name}');
      target.inliningCodeGen.generate(this, inlinedLocals, callBlock);
    } else {
      comment('Direct call to ${target.name}');
      call(target.function);
    }
    return emitUnreachableIfNoResult(target.signature.outputs);
  }

  /// Pushes fields common to all Dart objects (class id, id hash).
  void pushObjectHeaderFields(Translator translator, ClassInfo classInfo) {
    pushClassIdToStack(translator, classInfo.classId);
    i32_const(initialIdentityHash);
  }

  void pushClassIdToStack(Translator translator, ClassId classId) {
    switch (classId) {
      case AbsoluteClassId():
        i32_const(classId.value);
      case RelativeClassId():
        i32_const(classId.relativeValue);
        translator.pushModuleId(this);
        translator.callReference(translator.globalizeClassId.reference, this);
    }
  }

  void loadClassId(Translator translator, w.ValueType receiverType) {
    assert(!receiverType.nullable);
    assert(receiverType.isSubtypeOf(translator.topTypeNonNullable));
    struct_get(
        translator.classInfoCollector.topInfo.struct, FieldIndex.classId);
  }
}

/// A call target that may be called with a direct call or may be inlined.
abstract class CallTarget {
  /// The wasm signature of the call target (that may be called or inlined).
  final w.FunctionType signature;

  CallTarget(this.signature);

  /// Whether this call target supports inlining.
  bool get supportsInlining => false;

  /// Whether we should inline (different call targets may have semantic
  /// knowledge about how big the body would be and whether we should inline or
  /// not).
  bool get shouldInline => false;

  /// The code generator to use for inlining the body.
  CodeGenerator get inliningCodeGen => throw 'No inlining support (yet).';

  /// The name of this target
  ///
  /// The inliner can use this to emit comments for the inlined target.
  String get name;

  /// The wasm target function to call.
  ///
  /// This should only be accessed if caller intents to call it, as it will
  /// enqueue the function in the compilation queue.
  w.BaseFunction get function;
}

class AstCallTarget extends CallTarget {
  final Translator _translator;
  final Reference _reference;

  AstCallTarget(super.signature, this._translator, this._reference);

  @override
  String get name => _translator.functions.getFunctionName(_reference);

  @override
  bool get supportsInlining => _translator.supportsInlining(_reference);

  @override
  bool get shouldInline => _translator.shouldInline(_reference, signature);

  @override
  CodeGenerator get inliningCodeGen => getInlinableMemberCodeGenerator(
      _translator, AsyncMarker.Sync, signature, _reference)!;

  @override
  w.BaseFunction get function => _translator.functions.getFunction(_reference);
}

bool guardCanMatchJSException(Translator translator, DartType guard) {
  if (guard is DynamicType) {
    return true;
  }
  if (guard is InterfaceType) {
    return translator.hierarchy
        .isSubInterfaceOf(translator.javaScriptErrorClass, guard.classNode);
  }
  if (guard is TypeParameterType) {
    return guardCanMatchJSException(translator, guard.bound);
  }
  return false;
}
