// 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:typed_data';

import 'package:kernel/ast.dart';
import 'package:kernel/type_algebra.dart'
    show FunctionTypeInstantiator, substitute;
import 'package:wasm_builder/wasm_builder.dart' as w;

import 'class_info.dart';
import 'closures.dart';
import 'param_info.dart';
import 'translator.dart';
import 'types.dart';

const int maxArrayNewFixedLength = 10000;

class ConstantInfo {
  final Constant constant;
  final w.Global global;
  final w.BaseFunction? function;

  ConstantInfo(this.constant, this.global, this.function);

  bool get isLazy => function != null;
}

typedef ConstantCodeGenerator = void Function(
    w.FunctionBuilder?, w.InstructionsBuilder);

/// Handles the creation of Dart constants.
///
/// Each (non-trivial) constant is assigned to a Wasm global. Multiple
/// occurrences of the same constant use the same global.
///
/// When possible, the constant is contained within the global initializer,
/// meaning the constant is initialized eagerly during module initialization.
/// If this would exceed built-in Wasm limits (in particular the maximum length
/// for `array.new_fixed`), the constant is lazy, meaning that the global starts
/// out uninitialized, and every use of the constant checks the global to see if
/// it has been initialized and calls an initialization function otherwise.
/// A constant is also forced to be lazy if any sub-constants (e.g. elements of
/// a constant list) are lazy.
class Constants {
  final Translator translator;
  final Map<Constant, ConstantInfo> constantInfo = {};
  w.DataSegmentBuilder? oneByteStringSegment;
  w.DataSegmentBuilder? twoByteStringSegment;
  late final ClassInfo typeInfo = translator.classInfo[translator.typeClass]!;

  bool currentlyCreating = false;

  Constants(this.translator);

  w.ModuleBuilder get m => translator.m;

  /// Makes a `WasmArray<_Type>` [InstanceConstant].
  InstanceConstant makeTypeArray(Iterable<DartType> types) => makeArrayOf(
      translator.typeType, types.map((t) => TypeLiteralConstant(t)).toList());

  /// Makes a `_NamedParameter` [InstanceConstant].
  InstanceConstant makeNamedParameterConstant(NamedType n) =>
      InstanceConstant(translator.namedParameterClass.reference, const [], {
        translator.namedParameterNameField.fieldReference:
            StringConstant(n.name),
        translator.namedParameterTypeField.fieldReference:
            TypeLiteralConstant(n.type),
        translator.namedParameterIsRequiredField.fieldReference:
            BoolConstant(n.isRequired),
      });

  /// Creates a `WasmArray<_NamedParameter>` to be used as field of
  /// `_FunctionType`.
  InstanceConstant makeNamedParametersArray(FunctionType type) => makeArrayOf(
      translator.namedParameterType,
      [for (final n in type.namedParameters) makeNamedParameterConstant(n)]);

  /// Creates a `WasmArray<T>` with the given [Constant]s
  InstanceConstant makeArrayOf(
          InterfaceType elementType, List<Constant> entries) =>
      InstanceConstant(translator.wasmArrayClass.reference, [
        elementType,
      ], {
        translator.wasmArrayValueField.fieldReference:
            ListConstant(elementType, entries),
      });

  /// Ensure that the constant has a Wasm global assigned.
  ///
  /// Sub-constants must have Wasm globals assigned before the global for the
  /// composite constant is assigned, since global initializers can only refer
  /// to earlier globals.
  ConstantInfo? ensureConstant(Constant constant) {
    return ConstantCreator(this).ensureConstant(constant);
  }

  /// Emit code to push a constant onto the stack.
  void instantiateConstant(w.BaseFunction? function, w.InstructionsBuilder b,
      Constant constant, w.ValueType expectedType) {
    if (expectedType == translator.voidMarker) return;
    ConstantInstantiator(this, function, b, expectedType).instantiate(constant);
  }
}

class ConstantInstantiator extends ConstantVisitor<w.ValueType>
    with ConstantVisitorDefaultMixin<w.ValueType> {
  final Constants constants;
  final w.BaseFunction? function;
  final w.InstructionsBuilder b;
  final w.ValueType expectedType;

  ConstantInstantiator(
      this.constants, this.function, this.b, this.expectedType);

  Translator get translator => constants.translator;
  w.ModuleBuilder get m => translator.m;

  void instantiate(Constant constant) {
    w.ValueType resultType = constant.accept(this);
    if (translator.needsConversion(resultType, expectedType)) {
      if (expectedType == const w.RefType.extern(nullable: true)) {
        assert(resultType.isSubtypeOf(w.RefType.any(nullable: true)));
        b.extern_externalize();
      } else {
        // This only happens in invalid but unreachable code produced by the
        // TFA dead-code elimination.
        b.comment("Constant in incompatible context");
        b.unreachable();
      }
    }
  }

  @override
  w.ValueType defaultConstant(Constant constant) {
    ConstantInfo info = ConstantCreator(constants).ensureConstant(constant)!;
    if (info.isLazy) {
      // Lazily initialized constant.
      w.ValueType type = info.global.type.type.withNullability(false);
      w.Label done = b.block(const [], [type]);
      b.global_get(info.global);
      b.br_on_non_null(done);
      b.call(info.function!);
      b.end();
      return type;
    } else {
      // Constant initialized eagerly in a global initializer.
      b.global_get(info.global);
      return info.global.type.type;
    }
  }

  @override
  w.ValueType visitUnevaluatedConstant(UnevaluatedConstant constant) {
    if (constant == ParameterInfo.defaultValueSentinel) {
      // Instantiate a sentinel value specific to the parameter type.
      w.ValueType sentinelType = expectedType.withNullability(false);
      assert(sentinelType is w.RefType,
          "Default value sentinel for unboxed parameter");
      translator.globals.instantiateDummyValue(b, sentinelType);
      return sentinelType;
    }
    return super.visitUnevaluatedConstant(constant);
  }

  @override
  w.ValueType visitNullConstant(NullConstant node) {
    b.ref_null(w.HeapType.none);
    return const w.RefType.none(nullable: true);
  }

  @override
  w.ValueType visitBoolConstant(BoolConstant constant) {
    if (expectedType is w.RefType) return defaultConstant(constant);
    b.i32_const(constant.value ? 1 : 0);
    return w.NumType.i32;
  }

  @override
  w.ValueType visitIntConstant(IntConstant constant) {
    if (expectedType is w.RefType) return defaultConstant(constant);
    if (expectedType == w.NumType.i32) {
      b.i32_const(constant.value);
      return w.NumType.i32;
    }
    b.i64_const(constant.value);
    return w.NumType.i64;
  }

  @override
  w.ValueType visitDoubleConstant(DoubleConstant constant) {
    if (expectedType is w.RefType) return defaultConstant(constant);
    b.f64_const(constant.value);
    return w.NumType.f64;
  }

  @override
  w.ValueType visitInstanceConstant(InstanceConstant constant) {
    if (constant.classNode == translator.wasmI32Class) {
      int value = (constant.fieldValues.values.single as IntConstant).value;
      b.i32_const(value);
      return w.NumType.i32;
    }
    if (constant.classNode == translator.wasmI64Class) {
      int value = (constant.fieldValues.values.single as IntConstant).value;
      b.i64_const(value);
      return w.NumType.i64;
    }
    if (constant.classNode == translator.wasmF32Class) {
      double value =
          (constant.fieldValues.values.single as DoubleConstant).value;
      b.f32_const(value);
      return w.NumType.f32;
    }
    if (constant.classNode == translator.wasmF64Class) {
      double value =
          (constant.fieldValues.values.single as DoubleConstant).value;
      b.f64_const(value);
      return w.NumType.f64;
    }
    return super.visitInstanceConstant(constant);
  }
}

class ConstantCreator extends ConstantVisitor<ConstantInfo?>
    with ConstantVisitorDefaultMixin<ConstantInfo?> {
  final Constants constants;

  ConstantCreator(this.constants);

  Translator get translator => constants.translator;
  Types get types => translator.types;
  w.ModuleBuilder get m => constants.m;

  Constant get _uninitializedHashBaseIndexConstant =>
      (translator.uninitializedHashBaseIndex.initializer as ConstantExpression)
          .constant;

  ConstantInfo? ensureConstant(Constant constant) {
    // To properly canonicalize type literal constants, we normalize the
    // type before canonicalization.
    if (constant is TypeLiteralConstant) {
      DartType type = types.normalize(constant.type);
      if (!identical(type, constant.type)) {
        constant = TypeLiteralConstant(type);
      }
    }

    ConstantInfo? info = constants.constantInfo[constant];
    if (info == null) {
      info = constant.accept(this);
      if (info != null) {
        constants.constantInfo[constant] = info;
      }
    }
    return info;
  }

  ConstantInfo createConstant(
      Constant constant, w.RefType type, ConstantCodeGenerator generator,
      {bool lazy = false}) {
    assert(!type.nullable);
    if (lazy) {
      // Create uninitialized global and function to initialize it.
      final global = m.globals.define(w.GlobalType(type.withNullability(true)));
      global.initializer.ref_null(w.HeapType.none);
      global.initializer.end();
      w.FunctionType ftype = m.types.defineFunction(const [], [type]);
      final function = m.functions.define(ftype, "$constant");
      generator(function, function.body);
      w.Local temp = function.addLocal(type);
      final b2 = function.body;
      b2.local_tee(temp);
      b2.global_set(global);
      b2.local_get(temp);
      b2.end();

      return ConstantInfo(constant, global, function);
    } else {
      // Create global with the constant in its initializer.
      assert(!constants.currentlyCreating);
      constants.currentlyCreating = true;
      final global = m.globals.define(w.GlobalType(type, mutable: false));
      generator(null, global.initializer);
      global.initializer.end();
      constants.currentlyCreating = false;

      return ConstantInfo(constant, global, null);
    }
  }

  @override
  ConstantInfo? defaultConstant(Constant constant) => null;

  @override
  ConstantInfo? visitBoolConstant(BoolConstant constant) {
    ClassInfo info = translator.classInfo[translator.boxedBoolClass]!;
    return createConstant(constant, info.nonNullableType, (function, b) {
      b.i32_const(info.classId);
      b.i32_const(constant.value ? 1 : 0);
      b.struct_new(info.struct);
    });
  }

  @override
  ConstantInfo? visitIntConstant(IntConstant constant) {
    ClassInfo info = translator.classInfo[translator.boxedIntClass]!;
    return createConstant(constant, info.nonNullableType, (function, b) {
      b.i32_const(info.classId);
      b.i64_const(constant.value);
      b.struct_new(info.struct);
    });
  }

  @override
  ConstantInfo? visitDoubleConstant(DoubleConstant constant) {
    ClassInfo info = translator.classInfo[translator.boxedDoubleClass]!;
    return createConstant(constant, info.nonNullableType, (function, b) {
      b.i32_const(info.classId);
      b.f64_const(constant.value);
      b.struct_new(info.struct);
    });
  }

  @override
  ConstantInfo? visitStringConstant(StringConstant constant) {
    if (translator.options.jsCompatibility) {
      ClassInfo info = translator.classInfo[translator.jsStringClass]!;
      return createConstant(constant, info.nonNullableType, (function, b) {
        b.i32_const(info.classId);
        b.i32_const(initialIdentityHash);
        b.global_get(translator.getInternalizedStringGlobal(constant.value));
        b.struct_new(info.struct);
      });
    }
    bool isOneByte = constant.value.codeUnits.every((c) => c <= 255);
    ClassInfo info = translator.classInfo[isOneByte
        ? translator.oneByteStringClass
        : translator.twoByteStringClass]!;
    translator.functions.recordClassAllocation(info.classId);
    w.RefType type = info.nonNullableType;
    bool lazy = constant.value.length > maxArrayNewFixedLength;
    return createConstant(constant, type, lazy: lazy, (function, b) {
      w.ArrayType arrayType =
          (info.struct.fields[FieldIndex.stringArray].type as w.RefType)
              .heapType as w.ArrayType;

      b.i32_const(info.classId);
      b.i32_const(initialIdentityHash);
      if (lazy) {
        // Initialize string contents from passive data segment.
        w.DataSegmentBuilder segment;
        Uint8List bytes;
        if (isOneByte) {
          segment = constants.oneByteStringSegment ??= m.dataSegments.define();
          bytes = Uint8List.fromList(constant.value.codeUnits);
        } else {
          assert(Endian.host == Endian.little);
          segment = constants.twoByteStringSegment ??= m.dataSegments.define();
          bytes = Uint16List.fromList(constant.value.codeUnits)
              .buffer
              .asUint8List();
        }
        int offset = segment.length;
        segment.append(bytes);
        b.i32_const(offset);
        b.i32_const(constant.value.length);
        b.array_new_data(arrayType, segment);
      } else {
        // Initialize string contents from i32 constants on the stack.
        for (int charCode in constant.value.codeUnits) {
          b.i32_const(charCode);
        }
        b.array_new_fixed(arrayType, constant.value.length);
      }
      b.struct_new(info.struct);
    });
  }

  @override
  ConstantInfo? visitInstanceConstant(InstanceConstant constant) {
    Class cls = constant.classNode;
    if (cls == translator.wasmArrayClass) {
      return _makeWasmArrayLiteral(constant);
    }

    ClassInfo info = translator.classInfo[cls]!;
    translator.functions.recordClassAllocation(info.classId);
    w.RefType type = info.nonNullableType;

    // Collect sub-constants for field values.
    const int baseFieldCount = 2;
    int fieldCount = info.struct.fields.length;
    List<Constant?> subConstants = List.filled(fieldCount, null);
    bool lazy = false;
    constant.fieldValues.forEach((reference, subConstant) {
      int index = translator.fieldIndex[reference.asField]!;
      assert(subConstants[index] == null);
      subConstants[index] = subConstant;
      lazy |= ensureConstant(subConstant)?.isLazy ?? false;
    });

    // Collect sub-constants for type arguments.
    Map<TypeParameter, DartType> substitution = {};
    List<DartType> args = constant.typeArguments;
    while (true) {
      for (int i = 0; i < cls.typeParameters.length; i++) {
        TypeParameter parameter = cls.typeParameters[i];
        DartType arg = substitute(args[i], substitution);
        substitution[parameter] = arg;
        int index = translator.typeParameterIndex[parameter]!;
        Constant typeArgConstant = TypeLiteralConstant(arg);
        subConstants[index] = typeArgConstant;
        ensureConstant(typeArgConstant);
      }
      Supertype? supertype = cls.supertype;
      if (supertype == null) break;
      cls = supertype.classNode;
      args = supertype.typeArguments;
    }

    return createConstant(constant, type, lazy: lazy, (function, b) {
      b.i32_const(info.classId);
      b.i32_const(initialIdentityHash);
      for (int i = baseFieldCount; i < fieldCount; i++) {
        Constant subConstant = subConstants[i]!;
        constants.instantiateConstant(
            function, b, subConstant, info.struct.fields[i].type.unpacked);
      }
      b.struct_new(info.struct);
    });
  }

  ConstantInfo? _makeWasmArrayLiteral(InstanceConstant constant) {
    w.ArrayType arrayType =
        translator.arrayTypeForDartType(constant.typeArguments.single);
    w.ValueType elementType = arrayType.elementType.type.unpacked;

    List<Constant> elements =
        (constant.fieldValues.values.single as ListConstant).entries;
    final tooLargeForArrayNewFixed = elements.length > maxArrayNewFixedLength;
    bool lazy = tooLargeForArrayNewFixed;
    for (Constant element in elements) {
      lazy |= ensureConstant(element)?.isLazy ?? false;
    }

    return createConstant(constant, w.RefType.def(arrayType, nullable: false),
        lazy: lazy, (function, b) {
      if (tooLargeForArrayNewFixed) {
        // We will initialize the array with one of the elements (using
        // `array.new`) and update the fields.
        //
        // For the initial element pick the one that occurs the most to save
        // some work when the array has duplicates.
        final Map<Constant, int> occurrences = {};
        for (final element in elements) {
          occurrences.update(element, (i) => i + 1, ifAbsent: () => 1);
        }

        var initialElement = elements[0];
        var initialElementOccurrences = 1;
        for (final entry in occurrences.entries) {
          if (entry.value > initialElementOccurrences) {
            initialElementOccurrences = entry.value;
            initialElement = entry.key;
          }
        }

        w.Local arrayLocal =
            function!.addLocal(w.RefType.def(arrayType, nullable: false));
        constants.instantiateConstant(function, b, initialElement, elementType);
        b.i32_const(elements.length);
        b.array_new(arrayType);
        b.local_set(arrayLocal);
        for (int i = 0; i < elements.length; i++) {
          final element = elements[i];
          if (element == initialElement) {
            continue;
          }
          b.local_get(arrayLocal);
          b.i32_const(i);
          constants.instantiateConstant(function, b, element, elementType);
          b.array_set(arrayType);
        }
        b.local_get(arrayLocal);
      } else {
        for (Constant element in elements) {
          constants.instantiateConstant(function, b, element, elementType);
        }
        b.array_new_fixed(arrayType, elements.length);
      }
    });
  }

  @override
  ConstantInfo? visitListConstant(ListConstant constant) {
    Constant typeArgConstant = TypeLiteralConstant(constant.typeArgument);
    ensureConstant(typeArgConstant);
    bool lazy = constant.entries.length > maxArrayNewFixedLength;
    for (Constant subConstant in constant.entries) {
      lazy |= ensureConstant(subConstant)?.isLazy ?? false;
    }

    ClassInfo info = translator.classInfo[translator.immutableListClass]!;
    translator.functions.recordClassAllocation(info.classId);
    w.RefType type = info.nonNullableType;
    return createConstant(constant, type, lazy: lazy, (function, b) {
      w.ArrayType arrayType = translator.listArrayType;
      w.ValueType elementType = arrayType.elementType.type.unpacked;
      int length = constant.entries.length;
      b.i32_const(info.classId);
      b.i32_const(initialIdentityHash);
      constants.instantiateConstant(
          function, b, typeArgConstant, constants.typeInfo.nullableType);
      b.i64_const(length);
      if (lazy) {
        // Allocate array and set each entry to the corresponding sub-constant.
        w.Local arrayLocal =
            function!.addLocal(w.RefType.def(arrayType, nullable: false));
        b.i32_const(length);
        b.array_new_default(arrayType);
        b.local_set(arrayLocal);
        for (int i = 0; i < length; i++) {
          b.local_get(arrayLocal);
          b.i32_const(i);
          constants.instantiateConstant(
              function, b, constant.entries[i], elementType);
          b.array_set(arrayType);
        }
        b.local_get(arrayLocal);
      } else {
        // Push all sub-constants on the stack and initialize array from them.
        for (int i = 0; i < length; i++) {
          constants.instantiateConstant(
              function, b, constant.entries[i], elementType);
        }
        b.array_new_fixed(arrayType, length);
      }
      b.struct_new(info.struct);
    });
  }

  @override
  ConstantInfo? visitMapConstant(MapConstant constant) {
    final listElements = List.generate(constant.entries.length * 2, (i) {
      ConstantMapEntry entry = constant.entries[i >> 1];
      return i.isEven ? entry.key : entry.value;
    });

    final instanceConstant =
        InstanceConstant(translator.immutableMapClass.reference, [
      constant.keyType,
      constant.valueType
    ], {
      // _index = _uninitializedHashBaseIndex
      translator.hashFieldBaseIndexField.fieldReference:
          _uninitializedHashBaseIndexConstant,

      // _hashMask
      translator.hashFieldBaseHashMaskField.fieldReference: IntConstant(0),

      // _data
      translator.hashFieldBaseDataField.fieldReference:
          InstanceConstant(translator.wasmArrayClass.reference, [
        translator.coreTypes.objectNullableRawType
      ], {
        translator.wasmArrayValueField.fieldReference: ListConstant(
            translator.coreTypes.objectNullableRawType, listElements)
      }),

      // _usedData
      translator.hashFieldBaseUsedDataField.fieldReference:
          IntConstant(listElements.length),

      // _deletedKeys
      translator.hashFieldBaseDeletedKeysField.fieldReference: IntConstant(0),
    });

    return ensureConstant(instanceConstant);
  }

  @override
  ConstantInfo? visitSetConstant(SetConstant constant) {
    final instanceConstant =
        InstanceConstant(translator.immutableSetClass.reference, [
      constant.typeArgument
    ], {
      // _index = _uninitializedHashBaseIndex
      translator.hashFieldBaseIndexField.fieldReference:
          _uninitializedHashBaseIndexConstant,

      // _hashMask
      translator.hashFieldBaseHashMaskField.fieldReference: IntConstant(0),

      // _data
      translator.hashFieldBaseDataField.fieldReference:
          InstanceConstant(translator.wasmArrayClass.reference, [
        translator.coreTypes.objectNullableRawType
      ], {
        translator.wasmArrayValueField.fieldReference: ListConstant(
            translator.coreTypes.objectNullableRawType, constant.entries)
      }),

      // _usedData
      translator.hashFieldBaseUsedDataField.fieldReference:
          IntConstant(constant.entries.length),

      // _deletedKeys
      translator.hashFieldBaseDeletedKeysField.fieldReference: IntConstant(0),
    });

    return ensureConstant(instanceConstant);
  }

  @override
  ConstantInfo? visitStaticTearOffConstant(StaticTearOffConstant constant) {
    Procedure member = constant.targetReference.asProcedure;
    Constant functionTypeConstant =
        TypeLiteralConstant(translator.getTearOffType(member));
    ensureConstant(functionTypeConstant);
    ClosureImplementation closure = translator.getTearOffClosure(member);
    w.StructType struct = closure.representation.closureStruct;
    w.RefType type = w.RefType.def(struct, nullable: false);
    return createConstant(constant, type, (function, b) {
      ClassInfo info = translator.closureInfo;
      translator.functions.recordClassAllocation(info.classId);

      b.i32_const(info.classId);
      b.i32_const(initialIdentityHash);
      b.global_get(translator.globals.dummyStructGlobal); // Dummy context
      b.global_get(closure.vtable);
      constants.instantiateConstant(
          function, b, functionTypeConstant, types.nonNullableTypeType);
      b.struct_new(struct);
    });
  }

  @override
  ConstantInfo? visitInstantiationConstant(InstantiationConstant constant) {
    TearOffConstant tearOffConstant =
        constant.tearOffConstant as TearOffConstant;
    List<ConstantInfo> types = constant.types
        .map((c) => ensureConstant(TypeLiteralConstant(c))!)
        .toList();
    Procedure tearOffProcedure = tearOffConstant.targetReference.asProcedure;
    FunctionType tearOffFunctionType =
        translator.getTearOffType(tearOffProcedure);
    FunctionType instantiatedFunctionType =
        FunctionTypeInstantiator.instantiate(
            tearOffFunctionType, constant.types);
    Constant functionTypeConstant =
        TypeLiteralConstant(instantiatedFunctionType);
    ensureConstant(functionTypeConstant);
    ClosureImplementation tearOffClosure =
        translator.getTearOffClosure(tearOffProcedure);
    int positionalCount = tearOffConstant.function.positionalParameters.length;
    List<String> names =
        tearOffConstant.function.namedParameters.map((p) => p.name!).toList();
    ClosureRepresentation representation = translator.closureLayouter
        .getClosureRepresentation(0, positionalCount, names)!;
    ClosureRepresentation instantiationRepresentation = translator
        .closureLayouter
        .getClosureRepresentation(types.length, positionalCount, names)!;
    w.StructType struct = representation.closureStruct;
    w.RefType type = w.RefType.def(struct, nullable: false);

    final tearOffConstantInfo = ensureConstant(tearOffConstant)!;

    w.BaseFunction makeDynamicCallEntry() {
      final function = m.functions.define(
          translator.dynamicCallVtableEntryFunctionType, "dynamic call entry");

      final b = function.body;

      final closureLocal = function.locals[0];
      final typeArgsListLocal = function.locals[1]; // empty
      final posArgsListLocal = function.locals[2];
      final namedArgsListLocal = function.locals[3];

      b.local_get(closureLocal);
      final InstanceConstant typeArgs = constants.makeTypeArray(constant.types);
      constants.instantiateConstant(
          function, b, typeArgs, typeArgsListLocal.type);
      b.local_get(posArgsListLocal);
      b.local_get(namedArgsListLocal);
      b.call(tearOffClosure.dynamicCallEntry);
      b.end();

      return function;
    }

    // Dynamic call entry needs to be created first (before `createConstant`)
    // as it needs to create a constant for the type list, and we cannot create
    // a constant while creating another one.
    final w.BaseFunction dynamicCallEntry = makeDynamicCallEntry();

    return createConstant(constant, type, (function, b) {
      ClassInfo info = translator.closureInfo;
      translator.functions.recordClassAllocation(info.classId);

      w.BaseFunction makeTrampoline(
          w.FunctionType signature, w.BaseFunction tearOffFunction) {
        assert(tearOffFunction.type.inputs.length ==
            signature.inputs.length + types.length);
        final function =
            m.functions.define(signature, "instantiation constant trampoline");
        final b = function.body;
        b.local_get(function.locals[0]);
        for (ConstantInfo typeInfo in types) {
          b.global_get(typeInfo.global);
        }
        for (int i = 1; i < signature.inputs.length; i++) {
          b.local_get(function.locals[i]);
        }
        b.call(tearOffFunction);
        b.end();
        return function;
      }

      void fillVtableEntry(int posArgCount, List<String> argNames) {
        int fieldIndex =
            representation.fieldIndexForSignature(posArgCount, argNames);
        int tearOffFieldIndex = tearOffClosure.representation
            .fieldIndexForSignature(posArgCount, argNames);

        w.FunctionType signature =
            representation.getVtableFieldType(fieldIndex);
        w.BaseFunction tearOffFunction = tearOffClosure.functions[
            tearOffFieldIndex - tearOffClosure.representation.vtableBaseIndex];
        w.BaseFunction function =
            translator.globals.isDummyFunction(tearOffFunction)
                ? translator.globals.getDummyFunction(signature)
                : makeTrampoline(signature, tearOffFunction);
        b.ref_func(function);
      }

      void makeVtable() {
        b.ref_func(dynamicCallEntry);
        if (representation.isGeneric) {
          b.ref_func(representation.instantiationFunction);
        }
        for (int posArgCount = 0;
            posArgCount <= positionalCount;
            posArgCount++) {
          fillVtableEntry(posArgCount, const []);
        }
        for (NameCombination combination in representation.nameCombinations) {
          fillVtableEntry(positionalCount, combination.names);
        }
        b.struct_new(representation.vtableStruct);
      }

      b.i32_const(info.classId);
      b.i32_const(initialIdentityHash);

      // Context is not used by the vtable functions, but it's needed for
      // closure equality checks to work (`_Closure._equals`).
      b.global_get(tearOffConstantInfo.global);
      for (final ty in types) {
        b.global_get(ty.global);
      }
      b.struct_new(instantiationRepresentation.instantiationContextStruct!);

      makeVtable();
      constants.instantiateConstant(
          function, b, functionTypeConstant, this.types.nonNullableTypeType);
      b.struct_new(struct);
    });
  }

  ConstantInfo? _makeInterfaceType(
      TypeLiteralConstant constant, InterfaceType type, ClassInfo info) {
    // Don't use `_Closure` as a type. Use `Function` instead, as this is
    // properly recognized as the abstract function type.
    assert(type.classNode != translator.closureClass);
    InstanceConstant typeArgs = constants.makeTypeArray(type.typeArguments);
    ensureConstant(typeArgs);
    return createConstant(constant, info.nonNullableType, (function, b) {
      ClassInfo typeInfo = translator.classInfo[type.classNode]!;
      w.ValueType typeArrayExpectedType = info
          .struct.fields[FieldIndex.interfaceTypeTypeArguments].type.unpacked;

      b.i32_const(info.classId);
      b.i32_const(initialIdentityHash);
      b.i32_const(types.encodedNullability(type));
      b.i64_const(typeInfo.classId);
      constants.instantiateConstant(
          function, b, typeArgs, typeArrayExpectedType);
      b.struct_new(info.struct);
    });
  }

  ConstantInfo? _makeFutureOrType(
      TypeLiteralConstant constant, FutureOrType type, ClassInfo info) {
    TypeLiteralConstant typeArgument = TypeLiteralConstant(type.typeArgument);
    ensureConstant(typeArgument);
    return createConstant(constant, info.nonNullableType, (function, b) {
      b.i32_const(info.classId);
      b.i32_const(initialIdentityHash);
      b.i32_const(types.encodedNullability(type));
      constants.instantiateConstant(
          function, b, typeArgument, types.nonNullableTypeType);
      b.struct_new(info.struct);
    });
  }

  ConstantInfo? _makeFunctionType(
      TypeLiteralConstant constant, FunctionType type, ClassInfo info) {
    int typeParameterOffset = types.computeFunctionTypeParameterOffset(type);
    InstanceConstant typeParameterBoundsConstant =
        constants.makeTypeArray(type.typeParameters.map((p) => p.bound));
    InstanceConstant typeParameterDefaultsConstant =
        constants.makeTypeArray(type.typeParameters.map((p) => p.defaultType));
    TypeLiteralConstant returnTypeConstant =
        TypeLiteralConstant(type.returnType);
    InstanceConstant positionalParametersConstant =
        constants.makeTypeArray(type.positionalParameters);
    IntConstant requiredParameterCountConstant =
        IntConstant(type.requiredParameterCount);
    InstanceConstant namedParametersConstant =
        constants.makeNamedParametersArray(type);
    ensureConstant(typeParameterBoundsConstant);
    ensureConstant(typeParameterDefaultsConstant);
    ensureConstant(returnTypeConstant);
    ensureConstant(positionalParametersConstant);
    ensureConstant(requiredParameterCountConstant);
    ensureConstant(namedParametersConstant);
    return createConstant(constant, info.nonNullableType, (function, b) {
      b.i32_const(info.classId);
      b.i32_const(initialIdentityHash);
      b.i32_const(types.encodedNullability(type));
      b.i64_const(typeParameterOffset);
      constants.instantiateConstant(function, b, typeParameterBoundsConstant,
          types.typeArrayExpectedType);
      constants.instantiateConstant(function, b, typeParameterDefaultsConstant,
          types.typeArrayExpectedType);
      constants.instantiateConstant(
          function, b, returnTypeConstant, types.nonNullableTypeType);
      constants.instantiateConstant(function, b, positionalParametersConstant,
          types.typeArrayExpectedType);
      constants.instantiateConstant(
          function, b, requiredParameterCountConstant, w.NumType.i64);
      constants.instantiateConstant(function, b, namedParametersConstant,
          types.namedParametersExpectedType);
      b.struct_new(info.struct);
    });
  }

  @override
  ConstantInfo? visitTypeLiteralConstant(TypeLiteralConstant constant) {
    final DartType type = constant.type;
    final ClassInfo info = translator.classInfo[types.classForType(type)]!;
    translator.functions.recordClassAllocation(info.classId);
    if (type is InterfaceType && !types.isSpecializedClass(type.classNode)) {
      return _makeInterfaceType(constant, type, info);
    } else if (type is FutureOrType) {
      return _makeFutureOrType(constant, type, info);
    } else if (type is FunctionType) {
      return _makeFunctionType(constant, type, info);
    } else if (type is ExtensionType) {
      return ensureConstant(TypeLiteralConstant(type.extensionTypeErasure));
    } else if (type is TypeParameterType) {
      int environmentIndex =
          types.interfaceTypeEnvironment.lookup(type.parameter);
      return createConstant(constant, info.nonNullableType, (function, b) {
        b.i32_const(info.classId);
        b.i32_const(initialIdentityHash);
        b.i32_const(types.encodedNullability(type));
        b.i64_const(environmentIndex);
        b.struct_new(info.struct);
      });
    } else if (type is StructuralParameterType) {
      // The indexing scheme used by function type parameters ensures that
      // function type parameter types that are identical as constants (have
      // the same nullability and refer to the same type parameter) have the
      // same representation and thus can be canonicalized like other
      // constants.
      return createConstant(constant, info.nonNullableType, (function, b) {
        int index = types.getFunctionTypeParameterIndex(type.parameter);
        b.i32_const(info.classId);
        b.i32_const(initialIdentityHash);
        b.i32_const(types.encodedNullability(type));
        b.i64_const(index);
        b.struct_new(info.struct);
      });
    } else if (type is RecordType) {
      final names = constants.makeArrayOf(
          translator.coreTypes.stringNonNullableRawType,
          type.named.map((t) => StringConstant(t.name)).toList());
      ensureConstant(names);
      final fieldTypes = constants.makeArrayOf(translator.typeType, [
        for (final pos in type.positional) TypeLiteralConstant(pos),
        for (final named in type.named) TypeLiteralConstant(named.type),
      ]);
      ensureConstant(fieldTypes);
      return createConstant(constant, info.nonNullableType, (function, b) {
        b.i32_const(info.classId);
        b.i32_const(initialIdentityHash);
        b.i32_const(types.encodedNullability(type));
        final namesExpectedType =
            info.struct.fields[FieldIndex.recordTypeNames].type.unpacked;
        constants.instantiateConstant(function, b, names, namesExpectedType);
        final typeListExpectedType =
            info.struct.fields[FieldIndex.recordTypeFieldTypes].type.unpacked;
        constants.instantiateConstant(
            function, b, fieldTypes, typeListExpectedType);
        b.struct_new(info.struct);
      });
    } else if (type is VoidType ||
        type is DynamicType ||
        type is InterfaceType &&
            type.classNode == translator.coreTypes.objectClass) {
      return createConstant(constant, info.nonNullableType, (function, b) {
        b.i32_const(info.classId);
        b.i32_const(initialIdentityHash);
        b.i32_const(types.encodedNullability(type));
        b.i64_const(types.topTypeKind(type));
        b.struct_new(info.struct);
      });
    } else {
      assert(type is NeverType ||
          type is NullType ||
          type is InterfaceType && types.isSpecializedClass(type.classNode));
      return createConstant(constant, info.nonNullableType, (function, b) {
        b.i32_const(info.classId);
        b.i32_const(initialIdentityHash);
        b.i32_const(types.encodedNullability(type));
        b.struct_new(info.struct);
      });
    }
  }

  @override
  ConstantInfo? visitSymbolConstant(SymbolConstant constant) {
    ClassInfo info = translator.classInfo[translator.symbolClass]!;
    translator.functions.recordClassAllocation(info.classId);
    w.RefType stringType = translator
        .classInfo[translator.coreTypes.stringClass]!.repr.nonNullableType;
    StringConstant nameConstant = StringConstant(constant.name);
    bool lazy = ensureConstant(nameConstant)?.isLazy ?? false;
    return createConstant(constant, info.nonNullableType, lazy: lazy,
        (function, b) {
      b.i32_const(info.classId);
      b.i32_const(initialIdentityHash);
      constants.instantiateConstant(function, b, nameConstant, stringType);
      b.struct_new(info.struct);
    });
  }

  @override
  ConstantInfo? visitRecordConstant(RecordConstant constant) {
    final ClassInfo recordClassInfo =
        translator.getRecordClassInfo(constant.recordType);
    translator.functions.recordClassAllocation(recordClassInfo.classId);

    final List<Constant> arguments = constant.positional.toList();
    arguments.addAll(constant.named.values);

    for (Constant argument in arguments) {
      ensureConstant(argument);
    }

    return createConstant(constant, recordClassInfo.nonNullableType,
        lazy: false, (function, b) {
      b.i32_const(recordClassInfo.classId);
      b.i32_const(initialIdentityHash);
      for (Constant argument in arguments) {
        constants.instantiateConstant(
            function, b, argument, translator.topInfo.nullableType);
      }
      b.struct_new(recordClassInfo.struct);
    });
  }
}
