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

import 'package:dart2wasm/class_info.dart';
import 'package:dart2wasm/translator.dart';
import 'package:dart2wasm/types.dart';

import 'package:kernel/ast.dart';
import 'package:kernel/type_algebra.dart' show substitute;

import 'package:wasm_builder/wasm_builder.dart' as w;

class ConstantInfo {
  final Constant constant;
  final w.DefinedGlobal global;
  final w.DefinedFunction? function;

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

typedef ConstantCodeGenerator = void Function(
    w.DefinedFunction?, w.Instructions);

/// Handles the creation of Dart constants. Can operate in two modes - eager and
/// lazy - controlled by [TranslatorOptions.lazyConstants].
///
/// Each (non-trivial) constant is assigned to a Wasm global. Multiple
/// occurrences of the same constant use the same global.
///
/// In eager mode, the constant is contained within the global initializer,
/// meaning all constants are initialized eagerly during module initialization.
/// In lazy mode, 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.
class Constants {
  final Translator translator;
  final Map<Constant, ConstantInfo> constantInfo = {};
  final StringBuffer oneByteStrings = StringBuffer();
  final StringBuffer twoByteStrings = StringBuffer();
  late final w.DefinedFunction oneByteStringFunction;
  late final w.DefinedFunction twoByteStringFunction;
  late final w.DataSegment oneByteStringSegment;
  late final w.DataSegment twoByteStringSegment;
  late final w.DefinedGlobal emptyString;
  late final w.DefinedGlobal emptyTypeList;
  late final ClassInfo typeInfo = translator.classInfo[translator.typeClass]!;

  bool currentlyCreating = false;

  Constants(this.translator) {
    if (lazyConstants) {
      oneByteStringFunction = makeStringFunction(translator.oneByteStringClass);
      twoByteStringFunction = makeStringFunction(translator.twoByteStringClass);
    } else if (stringDataSegments) {
      oneByteStringSegment = m.addDataSegment();
      twoByteStringSegment = m.addDataSegment();
    }
    initEmptyString();
    initEmptyTypeList();
  }

  w.Module get m => translator.m;
  bool get lazyConstants => translator.options.lazyConstants;
  bool get stringDataSegments => translator.options.stringDataSegments;

  void initEmptyString() {
    ClassInfo info = translator.classInfo[translator.oneByteStringClass]!;
    translator.functions.allocateClass(info.classId);
    w.ArrayType arrayType =
        (info.struct.fields.last.type as w.RefType).heapType as w.ArrayType;

    if (lazyConstants) {
      w.RefType emptyStringType = info.nullableType;
      emptyString = m.addGlobal(w.GlobalType(emptyStringType));
      emptyString.initializer.ref_null(emptyStringType.heapType);
      emptyString.initializer.end();

      w.Instructions b = translator.initFunction.body;
      b.i32_const(info.classId);
      b.i32_const(initialIdentityHash);
      b.i32_const(0);
      translator.array_new_default(b, arrayType);
      translator.struct_new(b, info);
      b.global_set(emptyString);
    } else {
      w.RefType emptyStringType = info.nonNullableType;
      emptyString = m.addGlobal(w.GlobalType(emptyStringType, mutable: false));
      w.Instructions ib = emptyString.initializer;
      ib.i32_const(info.classId);
      ib.i32_const(initialIdentityHash);
      translator.array_init(ib, arrayType, 0);
      translator.struct_new(ib, info);
      ib.end();
    }

    Constant emptyStringConstant = StringConstant("");
    constantInfo[emptyStringConstant] =
        ConstantInfo(emptyStringConstant, emptyString, null);
  }

  void initEmptyTypeList() {
    ClassInfo info = translator.classInfo[translator.immutableListClass]!;
    translator.functions.allocateClass(info.classId);
    w.RefType refType = info.struct.fields.last.type.unpacked as w.RefType;
    w.ArrayType arrayType = refType.heapType as w.ArrayType;

    // Create the empty type list with its type parameter uninitialized for now.
    if (lazyConstants) {
      w.RefType emptyListType = info.nullableType;
      emptyTypeList = m.addGlobal(w.GlobalType(emptyListType));
      emptyTypeList.initializer.ref_null(emptyListType.heapType);
      emptyTypeList.initializer.end();

      w.Instructions b = translator.initFunction.body;
      b.i32_const(info.classId);
      b.i32_const(initialIdentityHash);
      b.ref_null(typeInfo.struct); // Initialized later
      b.i64_const(0);
      b.i32_const(0);
      translator.array_new_default(b, arrayType);
      translator.struct_new(b, info);
      b.global_set(emptyTypeList);
    } else {
      w.RefType emptyListType = info.nonNullableType;
      emptyTypeList = m.addGlobal(w.GlobalType(emptyListType, mutable: false));
      w.Instructions ib = emptyTypeList.initializer;
      ib.i32_const(info.classId);
      ib.i32_const(initialIdentityHash);
      ib.ref_null(typeInfo.struct); // Initialized later
      ib.i64_const(0);
      translator.array_init(ib, arrayType, 0);
      translator.struct_new(ib, info);
      ib.end();
    }

    Constant emptyTypeListConstant = ListConstant(
        InterfaceType(translator.typeClass, Nullability.nonNullable), const []);
    constantInfo[emptyTypeListConstant] =
        ConstantInfo(emptyTypeListConstant, emptyTypeList, null);

    // Initialize the type parameter of the empty type list to the type object
    // for _Type, which itself refers to the empty type list.
    w.Instructions b = translator.initFunction.body;
    b.global_get(emptyTypeList);
    instantiateConstant(
        translator.initFunction,
        b,
        TypeLiteralConstant(
            InterfaceType(translator.typeClass, Nullability.nonNullable)),
        typeInfo.nullableType);
    b.struct_set(info.struct,
        translator.typeParameterIndex[info.cls!.typeParameters.single]!);
  }

  void finalize() {
    if (lazyConstants) {
      finalizeStrings();
    }
  }

  void finalizeStrings() {
    Uint8List oneByteStringsAsBytes =
        Uint8List.fromList(oneByteStrings.toString().codeUnits);
    assert(Endian.host == Endian.little);
    Uint8List twoByteStringsAsBytes =
        Uint16List.fromList(twoByteStrings.toString().codeUnits)
            .buffer
            .asUint8List();
    Uint8List stringsAsBytes = (BytesBuilder()
          ..add(twoByteStringsAsBytes)
          ..add(oneByteStringsAsBytes))
        .toBytes();

    w.Memory stringMemory =
        m.addMemory(false, stringsAsBytes.length, stringsAsBytes.length);
    m.addDataSegment(stringsAsBytes, stringMemory, 0);
    makeStringFunctionBody(translator.oneByteStringClass, oneByteStringFunction,
        (b) {
      b.i32_load8_u(stringMemory, twoByteStringsAsBytes.length);
    });
    makeStringFunctionBody(translator.twoByteStringClass, twoByteStringFunction,
        (b) {
      b.i32_const(1);
      b.i32_shl();
      b.i32_load16_u(stringMemory, 0);
    });
  }

  /// Create one of the two Wasm functions (one for each string type) called
  /// from every lazily initialized string constant (of that type) to create and
  /// initialize the string.
  ///
  /// The function signature is (i32 offset, i32 length) -> (ref stringClass)
  /// where offset and length are measured in characters and indicate the place
  /// in the corresponding string data segment from which to copy this string.
  w.DefinedFunction makeStringFunction(Class cls) {
    ClassInfo info = translator.classInfo[cls]!;
    w.FunctionType ftype = translator.functionType(
        const [w.NumType.i32, w.NumType.i32], [info.nonNullableType]);
    return m.addFunction(ftype, "makeString (${cls.name})");
  }

  void makeStringFunctionBody(Class cls, w.DefinedFunction function,
      void Function(w.Instructions) emitLoad) {
    ClassInfo info = translator.classInfo[cls]!;
    w.ArrayType arrayType =
        (info.struct.fields.last.type as w.RefType).heapType as w.ArrayType;

    w.Local offset = function.locals[0];
    w.Local length = function.locals[1];
    w.Local array = function.addLocal(
        translator.typeForLocal(w.RefType.def(arrayType, nullable: false)));
    w.Local index = function.addLocal(w.NumType.i32);

    w.Instructions b = function.body;
    b.local_get(length);
    translator.array_new_default(b, arrayType);
    b.local_set(array);

    b.i32_const(0);
    b.local_set(index);
    w.Label loop = b.loop();
    b.local_get(array);
    b.local_get(index);
    b.local_get(offset);
    b.local_get(index);
    b.i32_add();
    emitLoad(b);
    b.array_set(arrayType);
    b.local_get(index);
    b.i32_const(1);
    b.i32_add();
    b.local_tee(index);
    b.local_get(length);
    b.i32_lt_u();
    b.br_if(loop);
    b.end();

    b.i32_const(info.classId);
    b.i32_const(initialIdentityHash);
    b.local_get(array);
    translator.struct_new(b, info);
    b.end();
  }

  /// Makes a type list [ListConstant].
  ListConstant makeTypeList(List<DartType> types) => ListConstant(
      InterfaceType(translator.typeClass, Nullability.nonNullable),
      types.map((t) => TypeLiteralConstant(t)).toList());

  /// Makes a `_NamedParameter` [InstanceConstant].
  InstanceConstant makeNamedParameterConstant(NamedType n) {
    Class namedParameter = translator.namedParameterClass;
    assert(namedParameter.fields[0].name.text == 'name' &&
        namedParameter.fields[1].name.text == 'type' &&
        namedParameter.fields[2].name.text == 'isRequired');
    Reference namedParameterName = namedParameter.fields[0].fieldReference;
    Reference namedParameterType = namedParameter.fields[1].fieldReference;
    Reference namedParameterIsRequired =
        namedParameter.fields[2].fieldReference;
    return InstanceConstant(namedParameter.reference, [], {
      namedParameterName: StringConstant(n.name),
      namedParameterType: TypeLiteralConstant(n.type),
      namedParameterIsRequired: BoolConstant(n.isRequired)
    });
  }

  /// Makes a [ListConstant] of `_NamedParameters` to initialize a [FunctionType].
  ListConstant makeNamedParametersList(FunctionType type) => ListConstant(
      translator.types.namedParameterType,
      type.namedParameters.map(makeNamedParameterConstant).toList());

  /// Ensure that the constant has a Wasm global assigned.
  ///
  /// In eager mode, 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.
  void ensureConstant(Constant constant) {
    ConstantCreator(this).ensureConstant(constant);
  }

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

class ConstantInstantiator extends ConstantVisitor<w.ValueType> {
  final Constants constants;
  final w.DefinedFunction? function;
  final w.Instructions b;
  final w.ValueType expectedType;

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

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

  void instantiate(Constant constant) {
    w.ValueType resultType = constant.accept(this);
    assert(!translator.needsConversion(resultType, expectedType),
        "For $constant: expected $expectedType, got $resultType");
  }

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

  @override
  w.ValueType visitNullConstant(NullConstant node) {
    w.ValueType? expectedType = this.expectedType;
    if (expectedType != translator.voidMarker) {
      if (expectedType.nullable) {
        w.HeapType heapType =
            expectedType is w.RefType ? expectedType.heapType : w.HeapType.data;
        b.ref_null(heapType);
      } else {
        // This only happens in invalid but unreachable code produced by the
        // TFA dead-code elimination.
        b.comment("Non-nullable null constant");
        b.block(const [], [expectedType]);
        b.unreachable();
        b.end();
      }
    }
    return expectedType;
  }

  w.ValueType _maybeBox(w.ValueType wasmType, void Function() pushValue) {
    if (expectedType is w.RefType) {
      ClassInfo info = translator.classInfo[translator.boxedClasses[wasmType]]!;
      b.i32_const(info.classId);
      pushValue();
      translator.struct_new(b, info);
      return info.nonNullableType;
    } else {
      pushValue();
      return wasmType;
    }
  }

  @override
  w.ValueType visitBoolConstant(BoolConstant constant) {
    return _maybeBox(w.NumType.i32, () {
      b.i32_const(constant.value ? 1 : 0);
    });
  }

  @override
  w.ValueType visitIntConstant(IntConstant constant) {
    return _maybeBox(w.NumType.i64, () {
      b.i64_const(constant.value);
    });
  }

  @override
  w.ValueType visitDoubleConstant(DoubleConstant constant) {
    return _maybeBox(w.NumType.f64, () {
      b.f64_const(constant.value);
    });
  }
}

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

  ConstantCreator(this.constants);

  Translator get translator => constants.translator;
  Types get types => translator.types;
  w.Module get m => constants.m;
  bool get lazyConstants => constants.lazyConstants;

  ConstantInfo? ensureConstant(Constant constant) {
    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) {
    assert(!type.nullable);
    if (lazyConstants) {
      // Create uninitialized global and function to initialize it.
      w.DefinedGlobal global =
          m.addGlobal(w.GlobalType(type.withNullability(true)));
      global.initializer.ref_null(type.heapType);
      global.initializer.end();
      w.FunctionType ftype = translator.functionType(const [], [type]);
      w.DefinedFunction function = m.addFunction(ftype, "$constant");
      generator(function, function.body);
      w.Local temp = function.addLocal(translator.typeForLocal(type));
      w.Instructions b2 = function.body;
      b2.local_tee(temp);
      b2.global_set(global);
      b2.local_get(temp);
      translator.convertType(function, temp.type, type);
      b2.end();

      return ConstantInfo(constant, global, function);
    } else {
      // Create global with the constant in its initializer.
      assert(!constants.currentlyCreating);
      constants.currentlyCreating = true;
      w.DefinedGlobal global = m.addGlobal(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? visitStringConstant(StringConstant constant) {
    bool isOneByte = constant.value.codeUnits.every((c) => c <= 255);
    ClassInfo info = translator.classInfo[isOneByte
        ? translator.oneByteStringClass
        : translator.twoByteStringClass]!;
    translator.functions.allocateClass(info.classId);
    w.RefType type = info.nonNullableType;
    return createConstant(constant, type, (function, b) {
      if (lazyConstants) {
        // Copy string contents from linear memory on initialization. The memory
        // is initialized by an active data segment for each string type.
        StringBuffer buffer =
            isOneByte ? constants.oneByteStrings : constants.twoByteStrings;
        int offset = buffer.length;
        int length = constant.value.length;
        buffer.write(constant.value);

        b.i32_const(offset);
        b.i32_const(length);
        b.call(isOneByte
            ? constants.oneByteStringFunction
            : constants.twoByteStringFunction);
      } else {
        w.ArrayType arrayType =
            (info.struct.fields.last.type as w.RefType).heapType as w.ArrayType;

        b.i32_const(info.classId);
        b.i32_const(initialIdentityHash);
        if (constants.stringDataSegments) {
          // Initialize string contents from passive data segment.
          w.DataSegment segment;
          Uint8List bytes;
          if (isOneByte) {
            segment = constants.oneByteStringSegment;
            bytes = Uint8List.fromList(constant.value.codeUnits);
          } else {
            assert(Endian.host == Endian.little);
            segment = constants.twoByteStringSegment;
            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);
          translator.array_init_from_data(b, arrayType, segment);
        } else {
          // Initialize string contents from i32 constants on the stack.
          for (int charCode in constant.value.codeUnits) {
            b.i32_const(charCode);
          }
          translator.array_init(b, arrayType, constant.value.length);
        }
        translator.struct_new(b, info);
      }
    });
  }

  @override
  ConstantInfo? visitInstanceConstant(InstanceConstant constant) {
    Class cls = constant.classNode;
    ClassInfo info = translator.classInfo[cls]!;
    translator.functions.allocateClass(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);
    constant.fieldValues.forEach((reference, subConstant) {
      int index = translator.fieldIndex[reference.asField]!;
      assert(subConstants[index] == null);
      subConstants[index] = subConstant;
      ensureConstant(subConstant);
    });

    // 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, (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);
      }
      translator.struct_new(b, info);
    });
  }

  @override
  ConstantInfo? visitListConstant(ListConstant constant) {
    Constant typeArgConstant = TypeLiteralConstant(constant.typeArgument);
    ensureConstant(typeArgConstant);
    for (Constant subConstant in constant.entries) {
      ensureConstant(subConstant);
    }

    ClassInfo info = translator.classInfo[translator.immutableListClass]!;
    translator.functions.allocateClass(info.classId);
    w.RefType type = info.nonNullableType;
    return createConstant(constant, type, (function, b) {
      w.RefType refType = info.struct.fields.last.type.unpacked as w.RefType;
      w.ArrayType arrayType = refType.heapType as w.ArrayType;
      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 (lazyConstants) {
        // Allocate array and set each entry to the corresponding sub-constant.
        w.Local arrayLocal = function!.addLocal(
            refType.withNullability(!translator.options.localNullability));
        b.i32_const(length);
        translator.array_new_default(b, 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);
        if (arrayLocal.type.nullable) {
          b.ref_as_non_null();
        }
      } 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);
        }
        translator.array_init(b, arrayType, length);
      }
      translator.struct_new(b, info);
    });
  }

  @override
  ConstantInfo? visitMapConstant(MapConstant constant) {
    Constant keyTypeConstant = TypeLiteralConstant(constant.keyType);
    ensureConstant(keyTypeConstant);
    Constant valueTypeConstant = TypeLiteralConstant(constant.valueType);
    ensureConstant(valueTypeConstant);
    List<Constant> dataElements =
        List.generate(constant.entries.length * 2, (i) {
      ConstantMapEntry entry = constant.entries[i >> 1];
      return i.isEven ? entry.key : entry.value;
    });
    ListConstant dataList = ListConstant(const DynamicType(), dataElements);
    ensureConstant(dataList);

    ClassInfo info = translator.classInfo[translator.immutableMapClass]!;
    translator.functions.allocateClass(info.classId);
    w.RefType type = info.nonNullableType;
    return createConstant(constant, type, (function, b) {
      w.RefType indexType =
          info.struct.fields[FieldIndex.hashBaseIndex].type as w.RefType;
      w.RefType dataType =
          info.struct.fields[FieldIndex.hashBaseData].type as w.RefType;

      b.i32_const(info.classId);
      b.i32_const(initialIdentityHash);
      b.ref_null(indexType.heapType); // _index
      b.i64_const(_computeHashMask(constant.entries.length)); // _hashMask
      constants.instantiateConstant(function, b, dataList, dataType); // _data
      b.i64_const(dataElements.length); // _usedData
      b.i64_const(0); // _deletedKeys
      constants.instantiateConstant(
          function, b, keyTypeConstant, constants.typeInfo.nullableType);
      constants.instantiateConstant(
          function, b, valueTypeConstant, constants.typeInfo.nullableType);
      translator.struct_new(b, info);
    });
  }

  @override
  ConstantInfo? visitSetConstant(SetConstant constant) {
    Constant elementTypeConstant = TypeLiteralConstant(constant.typeArgument);
    ensureConstant(elementTypeConstant);
    ListConstant dataList = ListConstant(const DynamicType(), constant.entries);
    ensureConstant(dataList);

    ClassInfo info = translator.classInfo[translator.immutableSetClass]!;
    translator.functions.allocateClass(info.classId);
    w.RefType type = info.nonNullableType;
    return createConstant(constant, type, (function, b) {
      w.RefType indexType =
          info.struct.fields[FieldIndex.hashBaseIndex].type as w.RefType;
      w.RefType dataType =
          info.struct.fields[FieldIndex.hashBaseData].type as w.RefType;

      b.i32_const(info.classId);
      b.i32_const(initialIdentityHash);
      b.ref_null(indexType.heapType); // _index
      b.i64_const(_computeHashMask(constant.entries.length)); // _hashMask
      constants.instantiateConstant(function, b, dataList, dataType); // _data
      b.i64_const(constant.entries.length); // _usedData
      b.i64_const(0); // _deletedKeys
      constants.instantiateConstant(
          function, b, elementTypeConstant, constants.typeInfo.nullableType);
      translator.struct_new(b, info);
    });
  }

  int _computeHashMask(int entries) {
    // This computation of the hash mask follows the computations in
    // [_ImmutableLinkedHashMapMixin._createIndex],
    // [_ImmutableLinkedHashSetMixin._createIndex] and
    // [_HashBase._indexSizeToHashMask].
    const int initialIndexSize = 8;
    final int indexSize = max(entries * 2, initialIndexSize);
    final int hashMask = (1 << (31 - (indexSize - 1).bitLength)) - 1;
    return hashMask;
  }

  @override
  ConstantInfo? visitStaticTearOffConstant(StaticTearOffConstant constant) {
    w.DefinedFunction closureFunction =
        translator.getTearOffFunction(constant.targetReference.asProcedure);
    int parameterCount = closureFunction.type.inputs.length - 1;
    w.StructType struct = translator.closureStructType(parameterCount);
    w.RefType type = w.RefType.def(struct, nullable: false);
    return createConstant(constant, type, (function, b) {
      ClassInfo info = translator.classInfo[translator.functionClass]!;
      translator.functions.allocateClass(info.classId);

      b.i32_const(info.classId);
      b.i32_const(initialIdentityHash);
      b.global_get(translator.globals.dummyGlobal); // Dummy context
      if (lazyConstants) {
        w.DefinedGlobal global = translator.makeFunctionRef(closureFunction);
        b.global_get(global);
      } else {
        b.ref_func(closureFunction);
      }
      translator.struct_new(b, parameterCount);
    });
  }

  ConstantInfo? _makeInterfaceType(
      TypeLiteralConstant constant, InterfaceType type, ClassInfo info) {
    ListConstant typeArgs = constants.makeTypeList(type.typeArguments);
    ensureConstant(typeArgs);
    return createConstant(constant, info.nonNullableType, (function, b) {
      ClassInfo typeInfo = translator.classInfo[type.classNode]!;
      w.ValueType typeListExpectedType = info
          .struct.fields[FieldIndex.interfaceTypeTypeArguments].type.unpacked;

      b.i32_const(info.classId);
      b.i32_const(initialIdentityHash);
      types.encodeNullability(b, type);
      b.i64_const(typeInfo.classId);
      constants.instantiateConstant(
          function, b, typeArgs, typeListExpectedType);
      translator.struct_new(b, info);
    });
  }

  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);
      types.encodeNullability(b, type);
      constants.instantiateConstant(
          function, b, typeArgument, types.nonNullableTypeType);
      translator.struct_new(b, info);
    });
  }

  ConstantInfo? _makeFunctionType(
      TypeLiteralConstant constant, FunctionType type, ClassInfo info) {
    TypeLiteralConstant returnTypeConstant =
        TypeLiteralConstant(type.returnType);
    ListConstant positionalParametersConstant =
        constants.makeTypeList(type.positionalParameters);
    IntConstant requiredParameterCountConstant =
        IntConstant(type.requiredParameterCount);
    ListConstant namedParametersConstant =
        constants.makeNamedParametersList(type);
    ensureConstant(returnTypeConstant);
    ensureConstant(positionalParametersConstant);
    ensureConstant(requiredParameterCountConstant);
    ensureConstant(namedParametersConstant);
    return createConstant(constant, info.nonNullableType, (function, b) {
      b.i32_const(info.classId);
      b.i32_const(initialIdentityHash);
      types.encodeNullability(b, type);
      constants.instantiateConstant(
          function, b, returnTypeConstant, types.nonNullableTypeType);
      constants.instantiateConstant(function, b, positionalParametersConstant,
          types.typeListExpectedType);
      constants.instantiateConstant(
          function, b, requiredParameterCountConstant, w.NumType.i64);
      constants.instantiateConstant(function, b, namedParametersConstant,
          types.namedParametersExpectedType);
      translator.struct_new(b, info);
    });
  }

  @override
  ConstantInfo? visitTypeLiteralConstant(TypeLiteralConstant constant) {
    DartType type = constant.type;

    ClassInfo info = translator.classInfo[types.classForType(type)]!;
    translator.functions.allocateClass(info.classId);
    if (type is InterfaceType) {
      return _makeInterfaceType(constant, type, info);
    } else if (type is FutureOrType) {
      return _makeFutureOrType(constant, type, info);
    } else if (type is FunctionType) {
      if (types.isGenericFunction(type)) {
        // TODO(joshualitt): implement generic function types and share most of
        // the logic with _makeFunctionType.
        return createConstant(constant, info.nonNullableType, (function, b) {
          b.i32_const(info.classId);
          b.i32_const(initialIdentityHash);
          types.encodeNullability(b, type);
          translator.struct_new(b, info);
        });
      } else {
        return _makeFunctionType(constant, type, info);
      }
    } else if (type is TypeParameterType) {
      // TODO(joshualitt): Handle generic function types.
      assert(!types.isGenericFunctionTypeParameter(type));
      int environmentIndex =
          types.interfaceTypeEnvironment.lookup(type.parameter);
      return createConstant(constant, info.nonNullableType, (function, b) {
        b.i32_const(info.classId);
        b.i32_const(initialIdentityHash);
        types.encodeNullability(b, type);
        b.i32_const(environmentIndex);
        translator.struct_new(b, info);
      });
    } else {
      assert(type is VoidType ||
          type is NeverType ||
          type is NullType ||
          type is DynamicType);
      return createConstant(constant, info.nonNullableType, (function, b) {
        b.i32_const(info.classId);
        b.i32_const(initialIdentityHash);
        types.encodeNullability(b, type);
        translator.struct_new(b, info);
      });
    }
  }
}
