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

import 'package:front_end/src/fasta/codes/fasta_codes.dart'
    show
        messageFfiAddressOfMustBeNative,
        messageFfiAddressPosition,
        messageFfiAddressReceiver,
        messageFfiCreateOfStructOrUnion,
        messageFfiExceptionalReturnNull,
        messageFfiExpectedConstant,
        templateFfiDartTypeMismatch,
        templateFfiNativeCallableListenerReturnVoid,
        templateFfiExpectedConstantArg,
        templateFfiExpectedExceptionalReturn,
        templateFfiExpectedNoExceptionalReturn,
        templateFfiExtendsOrImplementsSealedClass,
        templateFfiNotStatic;
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/clone.dart';
import 'package:kernel/constructor_tearoff_lowering.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/kernel.dart';
import 'package:kernel/library_index.dart' show LibraryIndex;
import 'package:kernel/names.dart';
import 'package:kernel/reference_from_index.dart';
import 'package:kernel/target/targets.dart' show DiagnosticReporter;
import 'package:kernel/type_algebra.dart'
    show FunctionTypeInstantiator, Substitution;
import 'package:kernel/type_environment.dart';

import 'common.dart'
    show FfiStaticTypeError, FfiTransformer, NativeType, FfiTypeCheckDirection;
import 'definitions.dart' as definitions;
import 'finalizable.dart';
import 'native.dart' as native;
import 'native_type_cfe.dart';

/// Checks and replaces calls to dart:ffi compound fields and methods.
///
/// To reliably lower calls to methods like `sizeOf` and `Native.addressOf`,
/// this requires that the [definitions] and the [native] transformer already
/// ran on the libraries to transform.
void transformLibraries(
    Component component,
    CoreTypes coreTypes,
    ClassHierarchy hierarchy,
    List<Library> libraries,
    DiagnosticReporter diagnosticReporter,
    ReferenceFromIndex? referenceFromIndex) {
  final index = LibraryIndex(component, [
    "dart:ffi",
    "dart:_internal",
    "dart:typed_data",
    "dart:nativewrappers",
    "dart:isolate"
  ]);
  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 _FfiUseSiteTransformer2(
      index, coreTypes, hierarchy, diagnosticReporter, referenceFromIndex);
  libraries.forEach(transformer.visitLibrary);
}

/// Combines [_FfiUseSiteTransformer] and [FinalizableTransformer] into a single
/// traversal.
///
/// This transformation is not AST-node preserving. [Expression]s and
/// [Statement]s can be replaced by other [Expression]s and [Statement]s
/// respectively. This means one cannot do `visitX() { super.visitX() as X }`.
class _FfiUseSiteTransformer2 extends FfiTransformer
    with _FfiUseSiteTransformer, FinalizableTransformer {
  _FfiUseSiteTransformer2(
      LibraryIndex index,
      CoreTypes coreTypes,
      ClassHierarchy hierarchy,
      DiagnosticReporter diagnosticReporter,
      ReferenceFromIndex? referenceFromIndex)
      : super(index, coreTypes, hierarchy, diagnosticReporter,
            referenceFromIndex);
}

/// Checks and replaces calls to dart:ffi compound fields and methods.
///
/// Designed to be mixed in. Calls super.visitXXX() to visit all nodes (except
/// the ones created by this transformation).
///
/// This transformation is not AST-node preserving. [Expression]s and
/// [Statement]s can be replaced by other [Expression]s and [Statement]s
/// respectively. This means one cannot do `visitX() { super.visitX() as X }`.
mixin _FfiUseSiteTransformer on FfiTransformer {
  StaticTypeContext? get staticTypeContext;

  bool _inFfiTearoff = false;

  bool get isFfiLibrary => currentLibrary == ffiLibrary;

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

  // Used to create private top-level trampoline methods with unique names
  // for each call.
  int callCount = 0;

  @override
  TreeNode visitLibrary(Library node) {
    callbackCount = 0;
    callCount = 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
  visitConstructorInvocation(ConstructorInvocation node) {
    if (_inFfiTearoff) {
      return node;
    }
    final target = node.target;
    if (hierarchy.isSubclassOf(target.enclosingClass, compoundClass) &&
        target.enclosingClass != arrayClass &&
        target.enclosingClass != compoundClass &&
        target.name != Name("#fromTypedDataBase") &&
        target.name != Name("#fromTypedData")) {
      diagnosticReporter.report(messageFfiCreateOfStructOrUnion,
          node.fileOffset, 1, node.location?.file);
    }
    return super.visitConstructorInvocation(node);
  }

  /// Transforms calls to Struct.create and Union.create.
  ///
  /// Transforms `create<T>()` into
  ///
  /// ```
  /// Compound._fromTypedDataBase(Uint8List(sizeOf<T>()))
  /// ```
  ///
  /// and `create<T>(typedList)` into
  ///
  /// ```
  /// Compound._fromTypedData(typedList, sizeOf<T>())
  /// ```
  ///
  /// in subclasses of `Struct` and `Union`.
  Expression _transformCompoundCreate(StaticInvocation node) {
    final positionalArguments = node.arguments.positional;
    final nativeType = (node.arguments.types.first as InterfaceType);
    final constructors = nativeType.classNode.constructors;
    final sizeOfExpression = inlineSizeOf(nativeType)!;
    if (positionalArguments.isNotEmpty) {
      // Check length of provided typed data, use checked constructor.
      return ConstructorInvocation(
        constructors.firstWhere((c) => c.name == Name("#fromTypedData")),
        Arguments([
          node.arguments.positional.first,
          (positionalArguments.length >= 2
              ? positionalArguments[1]
              : ConstantExpression(IntConstant(0))),
          // Length in bytes to check the typedData against.
          sizeOfExpression,
        ]),
      );
    }

    // Correct-size typed data is allocated, use unchecked constructor.
    return ConstructorInvocation(
      constructors.firstWhere((c) => c.name == Name("#fromTypedDataBase")),
      Arguments([
        StaticInvocation(
          uint8ListFactory,
          Arguments([sizeOfExpression]),
        ),
        ConstantExpression(IntConstant(0)),
      ]),
    );
  }

  @override
  visitProcedure(Procedure node) {
    assert(_inFfiTearoff == false);
    _inFfiTearoff = ((isFfiLibrary &&
            node.isExtensionMember &&
            (node == allocationTearoff ||
                node == asFunctionTearoff ||
                node == lookupFunctionTearoff ||
                node == abiSpecificIntegerPointerElementAtTearoff ||
                node == structPointerElementAtTearoff ||
                node == unionPointerElementAtTearoff))) ||
        // Dart2wasm uses enabledConstructorTearOffLowerings but these are not
        // users trying to call constructors.
        isConstructorTearOffLowering(node);
    final result = super.visitProcedure(node);
    _inFfiTearoff = false;
    return result;
  }

  @override
  TreeNode visitStaticInvocation(StaticInvocation node) {
    final modifiedExpression = _visitStaticInvocation(node);
    if (node == modifiedExpression) {
      return super.visitStaticInvocation(node);
    }
    // We've just created this node. We're likely not going to need to transform
    // this node itself. Visit its sub expressions.
    return super.defaultExpression(modifiedExpression);
  }

  /// Replaces nodes if they match. Does not invoke any super visit.
  Expression _visitStaticInvocation(StaticInvocation node) {
    if (_inFfiTearoff) {
      return node;
    }
    final Member target = node.target;
    try {
      if (target == abiSpecificIntegerArrayElemAt ||
          target == abiSpecificIntegerArraySetElemAt) {
        final pointer = node.arguments.positional[0];
        final pointerType =
            pointer.getStaticType(staticTypeContext!) as InterfaceType;
        ensureNativeTypeValid(pointerType, pointer,
            allowStructAndUnion: true, allowInlineArray: true);

        final typeArg = pointerType.typeArguments.single;
        final nativeTypeCfe =
            NativeTypeCfe(this, typeArg) as AbiSpecificNativeTypeCfe;

        final arrayVar = VariableDeclaration("#array",
            initializer: NullCheck(node.arguments.positional[0]),
            type: InterfaceType(arrayClass, Nullability.nonNullable),
            isSynthesized: true)
          ..fileOffset = node.fileOffset;
        final indexVar = VariableDeclaration("#index",
            initializer: NullCheck(node.arguments.positional[1]),
            type: coreTypes.intNonNullableRawType,
            isSynthesized: true)
          ..fileOffset = node.fileOffset;

        return BlockExpression(
          Block([
            arrayVar,
            indexVar,
            ExpressionStatement(InstanceInvocation(
              InstanceAccessKind.Instance,
              VariableGet(arrayVar),
              arrayCheckIndex.name,
              Arguments([VariableGet(indexVar)]),
              interfaceTarget: arrayCheckIndex,
              functionType: arrayCheckIndex.getterType as FunctionType,
            )),
          ]),
          abiSpecificLoadOrStoreExpression(
            nativeTypeCfe,
            typedDataBase: getCompoundTypedDataBaseField(
              VariableGet(arrayVar),
              node.fileOffset,
            ),
            offsetInBytes: getCompoundOffsetInBytesField(
              VariableGet(arrayVar),
              node.fileOffset,
            ),
            index: VariableGet(indexVar),
            value: target == abiSpecificIntegerArraySetElemAt
                ? node.arguments.positional.last
                : null,
            fileOffset: node.fileOffset,
          ),
        );
      }
      if (target == abiSpecificIntegerPointerGetValue ||
          target == abiSpecificIntegerPointerSetValue ||
          target == abiSpecificIntegerPointerElemAt ||
          target == abiSpecificIntegerPointerSetElemAt) {
        final pointer = node.arguments.positional[0];
        final pointerType =
            pointer.getStaticType(staticTypeContext!) as InterfaceType;
        ensureNativeTypeValid(pointerType, pointer,
            allowStructAndUnion: true, allowInlineArray: true);

        final typeArg = pointerType.typeArguments.single;
        final nativeTypeCfe =
            NativeTypeCfe(this, typeArg) as AbiSpecificNativeTypeCfe;

        return abiSpecificLoadOrStoreExpression(
          nativeTypeCfe,
          typedDataBase: node.arguments.positional[0],
          index: (target == abiSpecificIntegerPointerElemAt ||
                  target == abiSpecificIntegerPointerSetElemAt)
              ? node.arguments.positional[1]
              : null,
          value: (target == abiSpecificIntegerPointerSetValue ||
                  target == abiSpecificIntegerPointerSetElemAt)
              ? node.arguments.positional.last
              : null,
          fileOffset: node.fileOffset,
        );
      }
      if (target == structPointerGetRef ||
          target == structPointerGetElemAt ||
          target == unionPointerGetRef ||
          target == unionPointerGetElemAt) {
        final DartType nativeType = node.arguments.types[0];

        ensureNativeTypeValid(nativeType, node, allowStructAndUnion: true);

        return _replaceGetRef(node);
      } else if (target == structPointerSetRef ||
          target == structPointerSetElemAt ||
          target == unionPointerSetRef ||
          target == unionPointerSetElemAt) {
        final DartType nativeType = node.arguments.types[0];

        ensureNativeTypeValid(nativeType, node, allowStructAndUnion: true);

        return _replaceSetRef(node);
      } else if (target == abiSpecificIntegerPointerElementAt ||
          target == structPointerElementAt ||
          target == unionPointerElementAt ||
          target == abiSpecificIntegerPointerPlusOperator ||
          target == structPointerPlusOperator ||
          target == unionPointerPlusOperator ||
          target == abiSpecificIntegerPointerMinusOperator ||
          target == structPointerMinusOperator ||
          target == unionPointerMinusOperator) {
        final pointer = node.arguments.positional[0];
        final positiveOffset = node.arguments.positional[1];
        final Expression offset;
        if (target == abiSpecificIntegerPointerMinusOperator ||
            target == structPointerMinusOperator ||
            target == unionPointerMinusOperator) {
          offset = InstanceInvocation(InstanceAccessKind.Instance,
              positiveOffset, unaryMinusName, new Arguments([]),
              interfaceTarget: coreTypes.intUnaryMinus,
              functionType: coreTypes.intUnaryMinus.getterType as FunctionType);
        } else {
          offset = positiveOffset;
        }
        final pointerType =
            pointer.getStaticType(staticTypeContext!) as InterfaceType;
        ensureNativeTypeValid(pointerType, pointer,
            allowStructAndUnion: true, allowInlineArray: true);
        final DartType nativeType = node.arguments.types[0];

        ensureNativeTypeValid(nativeType, node, allowStructAndUnion: true);

        Expression? inlineSizeOf =
            this.inlineSizeOf(nativeType as InterfaceType);
        if (inlineSizeOf != null) {
          // Generates `receiver.offsetBy(inlineSizeOfExpression)`.
          return InstanceInvocation(InstanceAccessKind.Instance, pointer,
              offsetByMethod.name, Arguments([multiply(offset, inlineSizeOf)]),
              interfaceTarget: offsetByMethod,
              functionType: Substitution.fromInterfaceType(pointerType)
                  .substituteType(offsetByMethod.getterType) as FunctionType);
        }
      } else if (target == structArrayElemAt || target == unionArrayElemAt) {
        final DartType nativeType = node.arguments.types[0];

        ensureNativeTypeValid(nativeType, node, allowStructAndUnion: true);

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

        ensureNativeTypeValid(nativeType, node,
            allowInlineArray: true, allowStructAndUnion: true);

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

        ensureNativeTypeValid(nativeType, node,
            allowInlineArray: true, allowStructAndUnion: true);

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

        ensureNativeTypeValid(nativeType, node,
            allowStructAndUnion: true, allowVoid: true);

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

        _ensureIsLeafIsConst(node);
        final isLeaf = getIsLeafBoolean(node) ?? false;
        ensureNativeTypeValid(nativeType, node);
        ensureNativeTypeMatch(
          FfiTypeCheckDirection.nativeToDart,
          nativeType,
          dartType,
          node,
          allowHandle: true, // Handle-specific errors emitted below.
        );
        ensureLeafCallDoesNotUseHandles(
          nativeType,
          isLeaf,
          reportErrorOn: node,
        );
        return _replaceLookupFunction(node);
      } else if (target == asFunctionMethod) {
        final dartType = node.arguments.types[1];
        final InterfaceType nativeType = InterfaceType(nativeFunctionClass,
            Nullability.nonNullable, [node.arguments.types[0]]);

        _ensureIsLeafIsConst(node);
        final isLeaf = getIsLeafBoolean(node) ?? false;

        ensureNativeTypeValid(nativeType, node);
        ensureNativeTypeMatch(
          FfiTypeCheckDirection.nativeToDart,
          nativeType,
          dartType,
          node,
          allowHandle: true, // Handle-specific errors emitted below.
        );
        ensureLeafCallDoesNotUseHandles(
          nativeType,
          isLeaf,
          reportErrorOn: node,
        );
        final DartType nativeSignature = nativeType.typeArguments[0];

        return _replaceAsFunction(
          functionPointer: node.arguments.positional[0],
          pointerType: InterfaceType(
              pointerClass, Nullability.nonNullable, [nativeType]),
          nativeSignature: nativeSignature,
          dartSignature: dartType as FunctionType,
          isLeaf: isLeaf,
          fileOffset: node.fileOffset,
        );
      } else if (target == fromFunctionMethod) {
        return _verifyAndReplaceNativeCallableIsolateLocal(node,
            fromFunction: true);
      } else if (target == nativeCallableIsolateLocalConstructor) {
        return _verifyAndReplaceNativeCallableIsolateLocal(node);
      } else if (target == nativeCallableListenerConstructor) {
        final DartType nativeType = InterfaceType(nativeFunctionClass,
            currentLibrary.nonNullable, [node.arguments.types[0]]);
        final Expression func = node.arguments.positional[0];
        final DartType dartType = func.getStaticType(staticTypeContext!);

        ensureNativeTypeValid(nativeType, node);
        final ffiFuncType = ensureNativeTypeMatch(
                FfiTypeCheckDirection.dartToNative, nativeType, dartType, node)
            as FunctionType;

        final funcType = dartType as FunctionType;

        // Check return type.
        if (ffiFuncType.returnType != VoidType()) {
          diagnosticReporter.report(
              templateFfiNativeCallableListenerReturnVoid.withArguments(
                  ffiFuncType.returnType,
                  currentLibrary.isNonNullableByDefault),
              func.fileOffset,
              1,
              func.location?.file);
          return node;
        }

        final replacement = _replaceNativeCallableListenerConstructor(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,
            allowStructAndUnion: true, allowVoid: true);

        // Inline the body to get rid of a generic invocation of sizeOf.
        // TODO(http://dartbug.com/39964): Add `alignmentOf<T>()` call.
        Expression? sizeInBytes = inlineSizeOf(nativeType as InterfaceType);
        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: FunctionTypeInstantiator.instantiate(
                  allocateFunctionType, node.arguments.types));
        }
      } else if (target == structCreate || target == unionCreate) {
        final nativeType = node.arguments.types.first;
        ensureNativeTypeValid(nativeType, node, allowStructAndUnion: true);
        return _transformCompoundCreate(node);
      } else if (target == nativeAddressOf) {
        return _replaceNativeAddressOf(node);
      } else if (addressOfMethods.contains(target)) {
        // The AST is visited recursively down. Handling of native invocations
        // will inspect arguments for `<expr>.address` invocations. Any
        // remaining invocations occur are places where `<expr>.address` is
        // disallowed, so issue an error.
        diagnosticReporter.report(
            messageFfiAddressPosition, node.fileOffset, 1, node.location?.file);
      } else {
        final nativeAnnotation = memberGetNativeAnnotation(target);
        if (nativeAnnotation != null && _isLeaf(nativeAnnotation)) {
          return _replaceNativeCall(node, nativeAnnotation);
        }
      }
    } 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;
  }

  bool _isLeaf(InstanceConstant native) {
    return (native.fieldValues[nativeIsLeafField.fieldReference]
            as BoolConstant)
        .value;
  }

  /// Create Dart function which calls native code.
  ///
  /// Adds a native effect invoking a compound constructors if this is used
  /// as return type.
  Expression _replaceAsFunction({
    required Expression functionPointer,
    required DartType pointerType,
    required DartType nativeSignature,
    required FunctionType dartSignature,
    required bool isLeaf,
    required int fileOffset,
  }) {
    assert(dartSignature.namedParameters.isEmpty);
    final functionPointerVarName = '#ffiTarget$callCount';
    final closureName = '#ffiClosure$callCount';
    ++callCount;

    final pointerVar = VariableDeclaration(functionPointerVarName,
        initializer: functionPointer, type: pointerType, isSynthesized: true);

    final positionalParameters = [
      for (int i = 0; i < dartSignature.positionalParameters.length; ++i)
        VariableDeclaration(
          'arg${i + 1}',
          type: dartSignature.positionalParameters[i],
        )
    ];

    final closure = FunctionDeclaration(
        VariableDeclaration(closureName,
            type: dartSignature, isSynthesized: true)
          ..addAnnotation(ConstantExpression(
              InstanceConstant(coreTypes.pragmaClass.reference, [], {
            coreTypes.pragmaName.fieldReference:
                StringConstant('vm:ffi:call-closure'),
            coreTypes.pragmaOptions.fieldReference: InstanceConstant(
              ffiCallClass.reference,
              [nativeSignature],
              {
                ffiCallIsLeafField.fieldReference: BoolConstant(isLeaf),
              },
            ),
          }))),
        FunctionNode(
            Block([
              for (final param in positionalParameters)
                ExpressionStatement(StaticInvocation(
                    nativeEffectMethod, Arguments([VariableGet(param)]))),
              ReturnStatement(StaticInvocation(
                  ffiCallMethod,
                  Arguments([
                    VariableGet(pointerVar),
                  ], types: [
                    dartSignature.returnType,
                  ]))
                ..fileOffset = fileOffset),
            ]),
            positionalParameters: positionalParameters,
            requiredParameterCount: dartSignature.requiredParameterCount,
            returnType: dartSignature.returnType)
          ..fileOffset = fileOffset)
      ..fileOffset = fileOffset;

    final result = BlockExpression(
        Block([
          pointerVar,
          closure,
        ]),
        VariableGet(closure.variable));

    final possibleCompoundReturn = findCompoundReturnType(dartSignature);
    if (possibleCompoundReturn != null) {
      return invokeCompoundConstructor(result, possibleCompoundReturn);
    }

    return result;
  }

  Expression invokeCompoundConstructors(
          Expression nestedExpression, List<Class> compoundClasses) =>
      compoundClasses
          .distinct()
          .fold(nestedExpression, invokeCompoundConstructor);

  // 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) {
    final DartType nativeSignature = node.arguments.types[0];
    final DartType dartSignature = node.arguments.types[1];

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

    final lookupResult = InstanceInvocation(InstanceAccessKind.Instance,
        node.arguments.positional[0], libraryLookupMethod.name, lookupArgs,
        interfaceTarget: libraryLookupMethod,
        functionType: FunctionTypeInstantiator.instantiate(
            lookupFunctionType, lookupTypeArgs));

    final isLeaf = getIsLeafBoolean(node) ?? false;

    return _replaceAsFunction(
      functionPointer: lookupResult,
      pointerType: lookupResult.functionType.returnType,
      nativeSignature: nativeSignature,
      dartSignature: dartSignature as FunctionType,
      isLeaf: isLeaf,
      fileOffset: node.fileOffset,
    );
  }

  // 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) =>
  //   _createNativeCallableIsolateLocal<NativeFunction<T>>(
  //     _nativeCallbackFunction<T>(f, e), null, false);
  //
  //  ... _#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, Expression exceptionalReturn) {
    final nativeFunctionType = InterfaceType(
        nativeFunctionClass, currentLibrary.nonNullable, node.arguments.types);
    var name = Name("_#ffiCallback${callbackCount++}", currentLibrary);
    var getterReference = currentLibraryIndex?.lookupGetterReference(name);
    final Field field = Field.immutable(name,
        type: InterfaceType(
            pointerClass, currentLibrary.nonNullable, [nativeFunctionType]),
        initializer: StaticInvocation(
            createNativeCallableIsolateLocalProcedure,
            Arguments([
              StaticInvocation(
                  nativeCallbackFunctionProcedure,
                  Arguments([
                    node.arguments.positional[0],
                    exceptionalReturn,
                  ], types: node.arguments.types)),
              NullLiteral(),
              BoolLiteral(false),
            ], types: [
              nativeFunctionType
            ])),
        isStatic: true,
        isFinal: true,
        fileUri: currentLibrary.fileUri,
        getterReference: getterReference)
      ..fileOffset = node.fileOffset;
    currentLibrary.addField(field);
    return StaticGet(field);
  }

  // NativeCallable<T>.isolateLocal(target, exceptionalReturn) calls become:
  // isStaticFunction is false:
  //   _NativeCallableIsolateLocal<T>(
  //       _createNativeCallableIsolateLocal<NativeFunction<T>>(
  //           _nativeIsolateLocalCallbackFunction<T>(exceptionalReturn),
  //           target,
  //           true));
  // isStaticFunction is true:
  //   _NativeCallableIsolateLocal<T>(
  //       _createNativeCallableIsolateLocal<NativeFunction<T>>(
  //           _nativeCallbackFunction<T>(target, exceptionalReturn),
  //           null,
  //           true);
  Expression _replaceNativeCallableIsolateLocalConstructor(
      StaticInvocation node,
      Expression exceptionalReturn,
      bool isStaticFunction) {
    final nativeFunctionType = InterfaceType(
        nativeFunctionClass, currentLibrary.nonNullable, node.arguments.types);
    final target = node.arguments.positional[0];
    late StaticInvocation pointerValue;
    if (isStaticFunction) {
      pointerValue = StaticInvocation(
          createNativeCallableIsolateLocalProcedure,
          Arguments([
            StaticInvocation(
                nativeCallbackFunctionProcedure,
                Arguments([
                  target,
                  exceptionalReturn,
                ], types: node.arguments.types)),
            NullLiteral(),
            BoolLiteral(true),
          ], types: [
            nativeFunctionType,
          ]));
    } else {
      pointerValue = StaticInvocation(
          createNativeCallableIsolateLocalProcedure,
          Arguments([
            StaticInvocation(nativeIsolateLocalCallbackFunctionProcedure,
                Arguments([exceptionalReturn], types: node.arguments.types)),
            target,
            BoolLiteral(true),
          ], types: [
            nativeFunctionType,
          ]));
    }
    return ConstructorInvocation(nativeCallablePrivateIsolateLocalConstructor,
        Arguments([pointerValue], types: node.arguments.types));
  }

  // NativeCallable<T>.listener(target) calls become:
  // void _handler(List args) => target(args[0], args[1], ...)
  // final _callback = _NativeCallableListener<T>(_handler, debugName);
  // _callback._pointer = _createNativeCallableListener<NativeFunction<T>>(
  //       _nativeAsyncCallbackFunction<T>(), _callback._rawPort);
  // expression result: _callback;
  Expression _replaceNativeCallableListenerConstructor(StaticInvocation node) {
    final nativeFunctionType = InterfaceType(
        nativeFunctionClass, currentLibrary.nonNullable, node.arguments.types);
    final listType = InterfaceType(listClass, currentLibrary.nonNullable);
    final nativeCallableType = InterfaceType(
        nativeCallableClass, currentLibrary.nonNullable, node.arguments.types);
    final targetType = node.arguments.types[0] as FunctionType;

    // void _handler(List args) => target(args[0], args[1], ...)
    final args = VariableDeclaration('args', type: listType, isFinal: true)
      ..fileOffset = node.fileOffset;
    final targetArgs = <Expression>[];
    for (int i = 0; i < targetType.positionalParameters.length; ++i) {
      targetArgs.add(InstanceInvocation(InstanceAccessKind.Instance,
          VariableGet(args), listElementAt.name, Arguments([IntLiteral(i)]),
          interfaceTarget: listElementAt,
          functionType: Substitution.fromInterfaceType(listType)
              .substituteType(listElementAt.getterType) as FunctionType));
    }
    final target = node.arguments.positional[0];
    final handlerBody = ExpressionStatement(FunctionInvocation(
      FunctionAccessKind.FunctionType,
      target,
      Arguments(targetArgs),
      functionType: targetType,
    ));
    final handler = FunctionNode(handlerBody,
        positionalParameters: [args], returnType: VoidType())
      ..fileOffset = node.fileOffset;

    // final _callback = NativeCallable<T>._listener(_handler, debugName);
    final nativeCallable = VariableDeclaration.forValue(
        ConstructorInvocation(
            nativeCallablePrivateListenerConstructor,
            Arguments([
              FunctionExpression(handler),
              StringLiteral('NativeCallable($target)'),
            ], types: [
              targetType,
            ])),
        type: nativeCallableType,
        isFinal: true)
      ..fileOffset = node.fileOffset;

    // _callback._pointer = _createNativeCallableListener<NativeFunction<T>>(
    //       _nativeAsyncCallbackFunction<T>(), _callback._rawPort);
    final pointerValue = StaticInvocation(
        createNativeCallableListenerProcedure,
        Arguments([
          StaticInvocation(nativeAsyncCallbackFunctionProcedure,
              Arguments([], types: [targetType])),
          InstanceGet(InstanceAccessKind.Instance, VariableGet(nativeCallable),
              nativeCallablePortField.name,
              interfaceTarget: nativeCallablePortField,
              resultType: nativeCallablePortField.getterType),
        ], types: [
          nativeFunctionType,
        ]));
    final pointerSetter = ExpressionStatement(InstanceSet(
      InstanceAccessKind.Instance,
      VariableGet(nativeCallable),
      nativeCallablePointerField.name,
      pointerValue,
      interfaceTarget: nativeCallablePointerField,
    ));

    // expression result: _callback;
    return BlockExpression(
        Block([
          nativeCallable,
          pointerSetter,
        ]),
        VariableGet(nativeCallable));
  }

  Expression _verifyAndReplaceNativeCallableIsolateLocal(StaticInvocation node,
      {bool fromFunction = false}) {
    final DartType nativeType = InterfaceType(nativeFunctionClass,
        currentLibrary.nonNullable, [node.arguments.types[0]]);
    final Expression func = node.arguments.positional[0];
    final DartType dartType = func.getStaticType(staticTypeContext!);

    final isStaticFunction = _isStaticFunction(func);
    if (fromFunction && !isStaticFunction) {
      diagnosticReporter.report(
          templateFfiNotStatic.withArguments(fromFunctionMethod.name.text),
          func.fileOffset,
          1,
          func.location?.file);
      return node;
    }

    ensureNativeTypeValid(nativeType, node);
    final ffiFuncType = ensureNativeTypeMatch(
      FfiTypeCheckDirection.dartToNative,
      nativeType,
      dartType,
      node,
    ) as FunctionType;

    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);

    Expression exceptionalReturn = NullLiteral();
    bool hasExceptionalReturn = false;
    if (fromFunction) {
      if (node.arguments.positional.length > 1) {
        exceptionalReturn = node.arguments.positional[1];
        hasExceptionalReturn = true;
      }
    } else {
      if (node.arguments.named.isNotEmpty) {
        exceptionalReturn = node.arguments.named[0].value;
        hasExceptionalReturn = true;
      }
    }

    if (expectedReturn == NativeType.kVoid ||
        expectedReturn == NativeType.kPointer ||
        expectedReturn == NativeType.kHandle ||
        expectedReturnClass.superclass == structClass ||
        expectedReturnClass.superclass == unionClass) {
      if (hasExceptionalReturn) {
        diagnosticReporter.report(
            templateFfiExpectedNoExceptionalReturn.withArguments(
                ffiFuncType.returnType, currentLibrary.isNonNullableByDefault),
            node.fileOffset,
            1,
            node.location?.file);
        return node;
      }
    } else {
      // The exceptional return value is not optional for other return types.
      if (!hasExceptionalReturn) {
        diagnosticReporter.report(
            templateFfiExpectedExceptionalReturn.withArguments(
                ffiFuncType.returnType, currentLibrary.isNonNullableByDefault),
            node.fileOffset,
            1,
            node.location?.file);
        return node;
      }

      // The exceptional return value must be a constant so that it can 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 = fromFunction
        ? _replaceFromFunction(node, exceptionalReturn)
        : _replaceNativeCallableIsolateLocalConstructor(
            node, exceptionalReturn, isStaticFunction);

    final compoundClasses = funcType.positionalParameters
        .whereType<InterfaceType>()
        .map((t) => t.classNode)
        .where((c) => c.superclass == structClass || c.superclass == unionClass)
        .toList();
    return invokeCompoundConstructors(replacement, compoundClasses);
  }

  Expression _replaceGetRef(StaticInvocation node) {
    final dartType = node.arguments.types[0];
    final clazz = (dartType as InterfaceType).classNode;
    final referencedStruct = ReferencedCompoundSubtypeCfe(clazz);

    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 referencedStruct.generateLoad(
      dartType: dartType,
      transformer: this,
      typedDataBase: pointer,
      offsetInBytes: ConstantExpression(IntConstant(0)),
      fileOffset: node.fileOffset,
    );
  }

  /// Replaces a `.ref=` or `[]=` on a compound pointer extension with a mem
  /// copy call.
  Expression _replaceSetRef(StaticInvocation node) {
    final target = node.arguments.positional[0]; // Receiver of extension
    final referencedStruct = ReferencedCompoundSubtypeCfe(
        (node.arguments.types[0] as InterfaceType).classNode);

    final Expression sourceStruct, targetOffset;
    final DartType sourceStructType;

    if (node.arguments.positional.length == 3) {
      // []= call, args are (receiver, index, source)
      sourceStruct = node.arguments.positional[2];
      sourceStructType = node.arguments.types[0];
      targetOffset = multiply(node.arguments.positional[1],
          inlineSizeOf(node.arguments.types[0] as InterfaceType)!);
    } else {
      // .ref= call, args are (receiver, source)
      sourceStruct = node.arguments.positional[1];
      sourceStructType = node.arguments.types[0];
      targetOffset = ConstantExpression(IntConstant(0));
    }

    final sourceVar = VariableDeclaration(
      "#source",
      initializer: sourceStruct,
      type: sourceStructType,
      isSynthesized: true,
    )..fileOffset = node.fileOffset;

    return BlockExpression(
      Block([sourceVar]),
      referencedStruct.generateStore(
        sourceVar,
        dartType: node.arguments.types[0],
        offsetInBytes: targetOffset,
        typedDataBase: target,
        transformer: this,
        fileOffset: node.fileOffset,
      ),
    );
  }

  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 arrayVar = VariableDeclaration("#array",
        initializer: NullCheck(node.arguments.positional[0]),
        type: InterfaceType(arrayClass, Nullability.nonNullable),
        isSynthesized: true)
      ..fileOffset = node.fileOffset;
    final indexVar = VariableDeclaration("#index",
        initializer: NullCheck(node.arguments.positional[1]),
        type: coreTypes.intNonNullableRawType,
        isSynthesized: true)
      ..fileOffset = node.fileOffset;

    return BlockExpression(
      Block([
        arrayVar,
        indexVar,
        ExpressionStatement(InstanceInvocation(
          InstanceAccessKind.Instance,
          VariableGet(arrayVar),
          arrayCheckIndex.name,
          Arguments([VariableGet(indexVar)]),
          interfaceTarget: arrayCheckIndex,
          functionType: arrayCheckIndex.getterType as FunctionType,
        )),
      ]),
      ConstructorInvocation(
        constructor,
        Arguments([
          getCompoundTypedDataBaseField(
            VariableGet(arrayVar),
            node.fileOffset,
          ),
          add(
            getCompoundOffsetInBytesField(
              VariableGet(arrayVar),
              node.fileOffset,
            ),
            multiply(VariableGet(indexVar), inlineSizeOf(dartType)!),
          ),
        ]),
      ),
    );
  }

  /// 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>._(
  ///   #array._typedDataBase,
  ///   #offset,
  ///   #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),
        isSynthesized: true)
      ..fileOffset = node.fileOffset;
    final indexVar = VariableDeclaration("#index",
        initializer: NullCheck(node.arguments.positional[1]),
        type: coreTypes.intNonNullableRawType,
        isSynthesized: true)
      ..fileOffset = node.fileOffset;
    final singleElementSizeVar = VariableDeclaration("#singleElementSize",
        initializer: inlineSizeOf(elementType as InterfaceType),
        type: coreTypes.intNonNullableRawType,
        isSynthesized: true)
      ..fileOffset = node.fileOffset;
    final elementSizeVar = VariableDeclaration("#elementSize",
        initializer: multiply(
            VariableGet(singleElementSizeVar),
            InstanceGet(InstanceAccessKind.Instance, VariableGet(arrayVar),
                arrayNestedDimensionsFlattened.name,
                interfaceTarget: arrayNestedDimensionsFlattened,
                resultType: arrayNestedDimensionsFlattened.getterType)),
        type: coreTypes.intNonNullableRawType,
        isSynthesized: true)
      ..fileOffset = node.fileOffset;
    final offsetVar = VariableDeclaration("#offset",
        initializer:
            multiply(VariableGet(elementSizeVar), VariableGet(indexVar)),
        type: coreTypes.intNonNullableRawType,
        isSynthesized: true)
      ..fileOffset = node.fileOffset;

    final checkIndexAndLocalVars = [
      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(
          Block(checkIndexAndLocalVars),
          ConstructorInvocation(
              arrayConstructor,
              Arguments([
                getCompoundTypedDataBaseField(
                  VariableGet(arrayVar),
                  node.fileOffset,
                ),
                add(
                  getCompoundOffsetInBytesField(
                    VariableGet(arrayVar),
                    node.fileOffset,
                  ),
                  VariableGet(offsetVar),
                ),
                InstanceGet(InstanceAccessKind.Instance, VariableGet(arrayVar),
                    arrayNestedDimensionsFirst.name,
                    interfaceTarget: arrayNestedDimensionsFirst,
                    resultType: arrayNestedDimensionsFirst.getterType),
                InstanceGet(InstanceAccessKind.Instance, VariableGet(arrayVar),
                    arrayNestedDimensionsRest.name,
                    interfaceTarget: arrayNestedDimensionsRest,
                    resultType: arrayNestedDimensionsRest.getterType)
              ], types: [
                dartType
              ])));
    }

    // `[]=`
    final valueVar = VariableDeclaration(
      "#value",
      initializer: NullCheck(node.arguments.positional[2]),
      type: InterfaceType(arrayClass, Nullability.nonNullable),
      isSynthesized: true,
    )..fileOffset = node.fileOffset;
    return BlockExpression(
        Block([
          ...checkIndexAndLocalVars,
          valueVar,
        ]),
        StaticInvocation(
            memCopy,
            Arguments([
              getCompoundTypedDataBaseField(
                VariableGet(arrayVar),
                node.fileOffset,
              ),
              add(
                getCompoundOffsetInBytesField(
                  VariableGet(arrayVar),
                  node.fileOffset,
                ),
                VariableGet(offsetVar),
              ),
              getCompoundTypedDataBaseField(
                VariableGet(valueVar),
                node.fileOffset,
              ),
              getCompoundOffsetInBytesField(
                VariableGet(valueVar),
                node.fileOffset,
              ),
              VariableGet(elementSizeVar),
            ]))
          ..fileOffset = node.fileOffset);
  }

  bool _isStaticFunction(Expression node) =>
      (node is StaticGet && node.target is Procedure) ||
      (node is ConstantExpression && node.constant is StaticTearOffConstant);

  /// 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 ||
        klass == abiSpecificIntegerClass ||
        klass == varArgsClass ||
        classNativeTypes[klass] != null) {
      return null;
    }

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

    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();
    }
  }

  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();
    }
  }

  /// Replaces calls to `Native.addressOf(x)` by looking up the `@Native`
  /// annotation of `x` and rewriting the expression to use
  /// `_addressOf(annotation)`, which is implemented in the VM.
  ///
  /// By implementing this in the VM, we can re-use the implementation used to
  /// lookup addresses for `@Native` invocations. We could also replace the
  /// call with an invocation to `Native._ffi_resolver_function` and wrap the
  /// result in a `Pointer`. To support static linking of native functions in
  /// the future, having the unresolved symbol in the assembly generated for
  /// each call site in the VM will be necessary. So we're already doing this
  /// in the VM today.
  ///
  /// The transformation works by looking up the resolved `@Native` annotation
  /// left by the native transformer in a pragma. Looking for a `@Native`
  /// annotation on the argument wouldn't work because it's removed by the
  /// native transformer and because it requires context from the library to
  /// resolve the asset id.
  StaticInvocation _replaceNativeAddressOf(StaticInvocation node) {
    final arg = node.arguments.positional.single;
    final nativeType = node.arguments.types.single;

    final potentiallyNativeTarget = switch (arg) {
      ConstantExpression(constant: StaticTearOffConstant method) =>
        method.target,
      StaticGet(:var targetReference) => targetReference.asMember,
      _ => null,
    };
    Constant? nativeAnnotation =
        memberGetNativeAnnotation(potentiallyNativeTarget);

    if (nativeAnnotation == null) {
      diagnosticReporter.report(messageFfiAddressOfMustBeNative, arg.fileOffset,
          1, node.location?.file);
      return node;
    }

    ensureNativeTypeValid(nativeType, node,
        allowStructAndUnion: true, allowInlineArray: true);
    ensureNativeTypeMatch(FfiTypeCheckDirection.nativeToDart, nativeType,
        arg.getStaticType(staticTypeContext!), node,
        allowArray: true);

    return StaticInvocation(
      nativePrivateAddressOf,
      Arguments([ConstantExpression(nativeAnnotation)], types: [nativeType]),
    )..fileOffset = arg.fileOffset;
  }

  InstanceConstant? memberGetNativeAnnotation(Member? member) {
    if (member == null) {
      return null;
    }
    for (final annotation in member.annotations) {
      if (annotation
          case ConstantExpression(constant: final InstanceConstant c)) {
        if (c.classNode == coreTypes.pragmaClass) {
          final name = c.fieldValues[coreTypes.pragmaName.fieldReference];
          if (name is StringConstant &&
              name.value == native.FfiNativeTransformer.nativeMarker) {
            return c.fieldValues[coreTypes.pragmaOptions.fieldReference]
                as InstanceConstant;
          }
        }
      }
    }
    return null;
  }

  StaticInvocation _replaceNativeCall(
    StaticInvocation node,
    InstanceConstant targetNativeAnnotation,
  ) {
    final target = node.target;
    if (targetNativeAnnotation.typeArguments.length != 1) {
      return node;
    }
    final annotationType = targetNativeAnnotation.typeArguments.single;
    if (annotationType is! FunctionType) {
      return node;
    }
    final parameterTypes = [
      for (final varDecl in target.function.positionalParameters) varDecl.type,
    ];
    final numParams = parameterTypes.length;
    String methodPostfix = '';
    final newArguments = <Expression>[];
    final newParameters = <VariableDeclaration>[];
    bool isTransformed = false;
    for (int i = 0; i < numParams; i++) {
      final parameter = target.function.positionalParameters[i];
      final parameterType = parameterTypes[i];
      final argument = node.arguments.positional[i];
      final (
        postFix,
        newType,
        newArgument,
      ) = _replaceNativeCallParameterAndArgument(
        parameter,
        parameterType,
        argument,
        node.fileOffset,
      );
      methodPostfix += postFix;
      if (postFix == 'C' || postFix == 'E' || postFix == 'T') {
        isTransformed = true;
      }
      newParameters.add(VariableDeclaration(
        parameter.name,
        type: newType,
      ));
      newArguments.add(newArgument);
    }

    if (!isTransformed) {
      return node;
    }

    final newName = '${target.name.text}#$methodPostfix';
    final Procedure newTarget;
    final parent = target.parent;
    final members = switch (parent) {
      Library _ => parent.members,
      Class _ => parent.members,
      _ => throw UnimplementedError('Unexpected parent: ${parent}'),
    };

    final existingNewTarget = members
        .whereType<Procedure>()
        .where((element) => element.name.text == newName)
        .firstOrNull;
    if (existingNewTarget != null) {
      newTarget = existingNewTarget;
    } else {
      final cloner = CloneProcedureWithoutBody();
      newTarget = cloner.cloneProcedure(target, null);
      newTarget.name = Name(newName);
      newTarget.function.positionalParameters = newParameters;
      setParents(newParameters, newTarget.function);
      switch (parent) {
        case Library _:
          parent.addProcedure(newTarget);
        case Class _:
          parent.addProcedure(newTarget);
      }
    }

    return StaticInvocation(
      newTarget,
      Arguments(newArguments),
    );
  }

  /// Converts a single parameter with argument for [_replaceNativeCall].
  (
    /// '' for non-Pointer.
    /// 'P' for Pointer.
    /// 'T' for TypedData.
    /// 'C' for _Compound (TypedData/Pointer and offset in bytes).
    /// 'E' for errors.
    String methodPostFix,
    DartType parameterType,
    Expression argument,
  ) _replaceNativeCallParameterAndArgument(
    VariableDeclaration parameter,
    DartType parameterType,
    Expression argument,
    int fileOffset,
  ) {
    if (parameterType is! InterfaceType ||
        parameterType.classNode != pointerClass) {
      // Parameter is non-pointer. Keep unchanged.
      return ('', parameterType, argument);
    }

    if (argument is! StaticInvocation ||
        !addressOfMethods.contains(argument.target)) {
      // The argument has type Pointer, but it's not produced by any of the
      // `.address` getters.
      // Argument must be a Pointer object. Keep unchanged.
      return ('P', parameterType, argument);
    }

    if (addressOfMethodsTypedData.contains(argument.target)) {
      final subExpression = argument.arguments.positional.single;
      // Argument is `typedData.address`.
      final typedDataType = InterfaceType(
        typedDataClass,
        Nullability.nonNullable,
        const <DartType>[],
      );
      return ('T', typedDataType, subExpression);
    }

    final subExpression = argument.arguments.positional.single;

    if (addressOfMethodsCompound.contains(argument.target)) {
      // Argument is `structOrUnionOrArray.address`.
      return ('C', compoundType, subExpression);
    }

    assert(addressOfMethodsPrimitive.contains(argument.target));
    // Argument is an `expr.address` where `expr` is typed `bool`, `int`, or
    // `double`. Analyze `expr` further.
    switch (subExpression) {
      case InstanceGet _:
        // Look for `structOrUnion.member.address`.
        final interfaceTarget = subExpression.interfaceTarget;
        final enclosingClass = interfaceTarget.enclosingClass!;
        final targetSuperClass = enclosingClass.superclass;
        if (targetSuperClass == unionClass) {
          // `expr` is a union member access.
          // Union members have no additional offset. Pass in unchanged.
          return ('C', compoundType, subExpression.receiver);
        }
        if (targetSuperClass == structClass) {
          final getterName = interfaceTarget.name.text;
          final offsetOfName = '$getterName#offsetOf';
          final offsetGetter = enclosingClass.procedures
              .firstWhere((e) => e.name.text == offsetOfName);
          // `expr` is a struct member access. Struct members have an offset.
          // Pass in a newly constructed `_Compound`, with adjusted offset.
          return (
            'C',
            compoundType,
            _generateCompoundOffsetBy(
              subExpression.receiver,
              StaticGet(offsetGetter),
              fileOffset,
              variableName: "${parameter.name}#value",
            ),
          );
        }
      // Error, unrecognized getter.

      case StaticInvocation _:
        // Look for `array[index].address`.
        // Extensions have already been desugared, so no enclosing extension.
        final target = subExpression.target;
        if (!target.isExtensionMember) break;
        final positionalParameters = target.function.positionalParameters;
        if (positionalParameters.length != 2) break;
        final firstParamType = positionalParameters.first.type;
        if (firstParamType is! InterfaceType) break;
        if (firstParamType.classNode != arrayClass) break;
        // Extensions have already been desugared, so original name is lost.
        if (!target.name.text.endsWith('|[]')) break;
        final DartType arrayElementType;
        if (subExpression.arguments.types.isNotEmpty) {
          // AbiSpecificInteger.
          arrayElementType = subExpression.arguments.types.single;
        } else {
          arrayElementType = firstParamType.typeArguments.single;
        }
        final arrayElementSize =
            inlineSizeOf(arrayElementType as InterfaceType)!;
        // Array element. Pass in a newly constructed `_Compound`, with
        // adjusted offset.
        return (
          'C',
          compoundType,
          _generateCompoundOffsetBy(
            subExpression.arguments.positional[0],
            multiply(
              arrayElementSize,
              subExpression.arguments.positional[1], // index.
            ),
            fileOffset,
            variableName: "${parameter.name}#value",
          ),
        );

      case InstanceInvocation _:
        // Look for `typedData[index].address`
        final receiverType =
            staticTypeContext!.getExpressionType(subExpression.receiver);
        final implementsTypedData = TypeEnvironment(coreTypes, hierarchy)
            .isSubtypeOf(
                receiverType,
                InterfaceType(typedDataClass, Nullability.nonNullable),
                SubtypeCheckMode.withNullabilities);
        if (!implementsTypedData) break;
        if (receiverType is! InterfaceType) break;
        final classNode = receiverType.classNode;
        final elementSizeInBytes = _typedDataElementSizeInBytes(classNode);
        if (elementSizeInBytes == null) break;

        // Typed Data element off. Pass in new _Compound with extra
        // offset.
        return (
          'C',
          compoundType,
          ConstructorInvocation(
            compoundFromTypedDataBase,
            Arguments([
              subExpression.receiver,
              multiply(
                ConstantExpression(IntConstant(elementSizeInBytes)),
                subExpression.arguments.positional.first, // index.
              ),
            ]),
          ),
        );
      default:
    }

    diagnosticReporter.report(
      messageFfiAddressReceiver,
      argument.fileOffset,
      1,
      argument.location?.file,
    );
    // Pass nullptr to prevent cascading error messages.
    return (
      'E', // Error.
      pointerVoidType,
      StaticInvocation(
        fromAddressInternal,
        Arguments(
          <Expression>[ConstantExpression(IntConstant(0))],
          types: <DartType>[voidType],
        ),
      ),
    );
  }

  int? _typedDataElementSizeInBytes(Class classNode) {
    final name = classNode.name;
    if (name.contains('8')) {
      return 1;
    } else if (name.contains('16')) {
      return 2;
    } else if (name.contains('32')) {
      return 4;
    } else if (name.contains('64')) {
      return 8;
    }
    return null;
  }

  /// Returns:
  ///
  /// ```
  /// _Compound._fromTypedDataBase(
  ///   compound._typedDataBase,
  ///   compound._offsetInBytes + offsetInBytes,
  /// )
  /// ```
  Expression _generateCompoundOffsetBy(
    Expression compound,
    Expression offsetInBytes,
    int fileOffset, {
    String variableName = "#compoundOffset",
  }) {
    final compoundType = InterfaceType(
      compoundClass,
      Nullability.nonNullable,
      const <DartType>[],
    );

    final valueVar = VariableDeclaration(
      variableName,
      initializer: compound,
      type: compoundType,
      isSynthesized: true,
    )..fileOffset = fileOffset;
    final newArgument = BlockExpression(
      Block([
        valueVar,
      ]),
      ConstructorInvocation(
        compoundFromTypedDataBase,
        Arguments([
          getCompoundTypedDataBaseField(
            VariableGet(valueVar),
            fileOffset,
          ),
          add(
            getCompoundOffsetInBytesField(
              VariableGet(valueVar),
              fileOffset,
            ),
            offsetInBytes,
          ),
        ]),
      ),
    );
    return newArgument;
  }
}

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