// 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.

library vm.transformations.ffi_use_sites;

import 'package:front_end/src/api_unstable/vm.dart'
    show
        messageFfiExceptionalReturnNull,
        messageFfiExpectedConstant,
        templateFfiDartTypeMismatch,
        templateFfiEmptyStruct,
        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_environment.dart';

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

/// Checks and replaces calls to dart:ffi struct fields and methods.
void transformLibraries(
    Component component,
    CoreTypes coreTypes,
    ClassHierarchy hierarchy,
    List<Library> libraries,
    DiagnosticReporter diagnosticReporter,
    FfiTransformerData ffiTransformerData,
    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,
      ffiTransformerData.replacedGetters,
      ffiTransformerData.replacedSetters,
      ffiTransformerData.emptyStructs);
  libraries.forEach(transformer.visitLibrary);
}

/// Checks and replaces calls to dart:ffi struct fields and methods.
class _FfiUseSiteTransformer extends FfiTransformer {
  final Map<Field, Procedure> replacedGetters;
  final Map<Field, Procedure> replacedSetters;
  final Set<Class> emptyStructs;
  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,
      this.replacedGetters,
      this.replacedSetters,
      this.emptyStructs)
      : 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
  visitPropertyGet(PropertyGet node) {
    super.visitPropertyGet(node);

    final Procedure replacedWith = replacedGetters[node.interfaceTarget];
    if (replacedWith != null) {
      node = PropertyGet(node.receiver, replacedWith.name, replacedWith);
    }

    return node;
  }

  @override
  visitPropertySet(PropertySet node) {
    super.visitPropertySet(node);

    final Procedure replacedWith = replacedSetters[node.interfaceTarget];
    if (replacedWith != null) {
      node = PropertySet(
          node.receiver, replacedWith.name, node.value, replacedWith);
    }

    return node;
  }

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

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

        _ensureNativeTypeValid(nativeType, node, allowStructItself: false);

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

        _ensureNativeTypeValid(nativeType, node, allowStructItself: false);

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

        _ensureNativeTypeValid(nativeType, node,
            allowStructItself: false, allowInlineArray: true);

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

        _ensureNativeTypeValid(nativeType, node,
            allowStructItself: false, allowInlineArray: true);

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

        // TODO(http://dartbug.com/38721): Change this to an error after
        // package:ffi is no longer using sizeOf generically.
        if (!isFfiLibrary) {
          _ensureNativeTypeValid(nativeType, node);
        }

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

        _ensureNativeTypeValid(nativeType, node);
        _ensureNativeTypeToDartType(nativeType, dartType, node);
        _ensureNoEmptyStructs(dartType, node);
        return _replaceLookupFunction(node);
      } else if (target == asFunctionMethod) {
        final DartType dartType = node.arguments.types[1];
        final DartType nativeType = InterfaceType(
            nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);

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

        final DartType nativeSignature =
            (nativeType as InterfaceType).typeArguments[0];
        // Inline function body to make all type arguments instatiated.
        return StaticInvocation(
            asFunctionInternal,
            Arguments([node.arguments.positional[0]],
                types: [dartType, nativeSignature]));
      } 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);
        _ensureNoEmptyStructs(dartType, node);

        // Check `exceptionalReturn`'s type.
        final FunctionType funcType = dartType;
        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) {
          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;
          }
        }
        return _replaceFromFunction(node);
      } else if (target == allocateMethod) {
        final DartType nativeType = node.arguments.types[0];

        _ensureNativeTypeValid(nativeType, node);

        // TODO(http://dartbug.com/38721): Change this to an error.
        if (nativeType is TypeParameterType) {
          // Do not rewire generic invocations.
          return node;
        }

        // 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 = MethodInvocation(
                node.arguments.positional[1],
                numMultiplication.name,
                Arguments([sizeInBytes]),
                numMultiplication);
          }
          return MethodInvocation(
              node.arguments.positional[0],
              allocatorAllocateMethod.name,
              Arguments([sizeInBytes], types: node.arguments.types),
              allocatorAllocateMethod);
        }
      }
    } 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;
  }

  Expression _inlineSizeOf(InterfaceType nativeType) {
    final Class nativeClass = nativeType.classNode;
    final NativeType nt = getType(nativeClass);
    if (nt == null) {
      // User-defined structs.
      Field sizeOfField = nativeClass.fields.single;
      return StaticGet(sizeOfField);
    }
    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))

    final DartType nativeSignature = node.arguments.types[0];
    final DartType dartSignature = node.arguments.types[1];

    final Arguments args = Arguments([
      node.arguments.positional[1]
    ], types: [
      InterfaceType(nativeFunctionClass, Nullability.legacy, [nativeSignature])
    ]);

    final Expression lookupResult = MethodInvocation(
        node.arguments.positional[0],
        Name("lookup"),
        args,
        libraryLookupMethod);

    return StaticInvocation(asFunctionInternal,
        Arguments([lookupResult], 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 = MethodInvocation(
          pointer,
          offsetByMethod.name,
          Arguments([
            MethodInvocation(
                node.arguments.positional[1],
                numMultiplication.name,
                Arguments([_inlineSizeOf(dartType)]),
                numMultiplication)
          ]),
          offsetByMethod);
    }
    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(
        PropertyGet(NullCheck(node.arguments.positional[0]),
            arrayTypedDataBaseField.name, arrayTypedDataBaseField),
        MethodInvocation(node.arguments.positional[1], numMultiplication.name,
            Arguments([StaticGet(clazz.fields.single)]), numMultiplication),
        StaticGet(clazz.fields.single),
        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: MethodInvocation(
            VariableGet(singleElementSizeVar),
            numMultiplication.name,
            Arguments([
              PropertyGet(
                  VariableGet(arrayVar),
                  arrayNestedDimensionsFlattened.name,
                  arrayNestedDimensionsFlattened)
            ]),
            numMultiplication),
        type: coreTypes.intNonNullableRawType)
      ..fileOffset = node.fileOffset;
    final offsetVar = VariableDeclaration("#offset",
        initializer: MethodInvocation(
            VariableGet(elementSizeVar),
            numMultiplication.name,
            Arguments([
              VariableGet(indexVar),
            ]),
            numMultiplication),
        type: coreTypes.intNonNullableRawType)
      ..fileOffset = node.fileOffset;

    final checkIndexAndLocalVars = Block([
      arrayVar,
      indexVar,
      ExpressionStatement(MethodInvocation(
          VariableGet(arrayVar),
          arrayCheckIndex.name,
          Arguments([VariableGet(indexVar)]),
          arrayCheckIndex)),
      singleElementSizeVar,
      elementSizeVar,
      offsetVar
    ]);

    if (!setter) {
      // `[]`
      return BlockExpression(
          checkIndexAndLocalVars,
          ConstructorInvocation(
              arrayConstructor,
              Arguments([
                typedDataBaseOffset(
                    PropertyGet(VariableGet(arrayVar),
                        arrayTypedDataBaseField.name, arrayTypedDataBaseField),
                    VariableGet(offsetVar),
                    VariableGet(elementSizeVar),
                    dartType,
                    node.fileOffset),
                PropertyGet(
                    VariableGet(arrayVar),
                    arrayNestedDimensionsFirst.name,
                    arrayNestedDimensionsFirst),
                PropertyGet(VariableGet(arrayVar),
                    arrayNestedDimensionsRest.name, arrayNestedDimensionsRest)
              ], types: [
                dartType
              ])));
    }

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

  @override
  visitMethodInvocation(MethodInvocation node) {
    super.visitMethodInvocation(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);

        Expression inlineSizeOf = _inlineSizeOf(nativeType);
        if (inlineSizeOf != null) {
          // Generates `receiver.offsetBy(inlineSizeOfExpression)`.
          return MethodInvocation(
              node.receiver,
              offsetByMethod.name,
              Arguments([
                MethodInvocation(
                    node.arguments.positional.single,
                    numMultiplication.name,
                    Arguments([inlineSizeOf]),
                    numMultiplication)
              ]),
              offsetByMethod);
        }
      }
    } 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,
        allowStructs: 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 allowStructItself = true,
      bool allowInlineArray = false}) {
    if (!_nativeTypeValid(nativeType,
        allowStructs: true,
        allowStructItself: allowStructItself,
        allowHandle: allowHandle,
        allowInlineArray: allowInlineArray)) {
      diagnosticReporter.report(
          templateFfiTypeInvalid.withArguments(
              nativeType, currentLibrary.isNonNullableByDefault),
          node.fileOffset,
          1,
          node.location.file);
      throw _FfiStaticTypeError();
    }
  }

  void _ensureNoEmptyStructs(DartType nativeType, Expression node) {
    // Error on structs with no fields.
    if (nativeType is InterfaceType) {
      final Class nativeClass = nativeType.classNode;
      if (hierarchy.isSubclassOf(nativeClass, structClass)) {
        if (emptyStructs.contains(nativeClass)) {
          diagnosticReporter.report(
              templateFfiEmptyStruct.withArguments(nativeClass.name),
              node.fileOffset,
              1,
              node.location.file);
        }
      }
    }

    // Recurse when seeing a function type.
    if (nativeType is FunctionType) {
      nativeType.positionalParameters
          .forEach((e) => _ensureNoEmptyStructs(e, node));
      _ensureNoEmptyStructs(nativeType.returnType, node);
    }
  }

  /// 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 allowStructs: false,
      bool allowStructItself = false,
      bool allowHandle = false,
      bool allowInlineArray = false}) {
    return convertNativeTypeToDartType(nativeType,
            allowStructs: allowStructs,
            allowStructItself: allowStructItself,
            allowHandle: allowHandle,
            allowInlineArray: allowInlineArray) !=
        null;
  }

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

  Class _extendsOrImplementsSealedClass(Class klass) {
    final Class superClass = klass.supertype?.classNode;

    // The Opaque and Struct classes can be extended, but subclasses
    // cannot be (nor implemented).
    if (klass != opaqueClass &&
        klass != structClass &&
        (hierarchy.isSubtypeOf(klass, opaqueClass) ||
            hierarchy.isSubtypeOf(klass, structClass))) {
      return superClass != opaqueClass && superClass != structClass
          ? superClass
          : null;
    }

    if (!nativeTypesClasses.contains(klass) && klass != arrayClass) {
      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();
    }
  }
}

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