// Copyright (c) 2019, 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.

// @dart=2.9

library vm.transformations.ffi_use_sites;

import 'package:front_end/src/api_unstable/vm.dart'
    show
        messageFfiExceptionalReturnNull,
        messageFfiExpectedConstant,
        messageFfiLeafCallMustNotReturnHandle,
        messageFfiLeafCallMustNotTakeHandle,
        templateFfiDartTypeMismatch,
        templateFfiExpectedConstantArg,
        templateFfiExpectedExceptionalReturn,
        templateFfiExpectedNoExceptionalReturn,
        templateFfiExtendsOrImplementsSealedClass,
        templateFfiNotStatic,
        templateFfiTypeInvalid,
        templateFfiTypeMismatch;

import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/core_types.dart';
import 'package:kernel/library_index.dart' show LibraryIndex;
import 'package:kernel/reference_from_index.dart';
import 'package:kernel/target/targets.dart' show DiagnosticReporter;
import 'package:kernel/type_algebra.dart' show Substitution;
import 'package:kernel/type_environment.dart';

import 'ffi.dart'
    show
        NativeType,
        FfiTransformer,
        nativeTypeSizes,
        WORD_SIZE,
        UNKNOWN,
        wordSize;

/// Checks and replaces calls to dart:ffi compound fields and methods.
void transformLibraries(
    Component component,
    CoreTypes coreTypes,
    ClassHierarchy hierarchy,
    List<Library> libraries,
    DiagnosticReporter diagnosticReporter,
    ReferenceFromIndex referenceFromIndex) {
  final index = new LibraryIndex(
      component, ["dart:ffi", "dart:_internal", "dart:typed_data"]);
  if (!index.containsLibrary("dart:ffi")) {
    // TODO: This check doesn't make sense: "dart:ffi" is always loaded/created
    // for the VM target.
    // If dart:ffi is not loaded, do not do the transformation.
    return;
  }
  if (index.tryGetClass('dart:ffi', 'NativeFunction') == null) {
    // If dart:ffi is not loaded (for real): do not do the transformation.
    return;
  }
  final transformer = new _FfiUseSiteTransformer(
      index, coreTypes, hierarchy, diagnosticReporter, referenceFromIndex);
  libraries.forEach(transformer.visitLibrary);
}

/// Checks and replaces calls to dart:ffi compound fields and methods.
class _FfiUseSiteTransformer extends FfiTransformer {
  StaticTypeContext _staticTypeContext;

  bool get isFfiLibrary => currentLibrary == ffiLibrary;

  // Used to create private top-level fields with unique names for each
  // callback.
  int callbackCount = 0;

  _FfiUseSiteTransformer(
      LibraryIndex index,
      CoreTypes coreTypes,
      ClassHierarchy hierarchy,
      DiagnosticReporter diagnosticReporter,
      ReferenceFromIndex referenceFromIndex)
      : super(index, coreTypes, hierarchy, diagnosticReporter,
            referenceFromIndex) {}

  @override
  TreeNode visitLibrary(Library node) {
    callbackCount = 0;
    return super.visitLibrary(node);
  }

  @override
  visitClass(Class node) {
    try {
      _ensureNotExtendsOrImplementsSealedClass(node);
      return super.visitClass(node);
    } on _FfiStaticTypeError {
      // It's OK to swallow the exception because the diagnostics issued will
      // cause compilation to fail. By continuing, we can report more
      // diagnostics before compilation ends.
      return super.visitClass(node);
    }
  }

  @override
  visitField(Field node) {
    _staticTypeContext = new StaticTypeContext(node, env);
    var result = super.visitField(node);
    _staticTypeContext = null;
    return result;
  }

  @override
  visitConstructor(Constructor node) {
    _staticTypeContext = new StaticTypeContext(node, env);
    var result = super.visitConstructor(node);
    _staticTypeContext = null;
    return result;
  }

  @override
  visitProcedure(Procedure node) {
    if (isFfiLibrary && node.isExtensionMember) {
      if (node == allocationTearoff ||
          node == asFunctionTearoff ||
          node == lookupFunctionTearoff) {
        // Skip static checks and transformation for the tearoffs.
        return node;
      }
    }

    _staticTypeContext = new StaticTypeContext(node, env);
    final result = super.visitProcedure(node);
    _staticTypeContext = null;
    return result;
  }

  @override
  visitStaticInvocation(StaticInvocation node) {
    super.visitStaticInvocation(node);

    final Member target = node.target;
    try {
      if (target == structPointerRef ||
          target == structPointerElemAt ||
          target == unionPointerRef ||
          target == unionPointerElemAt) {
        final DartType nativeType = node.arguments.types[0];

        _ensureNativeTypeValid(nativeType, node, allowCompounds: true);

        return _replaceRef(node);
      } else if (target == structArrayElemAt || target == unionArrayElemAt) {
        final DartType nativeType = node.arguments.types[0];

        _ensureNativeTypeValid(nativeType, node, allowCompounds: true);

        return _replaceRefArray(node);
      } else if (target == arrayArrayElemAt) {
        final DartType nativeType = node.arguments.types[0];

        _ensureNativeTypeValid(nativeType, node,
            allowInlineArray: true, allowCompounds: true);

        return _replaceArrayArrayElemAt(node);
      } else if (target == arrayArrayAssignAt) {
        final DartType nativeType = node.arguments.types[0];

        _ensureNativeTypeValid(nativeType, node,
            allowInlineArray: true, allowCompounds: true);

        return _replaceArrayArrayElemAt(node, setter: true);
      } else if (target == sizeOfMethod) {
        final DartType nativeType = node.arguments.types[0];

        _ensureNativeTypeValid(nativeType, node, allowCompounds: true);

        if (nativeType is InterfaceType) {
          Expression inlineSizeOf = _inlineSizeOf(nativeType);
          if (inlineSizeOf != null) {
            return inlineSizeOf;
          }
        }
      } else if (target == lookupFunctionMethod) {
        final nativeType = InterfaceType(
            nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);
        final DartType dartType = node.arguments.types[1];

        _ensureNativeTypeValid(nativeType, node);
        _ensureNativeTypeToDartType(nativeType, dartType, node);
        _ensureIsLeafIsConst(node);
        _ensureLeafCallDoesNotUseHandles(nativeType, node);

        final replacement = _replaceLookupFunction(node);

        if (dartType is FunctionType) {
          final returnType = dartType.returnType;
          if (returnType is InterfaceType) {
            final clazz = returnType.classNode;
            if (clazz.superclass == structClass ||
                clazz.superclass == unionClass) {
              return _invokeCompoundConstructor(replacement, clazz);
            }
          }
        }
        return replacement;
      } else if (target == asFunctionMethod) {
        final dartType = node.arguments.types[1];
        final DartType nativeType = InterfaceType(
            nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);

        _ensureNativeTypeValid(nativeType, node);
        _ensureNativeTypeToDartType(nativeType, dartType, node);
        _ensureIsLeafIsConst(node);
        _ensureLeafCallDoesNotUseHandles(nativeType, node);

        final DartType nativeSignature =
            (nativeType as InterfaceType).typeArguments[0];

        bool isLeaf = _getIsLeafBoolean(node);
        if (isLeaf == null) {
          isLeaf = false;
        }

        // Inline function body to make all type arguments instatiated.
        final replacement = StaticInvocation(
            asFunctionInternal,
            Arguments([node.arguments.positional[0], BoolLiteral(isLeaf)],
                types: [dartType, nativeSignature]));

        if (dartType is FunctionType) {
          final returnType = dartType.returnType;
          if (returnType is InterfaceType) {
            final clazz = returnType.classNode;
            if (clazz.superclass == structClass ||
                clazz.superclass == unionClass) {
              return _invokeCompoundConstructor(replacement, clazz);
            }
          }
        }
        return replacement;
      } else if (target == fromFunctionMethod) {
        final DartType nativeType = InterfaceType(
            nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);
        final Expression func = node.arguments.positional[0];
        final DartType dartType = func.getStaticType(_staticTypeContext);

        _ensureIsStaticFunction(func);

        _ensureNativeTypeValid(nativeType, node);
        _ensureNativeTypeToDartType(nativeType, dartType, node);

        final funcType = dartType as FunctionType;

        // Check `exceptionalReturn`'s type.
        final Class expectedReturnClass =
            ((node.arguments.types[0] as FunctionType).returnType
                    as InterfaceType)
                .classNode;
        final NativeType expectedReturn = getType(expectedReturnClass);

        if (expectedReturn == NativeType.kVoid ||
            expectedReturn == NativeType.kPointer ||
            expectedReturn == NativeType.kHandle ||
            expectedReturnClass.superclass == structClass ||
            expectedReturnClass.superclass == unionClass) {
          if (node.arguments.positional.length > 1) {
            diagnosticReporter.report(
                templateFfiExpectedNoExceptionalReturn.withArguments(
                    funcType.returnType, currentLibrary.isNonNullableByDefault),
                node.fileOffset,
                1,
                node.location?.file);
            return node;
          }
          node.arguments.positional.add(NullLiteral()..parent = node);
        } else {
          // The exceptional return value is not optional for other return
          // types.
          if (node.arguments.positional.length < 2) {
            diagnosticReporter.report(
                templateFfiExpectedExceptionalReturn.withArguments(
                    funcType.returnType, currentLibrary.isNonNullableByDefault),
                node.fileOffset,
                1,
                node.location?.file);
            return node;
          }

          final Expression exceptionalReturn = node.arguments.positional[1];

          // The exceptional return value must be a constant so that it be
          // referenced by precompiled trampoline's object pool.
          if (exceptionalReturn is! BasicLiteral &&
              !(exceptionalReturn is ConstantExpression &&
                  exceptionalReturn.constant is PrimitiveConstant)) {
            diagnosticReporter.report(messageFfiExpectedConstant,
                node.fileOffset, 1, node.location?.file);
            return node;
          }

          // Moreover it may not be null.
          if (exceptionalReturn is NullLiteral ||
              (exceptionalReturn is ConstantExpression &&
                  exceptionalReturn.constant is NullConstant)) {
            diagnosticReporter.report(messageFfiExceptionalReturnNull,
                node.fileOffset, 1, node.location?.file);
            return node;
          }

          final DartType returnType =
              exceptionalReturn.getStaticType(_staticTypeContext);

          if (!env.isSubtypeOf(returnType, funcType.returnType,
              SubtypeCheckMode.ignoringNullabilities)) {
            diagnosticReporter.report(
                templateFfiDartTypeMismatch.withArguments(returnType,
                    funcType.returnType, currentLibrary.isNonNullableByDefault),
                exceptionalReturn.fileOffset,
                1,
                exceptionalReturn.location?.file);
            return node;
          }
        }

        final replacement = _replaceFromFunction(node);

        final compoundClasses = funcType.positionalParameters
            .whereType<InterfaceType>()
            .map((t) => t.classNode)
            .where((c) =>
                c.superclass == structClass || c.superclass == unionClass)
            .toList();
        return _invokeCompoundConstructors(replacement, compoundClasses);
      } else if (target == allocateMethod) {
        final DartType nativeType = node.arguments.types[0];

        _ensureNativeTypeValid(nativeType, node, allowCompounds: true);

        // Inline the body to get rid of a generic invocation of sizeOf.
        // TODO(http://dartbug.com/39964): Add `allignmentOf<T>()` call.
        Expression sizeInBytes = _inlineSizeOf(nativeType);
        if (sizeInBytes != null) {
          if (node.arguments.positional.length == 2) {
            sizeInBytes = multiply(node.arguments.positional[1], sizeInBytes);
          }
          final FunctionType allocateFunctionType =
              allocatorAllocateMethod.getterType as FunctionType;
          return InstanceInvocation(
              InstanceAccessKind.Instance,
              node.arguments.positional[0],
              allocatorAllocateMethod.name,
              Arguments([sizeInBytes], types: node.arguments.types),
              interfaceTarget: allocatorAllocateMethod,
              functionType: Substitution.fromPairs(
                      allocateFunctionType.typeParameters, node.arguments.types)
                  .substituteType(allocateFunctionType
                      .withoutTypeParameters) as FunctionType);
        }
      }
    } on _FfiStaticTypeError {
      // It's OK to swallow the exception because the diagnostics issued will
      // cause compilation to fail. By continuing, we can report more
      // diagnostics before compilation ends.
    }

    return node;
  }

  /// Prevents the struct from being tree-shaken in TFA by invoking its
  /// constructor in a `_nativeEffect` expression.
  Expression _invokeCompoundConstructor(
      Expression nestedExpression, Class compoundClass) {
    final constructor = compoundClass.constructors
        .firstWhere((c) => c.name == Name("#fromTypedDataBase"));
    return BlockExpression(
        Block([
          ExpressionStatement(StaticInvocation(
              nativeEffectMethod,
              Arguments([
                ConstructorInvocation(
                    constructor,
                    Arguments([
                      StaticInvocation(
                          uint8ListFactory,
                          Arguments([
                            ConstantExpression(IntConstant(1)),
                          ]))
                        ..fileOffset = nestedExpression.fileOffset,
                    ]))
                  ..fileOffset = nestedExpression.fileOffset
              ])))
        ]),
        nestedExpression)
      ..fileOffset = nestedExpression.fileOffset;
  }

  Expression _invokeCompoundConstructors(
          Expression nestedExpression, List<Class> compoundClasses) =>
      compoundClasses
          .distinct()
          .fold(nestedExpression, _invokeCompoundConstructor);

  Expression _inlineSizeOf(InterfaceType nativeType) {
    final Class nativeClass = nativeType.classNode;
    final NativeType nt = getType(nativeClass);
    if (nt == null) {
      // User-defined compounds.
      final Procedure sizeOfGetter = nativeClass.procedures
          .firstWhere((function) => function.name == Name('#sizeOf'));
      return StaticGet(sizeOfGetter);
    }
    final int size = nativeTypeSizes[nt.index];
    if (size == WORD_SIZE) {
      return runtimeBranchOnLayout(wordSize);
    }
    if (size != UNKNOWN) {
      return ConstantExpression(
          IntConstant(size),
          InterfaceType(listClass, Nullability.legacy,
              [InterfaceType(intClass, Nullability.legacy)]));
    }
    // Size unknown.
    return null;
  }

  // We need to replace calls to 'DynamicLibrary.lookupFunction' with explicit
  // Kernel, because we cannot have a generic call to 'asFunction' in its body.
  //
  // Above, in 'visitStaticInvocation', we ensure that the type arguments to
  // 'lookupFunction' are constants, so by inlining the call to 'asFunction' at
  // the call-site, we ensure that there are no generic calls to 'asFunction'.
  Expression _replaceLookupFunction(StaticInvocation node) {
    // The generated code looks like:
    //
    // _asFunctionInternal<DS, NS>(lookup<NativeFunction<NS>>(symbolName),
    //     isLeaf)
    final DartType nativeSignature = node.arguments.types[0];
    final DartType dartSignature = node.arguments.types[1];

    final List<DartType> lookupTypeArgs = [
      InterfaceType(nativeFunctionClass, Nullability.legacy, [nativeSignature])
    ];
    final Arguments lookupArgs =
        Arguments([node.arguments.positional[1]], types: lookupTypeArgs);
    final FunctionType lookupFunctionType =
        libraryLookupMethod.getterType as FunctionType;

    final Expression lookupResult = InstanceInvocation(
        InstanceAccessKind.Instance,
        node.arguments.positional[0],
        libraryLookupMethod.name,
        lookupArgs,
        interfaceTarget: libraryLookupMethod,
        functionType: Substitution.fromPairs(
                    lookupFunctionType.typeParameters, lookupTypeArgs)
                .substituteType(lookupFunctionType.withoutTypeParameters)
            as FunctionType);

    bool isLeaf = _getIsLeafBoolean(node);
    if (isLeaf == null) {
      isLeaf = false;
    }

    return StaticInvocation(
        asFunctionInternal,
        Arguments([lookupResult, BoolLiteral(isLeaf)],
            types: [dartSignature, nativeSignature]));
  }

  // We need to rewrite calls to 'fromFunction' into two calls, representing the
  // compile-time and run-time aspects of creating the closure:
  //
  // final dynamic _#ffiCallback0 = Pointer.fromFunction<T>(f, e) =>
  //   _pointerFromFunction<NativeFunction<T>>(
  //     _nativeCallbackFunction<T>(f, e));
  //
  //  ... _#ffiCallback0 ...
  //
  // We must implement this as a Kernel rewrite because <T> must be a
  // compile-time constant to any invocation of '_nativeCallbackFunction'.
  //
  // Creating this closure requires a runtime call, so we save the result in a
  // synthetic top-level field to avoid recomputing it.
  Expression _replaceFromFunction(StaticInvocation node) {
    final nativeFunctionType = InterfaceType(
        nativeFunctionClass, Nullability.legacy, node.arguments.types);
    var name = Name("_#ffiCallback${callbackCount++}", currentLibrary);
    var getterReference = currentLibraryIndex?.lookupGetterReference(name);
    final Field field = Field.immutable(name,
        type: InterfaceType(
            pointerClass, Nullability.legacy, [nativeFunctionType]),
        initializer: StaticInvocation(
            pointerFromFunctionProcedure,
            Arguments([
              StaticInvocation(nativeCallbackFunctionProcedure, node.arguments)
            ], types: [
              nativeFunctionType
            ])),
        isStatic: true,
        isFinal: true,
        fileUri: currentLibrary.fileUri,
        getterReference: getterReference)
      ..fileOffset = node.fileOffset;
    currentLibrary.addField(field);
    return StaticGet(field);
  }

  Expression _replaceRef(StaticInvocation node) {
    final dartType = node.arguments.types[0];
    final clazz = (dartType as InterfaceType).classNode;
    final constructor = clazz.constructors
        .firstWhere((c) => c.name == Name("#fromTypedDataBase"));
    Expression pointer = NullCheck(node.arguments.positional[0]);
    if (node.arguments.positional.length == 2) {
      pointer = InstanceInvocation(
          InstanceAccessKind.Instance,
          pointer,
          offsetByMethod.name,
          Arguments([
            multiply(node.arguments.positional[1], _inlineSizeOf(dartType))
          ]),
          interfaceTarget: offsetByMethod,
          functionType:
              Substitution.fromPairs(pointerClass.typeParameters, [dartType])
                  .substituteType(offsetByMethod.getterType) as FunctionType);
    }
    return ConstructorInvocation(constructor, Arguments([pointer]));
  }

  Expression _replaceRefArray(StaticInvocation node) {
    final dartType = node.arguments.types[0];
    final clazz = (dartType as InterfaceType).classNode;
    final constructor = clazz.constructors
        .firstWhere((c) => c.name == Name("#fromTypedDataBase"));

    final typedDataBasePrime = typedDataBaseOffset(
        getArrayTypedDataBaseField(NullCheck(node.arguments.positional[0])),
        multiply(node.arguments.positional[1], _inlineSizeOf(dartType)),
        _inlineSizeOf(dartType),
        dartType,
        node.fileOffset);

    return ConstructorInvocation(constructor, Arguments([typedDataBasePrime]));
  }

  /// Generates an expression that returns a new `Array<dartType>`.
  ///
  /// Sample input getter:
  /// ```
  /// this<Array<T>>[index]
  /// ```
  ///
  /// Sample output getter:
  ///
  /// ```
  /// Array #array = this!;
  /// int #index = index!;
  /// #array._checkIndex(#index);
  /// int #singleElementSize = _inlineSizeOf<innermost(T)>();
  /// int #elementSize = #array.nestedDimensionsFlattened * #singleElementSize;
  /// int #offset = #elementSize * #index;
  ///
  /// new Array<T>._(
  ///   typedDataBaseOffset(#array._typedDataBase, #offset, #elementSize),
  ///   #array.nestedDimensionsFirst,
  ///   #array.nestedDimensionsRest
  /// )
  /// ```
  ///
  /// Sample input setter:
  /// ```
  /// this<Array<T>>[index] = value
  /// ```
  ///
  /// Sample output setter:
  ///
  /// ```
  /// Array #array = this!;
  /// int #index = index!;
  /// #array._checkIndex(#index);
  /// int #singleElementSize = _inlineSizeOf<innermost(T)>();
  /// int #elementSize = #array.nestedDimensionsFlattened * #singleElementSize;
  /// int #offset = #elementSize * #index;
  ///
  /// _memCopy(
  ///   #array._typedDataBase, #offset, value._typedDataBase, 0, #elementSize)
  /// ```
  Expression _replaceArrayArrayElemAt(StaticInvocation node,
      {bool setter: false}) {
    final dartType = node.arguments.types[0];
    final elementType = arraySingleElementType(dartType as InterfaceType);

    final arrayVar = VariableDeclaration("#array",
        initializer: NullCheck(node.arguments.positional[0]),
        type: InterfaceType(arrayClass, Nullability.nonNullable))
      ..fileOffset = node.fileOffset;
    final indexVar = VariableDeclaration("#index",
        initializer: NullCheck(node.arguments.positional[1]),
        type: coreTypes.intNonNullableRawType)
      ..fileOffset = node.fileOffset;
    final singleElementSizeVar = VariableDeclaration("#singleElementSize",
        initializer: _inlineSizeOf(elementType),
        type: coreTypes.intNonNullableRawType)
      ..fileOffset = node.fileOffset;
    final elementSizeVar = VariableDeclaration("#elementSize",
        initializer: multiply(
            VariableGet(singleElementSizeVar),
            InstanceGet(InstanceAccessKind.Instance, VariableGet(arrayVar),
                arrayNestedDimensionsFlattened.name,
                interfaceTarget: arrayNestedDimensionsFlattened,
                resultType: arrayNestedDimensionsFlattened.type)),
        type: coreTypes.intNonNullableRawType)
      ..fileOffset = node.fileOffset;
    final offsetVar = VariableDeclaration("#offset",
        initializer:
            multiply(VariableGet(elementSizeVar), VariableGet(indexVar)),
        type: coreTypes.intNonNullableRawType)
      ..fileOffset = node.fileOffset;

    final checkIndexAndLocalVars = Block([
      arrayVar,
      indexVar,
      ExpressionStatement(InstanceInvocation(
          InstanceAccessKind.Instance,
          VariableGet(arrayVar),
          arrayCheckIndex.name,
          Arguments([VariableGet(indexVar)]),
          interfaceTarget: arrayCheckIndex,
          functionType: arrayCheckIndex.getterType as FunctionType)),
      singleElementSizeVar,
      elementSizeVar,
      offsetVar
    ]);

    if (!setter) {
      // `[]`
      return BlockExpression(
          checkIndexAndLocalVars,
          ConstructorInvocation(
              arrayConstructor,
              Arguments([
                typedDataBaseOffset(
                    getArrayTypedDataBaseField(VariableGet(arrayVar)),
                    VariableGet(offsetVar),
                    VariableGet(elementSizeVar),
                    dartType,
                    node.fileOffset),
                InstanceGet(InstanceAccessKind.Instance, VariableGet(arrayVar),
                    arrayNestedDimensionsFirst.name,
                    interfaceTarget: arrayNestedDimensionsFirst,
                    resultType: arrayNestedDimensionsFirst.type),
                InstanceGet(InstanceAccessKind.Instance, VariableGet(arrayVar),
                    arrayNestedDimensionsRest.name,
                    interfaceTarget: arrayNestedDimensionsRest,
                    resultType: arrayNestedDimensionsRest.type)
              ], types: [
                dartType
              ])));
    }

    // `[]=`
    return BlockExpression(
        checkIndexAndLocalVars,
        StaticInvocation(
            memCopy,
            Arguments([
              getArrayTypedDataBaseField(
                  VariableGet(arrayVar), node.fileOffset),
              VariableGet(offsetVar),
              getArrayTypedDataBaseField(
                  node.arguments.positional[2], node.fileOffset),
              ConstantExpression(IntConstant(0)),
              VariableGet(elementSizeVar),
            ]))
          ..fileOffset = node.fileOffset);
  }

  @override
  visitInstanceInvocation(InstanceInvocation node) {
    super.visitInstanceInvocation(node);

    final Member target = node.interfaceTarget;
    try {
      if (target == elementAtMethod) {
        final DartType pointerType =
            node.receiver.getStaticType(_staticTypeContext);
        final DartType nativeType = _pointerTypeGetTypeArg(pointerType);

        _ensureNativeTypeValid(nativeType, node, allowCompounds: true);

        Expression inlineSizeOf = _inlineSizeOf(nativeType);
        if (inlineSizeOf != null) {
          // Generates `receiver.offsetBy(inlineSizeOfExpression)`.
          return InstanceInvocation(
              InstanceAccessKind.Instance,
              node.receiver,
              offsetByMethod.name,
              Arguments(
                  [multiply(node.arguments.positional.single, inlineSizeOf)]),
              interfaceTarget: offsetByMethod,
              functionType:
                  Substitution.fromInterfaceType(pointerType as InterfaceType)
                          .substituteType(offsetByMethod.getterType)
                      as FunctionType);
        }
      }
    } on _FfiStaticTypeError {
      // It's OK to swallow the exception because the diagnostics issued will
      // cause compilation to fail. By continuing, we can report more
      // diagnostics before compilation ends.
    }

    return node;
  }

  DartType _pointerTypeGetTypeArg(DartType pointerType) {
    return pointerType is InterfaceType ? pointerType.typeArguments[0] : null;
  }

  void _ensureNativeTypeToDartType(
      DartType nativeType, DartType dartType, Expression node,
      {bool allowHandle: false}) {
    final DartType correspondingDartType = convertNativeTypeToDartType(
        nativeType,
        allowCompounds: true,
        allowHandle: allowHandle);
    if (dartType == correspondingDartType) return;
    if (env.isSubtypeOf(correspondingDartType, dartType,
        SubtypeCheckMode.ignoringNullabilities)) {
      return;
    }
    diagnosticReporter.report(
        templateFfiTypeMismatch.withArguments(dartType, correspondingDartType,
            nativeType, currentLibrary.isNonNullableByDefault),
        node.fileOffset,
        1,
        node.location?.file);
    throw _FfiStaticTypeError();
  }

  void _ensureNativeTypeValid(DartType nativeType, Expression node,
      {bool allowHandle: false,
      bool allowCompounds: false,
      bool allowInlineArray = false}) {
    if (!_nativeTypeValid(nativeType,
        allowCompounds: allowCompounds,
        allowHandle: allowHandle,
        allowInlineArray: allowInlineArray)) {
      diagnosticReporter.report(
          templateFfiTypeInvalid.withArguments(
              nativeType, currentLibrary.isNonNullableByDefault),
          node.fileOffset,
          1,
          node.location?.file);
      throw _FfiStaticTypeError();
    }
  }

  /// The Dart type system does not enforce that NativeFunction return and
  /// parameter types are only NativeTypes, so we need to check this.
  bool _nativeTypeValid(DartType nativeType,
      {bool allowCompounds: false,
      bool allowHandle = false,
      bool allowInlineArray = false}) {
    return convertNativeTypeToDartType(nativeType,
            allowCompounds: allowCompounds,
            allowHandle: allowHandle,
            allowInlineArray: allowInlineArray) !=
        null;
  }

  void _ensureIsStaticFunction(Expression node) {
    if ((node is StaticGet && node.target is Procedure) ||
        (node is ConstantExpression &&
            node.constant is StaticTearOffConstant)) {
      return;
    }
    diagnosticReporter.report(
        templateFfiNotStatic.withArguments(fromFunctionMethod.name.text),
        node.fileOffset,
        1,
        node.location?.file);
    throw _FfiStaticTypeError();
  }

  /// Returns the class that should not be implemented or extended.
  ///
  /// If the superclass is not sealed, returns `null`.
  Class _extendsOrImplementsSealedClass(Class klass) {
    // Classes in dart:ffi themselves can extend FFI classes.
    if (klass == arrayClass ||
        klass == arraySizeClass ||
        klass == compoundClass ||
        klass == opaqueClass ||
        klass == structClass ||
        klass == unionClass ||
        nativeTypesClasses.contains(klass)) {
      return null;
    }

    // The Opaque and Struct classes can be extended, but subclasses
    // cannot be (nor implemented).
    final onlyDirectExtendsClasses = [opaqueClass, structClass, unionClass];
    final superClass = klass.superclass;
    for (final onlyDirectExtendsClass in onlyDirectExtendsClasses) {
      if (hierarchy.isSubtypeOf(klass, onlyDirectExtendsClass)) {
        if (superClass == onlyDirectExtendsClass) {
          // Directly extending is fine.
          return null;
        } else {
          return superClass;
        }
      }
    }

    for (final parent in nativeTypesClasses) {
      if (hierarchy.isSubtypeOf(klass, parent)) {
        return parent;
      }
    }

    return null;
  }

  void _ensureNotExtendsOrImplementsSealedClass(Class klass) {
    final Class extended = _extendsOrImplementsSealedClass(klass);
    if (extended != null) {
      diagnosticReporter.report(
          templateFfiExtendsOrImplementsSealedClass
              .withArguments(extended.name),
          klass.fileOffset,
          1,
          klass.location?.file);
      throw _FfiStaticTypeError();
    }
  }

  // Returns
  // - `true` if leaf
  // - `false` if not leaf
  // - `null` if the expression is not valid (e.g. non-const bool, null)
  bool _getIsLeafBoolean(StaticInvocation node) {
    for (final named in node.arguments.named) {
      if (named.name == 'isLeaf') {
        final expr = named.value;
        if (expr is BoolLiteral) {
          return expr.value;
        } else if (expr is ConstantExpression) {
          final constant = expr.constant;
          if (constant is BoolConstant) {
            return constant.value;
          }
        }
        // isLeaf is passed some invalid value.
        return null;
      }
    }
    // isLeaf defaults to false.
    return false;
  }

  void _ensureIsLeafIsConst(StaticInvocation node) {
    final isLeaf = _getIsLeafBoolean(node);
    if (isLeaf == null) {
      diagnosticReporter.report(
          templateFfiExpectedConstantArg.withArguments('isLeaf'),
          node.fileOffset,
          1,
          node.location?.file);
      // Throw so we don't get another error about not replacing
      // `lookupFunction`, which will shadow the above error.
      throw _FfiStaticTypeError();
    }
  }

  void _ensureLeafCallDoesNotUseHandles(
      InterfaceType nativeType, StaticInvocation node) {
    // Handles are only disallowed for leaf calls.
    final isLeaf = _getIsLeafBoolean(node);
    if (isLeaf == null || isLeaf == false) {
      return;
    }

    // Check if return type is Handle.
    final functionType = nativeType.typeArguments[0];
    if (functionType is FunctionType) {
      final returnType = functionType.returnType;
      if (returnType is InterfaceType) {
        if (returnType.classNode == handleClass) {
          diagnosticReporter.report(messageFfiLeafCallMustNotReturnHandle,
              node.fileOffset, 1, node.location?.file);
        }
      }
      // Check if any of the argument types are Handle.
      for (InterfaceType param in functionType.positionalParameters) {
        if (param.classNode == handleClass) {
          diagnosticReporter.report(messageFfiLeafCallMustNotTakeHandle,
              node.fileOffset, 1, node.location?.file);
        }
      }
    }
  }
}

/// Used internally for abnormal control flow to prevent cascading error
/// messages.
class _FfiStaticTypeError implements Exception {}

extension<T extends Object> on List<T> {
  /// Order-preserved distinct elements.
  List<T> distinct() {
    final seen = <T>{};
    return where((element) => seen.add(element)).toList();
  }
}
