// 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_definitions;

import 'dart:math' as math;

import 'package:front_end/src/api_unstable/vm.dart'
    show
        templateFfiEmptyStruct,
        templateFfiEmptyStructWarning,
        templateFfiFieldAnnotation,
        templateFfiFieldCyclic,
        templateFfiFieldNoAnnotation,
        templateFfiTypeMismatch,
        templateFfiFieldInitializer,
        templateFfiStructGeneric;

import 'package:kernel/ast.dart' hide MapEntry;
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/changed_structure_notifier.dart';
import 'package:kernel/target/targets.dart' show DiagnosticReporter;
import 'package:kernel/type_environment.dart' show SubtypeCheckMode;
import 'package:kernel/util/graph.dart';

import 'ffi.dart';

/// Checks and elaborates the dart:ffi structs and fields.
///
/// Input:
/// class Coord extends Struct {
///   @Double()
///   double x;
///
///   @Double()
///   double y;
///
///   Coord next;
/// }
///
/// Output:
/// class Coord extends Struct {
///   Coord.#fromTypedDataBase(Pointer<Coord> coord) : super._(coord);
///
///   Pointer<Double> get _xPtr => addressOf.cast();
///   set x(double v) => _xPtr.store(v);
///   double get x => _xPtr.load();
///
///   Pointer<Double> get _yPtr => addressOf.offsetBy(...).cast();
///   set y(double v) => _yPtr.store(v);
///   double get y => _yPtr.load();
///
///   ffi.Pointer<Coordinate> get _nextPtr => addressof.offsetBy(...).cast();
///   set next(Coordinate v) => _nextPtr.store(v);
///   Coordinate get next => _nextPtr.load();
///
///   static final int #sizeOf = 24;
/// }
FfiTransformerData transformLibraries(
    Component component,
    CoreTypes coreTypes,
    ClassHierarchy hierarchy,
    List<Library> libraries,
    DiagnosticReporter diagnosticReporter,
    ReferenceFromIndex referenceFromIndex,
    ChangedStructureNotifier changedStructureNotifier) {
  final LibraryIndex index = LibraryIndex(component,
      const ["dart:core", "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 FfiTransformerData({}, {}, {});
  }
  if (index.tryGetClass('dart:ffi', 'NativeFunction') == null) {
    // If dart:ffi is not loaded (for real): do not do the transformation.
    return FfiTransformerData({}, {}, {});
  }
  final transformer = new _FfiDefinitionTransformer(index, coreTypes, hierarchy,
      diagnosticReporter, referenceFromIndex, changedStructureNotifier);
  libraries.forEach(transformer.visitLibrary);
  transformer.manualVisitInTopologicalOrder();
  return FfiTransformerData(transformer.replacedGetters,
      transformer.replacedSetters, transformer.emptyStructs);
}

class StructDependencyGraph<T> implements Graph<T> {
  final Map<T, Iterable<T>> map;
  StructDependencyGraph(this.map);

  Iterable<T> get vertices => map.keys;
  Iterable<T> neighborsOf(T vertex) => map[vertex];
}

/// Checks and elaborates the dart:ffi structs and fields.
class _FfiDefinitionTransformer extends FfiTransformer {
  final LibraryIndex index;

  // Data structures for topological navigation.
  Map<Class, IndexedClass> indexedStructClasses = {};
  Map<Class, Set<Class>> structClassDependencies = {};
  Map<Class, bool> fieldsValid = {};
  Map<Class, Map<Abi, StructLayout>> structLayouts = {};

  Map<Field, Procedure> replacedGetters = {};
  Map<Field, Procedure> replacedSetters = {};
  Set<Class> emptyStructs = {};

  ChangedStructureNotifier changedStructureNotifier;

  IndexedLibrary currentLibraryIndex;

  _FfiDefinitionTransformer(
      this.index,
      CoreTypes coreTypes,
      ClassHierarchy hierarchy,
      DiagnosticReporter diagnosticReporter,
      ReferenceFromIndex referenceFromIndex,
      this.changedStructureNotifier)
      : super(index, coreTypes, hierarchy, diagnosticReporter,
            referenceFromIndex) {}

  void manualVisitInTopologicalOrder() {
    final connectedComponents =
        computeStrongComponents(StructDependencyGraph(structClassDependencies));

    connectedComponents.forEach((List<Class> component) {
      bool report = false;
      if (component.length > 1) {
        // Indirect cycle.
        report = true;
      }
      if (component.length == 1) {
        if (structClassDependencies[component.single]
            .contains(component.single)) {
          // Direct cycle.
          report = true;
        }
      }
      if (report) {
        component.forEach((Class e) {
          diagnosticReporter.report(
              templateFfiFieldCyclic.withArguments(
                  e.name, component.map((e) => e.name).toList()),
              e.fileOffset,
              e.name.length,
              e.fileUri);
        });
      }
    });

    final structClassesSorted = connectedComponents.expand((i) => i).toList();

    structClassesSorted.forEach(visitClassInTopologicalOrder);
  }

  @override
  visitLibrary(Library node) {
    currentLibraryIndex = referenceFromIndex?.lookupLibrary(node);
    return super.visitLibrary(node);
  }

  @override
  visitExtension(Extension node) {
    // The extension and it's members are only metadata.
    return node;
  }

  @override
  visitClass(Class node) {
    if (!hierarchy.isSubclassOf(node, structClass) || node == structClass) {
      return node;
    }

    _checkStructClass(node);

    // Struct objects are manufactured in the VM by 'allocate' and 'load'.
    _makeEntryPoint(node);

    final indexedClass = currentLibraryIndex?.lookupIndexedClass(node.name);
    _checkConstructors(node, indexedClass);
    indexedStructClasses[node] = indexedClass;

    fieldsValid[node] = _checkFieldAnnotations(node);

    return node;
  }

  void visitClassInTopologicalOrder(Class node) {
    final indexedClass = indexedStructClasses[node];
    if (fieldsValid[node]) {
      final structSize = _replaceFields(node, indexedClass);
      _replaceSizeOfMethod(node, structSize, indexedClass);
      changedStructureNotifier?.registerClassMemberChange(node);
    }
  }

  void _checkStructClass(Class node) {
    if (node.typeParameters.length > 0) {
      diagnosticReporter.report(
          templateFfiStructGeneric.withArguments(node.name),
          node.fileOffset,
          1,
          node.location.file);
    }

    if (node.supertype?.classNode != structClass) {
      // Not a struct, but extends a struct. The error will be emitted by
      // _FfiUseSiteTransformer.
      return;
    }
  }

  bool _isPointerType(DartType type) {
    return env.isSubtypeOf(
        type,
        InterfaceType(pointerClass, Nullability.legacy, [
          InterfaceType(nativeTypesClasses[NativeType.kNativeType.index],
              Nullability.legacy)
        ]),
        SubtypeCheckMode.ignoringNullabilities);
  }

  bool _isStructSubtype(DartType type) {
    return env.isSubtypeOf(type, InterfaceType(structClass, Nullability.legacy),
        SubtypeCheckMode.ignoringNullabilities);
  }

  /// Returns members of [node] that correspond to struct fields.
  ///
  /// Note that getters and setters that originate from an external field have
  /// the same `fileOffset`, we always returns getters first.
  List<Member> _structFieldMembers(Class node) {
    final externalGetterSetters = [...node.procedures]
      ..retainWhere((p) => p.isExternal && (p.isGetter || p.isSetter));
    final structMembers = [...node.fields, ...externalGetterSetters]
      ..sort((m1, m2) {
        if (m1.fileOffset == m2.fileOffset) {
          // Getter and setter have same offset, getter comes first.
          return (m1 as Procedure).isGetter ? -1 : 1;
        }
        return m1.fileOffset - m2.fileOffset;
      });
    return structMembers;
  }

  DartType _structFieldMemberType(Member member) {
    if (member is Field) {
      return member.type;
    }
    final Procedure p = member;
    if (p.isGetter) {
      return p.function.returnType;
    }
    return p.function.positionalParameters.single.type;
  }

  bool _checkFieldAnnotations(Class node) {
    bool success = true;
    structClassDependencies[node] = {};
    final membersWithAnnotations = _structFieldMembers(node)
      ..retainWhere((m) => (m is Field) || (m is Procedure && m.isGetter));
    for (final Member f in membersWithAnnotations) {
      if (f is Field) {
        if (f.initializer is! NullLiteral) {
          diagnosticReporter.report(
              templateFfiFieldInitializer.withArguments(f.name.text),
              f.fileOffset,
              f.name.text.length,
              f.fileUri);
        }
      }
      final nativeTypeAnnos = _getNativeTypeAnnotations(f).toList();
      final type = _structFieldMemberType(f);
      if (_isPointerType(type) || _isStructSubtype(type)) {
        if (nativeTypeAnnos.length != 0) {
          diagnosticReporter.report(
              templateFfiFieldNoAnnotation.withArguments(f.name.text),
              f.fileOffset,
              f.name.text.length,
              f.fileUri);
        }
        if (_isStructSubtype(type)) {
          final clazz = (type as InterfaceType).classNode;
          structClassDependencies[node].add(clazz);
        }
      } else if (nativeTypeAnnos.length != 1) {
        diagnosticReporter.report(
            templateFfiFieldAnnotation.withArguments(f.name.text),
            f.fileOffset,
            f.name.text.length,
            f.fileUri);
      } else {
        final DartType nativeType = InterfaceType(
            nativeTypesClasses[_getFieldType(nativeTypeAnnos.first).index],
            Nullability.legacy);
        final DartType shouldBeDartType = convertNativeTypeToDartType(
            nativeType,
            allowStructs: true,
            allowHandle: false);
        if (shouldBeDartType == null ||
            !env.isSubtypeOf(type, shouldBeDartType,
                SubtypeCheckMode.ignoringNullabilities)) {
          diagnosticReporter.report(
              templateFfiTypeMismatch.withArguments(type, shouldBeDartType,
                  nativeType, node.enclosingLibrary.isNonNullableByDefault),
              f.fileOffset,
              1,
              f.location.file);
          success = false;
        }
      }
    }
    return success;
  }

  void _checkConstructors(Class node, IndexedClass indexedClass) {
    final toRemove = <Initializer>[];

    // Constructors cannot have initializers because initializers refer to
    // fields, and the fields were replaced with getter/setter pairs.
    for (final Constructor c in node.constructors) {
      for (final Initializer i in c.initializers) {
        if (i is FieldInitializer) {
          toRemove.add(i);
          diagnosticReporter.report(
              templateFfiFieldInitializer.withArguments(i.field.name.text),
              i.fileOffset,
              1,
              i.location.file);
        }
      }
    }
    // Remove initializers referring to fields to prevent cascading errors.
    for (final Initializer i in toRemove) {
      i.remove();
    }

    // Add a constructor which 'load' can use.
    // C.#fromTypedDataBase(Object address) : super.fromPointer(address);
    final VariableDeclaration pointer = new VariableDeclaration("#pointer");
    final name = Name("#fromTypedDataBase");
    final referenceFrom = indexedClass?.lookupConstructor(name);
    final Constructor ctor = Constructor(
        FunctionNode(EmptyStatement(), positionalParameters: [pointer]),
        name: name,
        initializers: [
          SuperInitializer(structFromPointer, Arguments([VariableGet(pointer)]))
        ],
        fileUri: node.fileUri,
        reference: referenceFrom?.reference)
      ..fileOffset = node.fileOffset
      ..isNonNullableByDefault = node.enclosingLibrary.isNonNullableByDefault;
    _makeEntryPoint(ctor);
    node.addConstructor(ctor);
  }

  /// Computes the field offsets (for all ABIs) in the struct and replaces the
  /// fields with getters and setters using these offsets.
  ///
  /// Returns the total size of the struct (for all ABIs).
  Map<Abi, int> _replaceFields(Class node, IndexedClass indexedClass) {
    final classes = <Class>[];
    final types = <NativeType>[];
    final fields = <int, Field>{};
    final getters = <int, Procedure>{};
    final setters = <int, Procedure>{};

    int i = 0;
    for (final Member m in _structFieldMembers(node)) {
      final dartType = _structFieldMemberType(m);

      NativeType nativeType;
      Class clazz;
      if (_isPointerType(dartType)) {
        nativeType = NativeType.kPointer;
        clazz = pointerClass;
      } else if (_isStructSubtype(dartType)) {
        nativeType = NativeType.kStruct;
        clazz = (dartType as InterfaceType).classNode;
        if (emptyStructs.contains(clazz)) {
          diagnosticReporter.report(
              templateFfiEmptyStruct.withArguments(clazz.name),
              m.fileOffset,
              1,
              m.location.file);
        }
      } else {
        final nativeTypeAnnos = _getNativeTypeAnnotations(m).toList();
        if (nativeTypeAnnos.length == 1) {
          clazz = nativeTypeAnnos.first;
          nativeType = _getFieldType(clazz);
        }
      }

      if ((m is Field || (m is Procedure && m.isGetter)) &&
          nativeType != null) {
        types.add(nativeType);
        classes.add(clazz);
        if (m is Field) {
          fields[i] = m;
        }
        if (m is Procedure) {
          getters[i] = m;
        }
        i++;
      }
      if (m is Procedure && m.isSetter) {
        final index = i - 1; // The corresponding getter's index.
        if (getters.containsKey(index)) {
          setters[i - 1] = m;
        }
      }
    }

    _annoteStructWithFields(node, classes);
    if (classes.isEmpty) {
      diagnosticReporter.report(
          templateFfiEmptyStructWarning.withArguments(node.name),
          node.fileOffset,
          node.name.length,
          node.location.file);
      emptyStructs.add(node);
    }

    final structLayout = <Abi, StructLayout>{};
    for (final Abi abi in Abi.values) {
      structLayout[abi] = _calculateStructLayout(types, classes, abi);
    }
    structLayouts[node] = structLayout;

    for (final i in fields.keys) {
      final fieldOffsets = structLayout
          .map((Abi abi, StructLayout v) => MapEntry(abi, v.offsets[i]));
      final methods = _generateMethodsForField(
          fields[i], types[i], fieldOffsets, indexedClass);
      methods.forEach((p) => node.addProcedure(p));
    }

    for (final Field f in fields.values) {
      f.remove();
    }

    for (final i in getters.keys) {
      final fieldOffsets = structLayout
          .map((Abi abi, StructLayout v) => MapEntry(abi, v.offsets[i]));
      Procedure getter = getters[i];
      getter.function.body = _generateGetterStatement(
          getter.function.returnType,
          types[i],
          getter.fileOffset,
          fieldOffsets);
      getter.isExternal = false;
    }

    for (final i in setters.keys) {
      final fieldOffsets = structLayout
          .map((Abi abi, StructLayout v) => MapEntry(abi, v.offsets[i]));
      Procedure setter = setters[i];
      setter.function.body = _generateSetterStatement(
          setter.function.positionalParameters.single.type,
          types[i],
          setter.fileOffset,
          fieldOffsets,
          setter.function.positionalParameters.single);
      setter.isExternal = false;
    }

    return structLayout.map((k, v) => MapEntry(k, v.size));
  }

  void _annoteStructWithFields(Class node, List<Class> fieldTypes) {
    final types = fieldTypes.map((Class c) {
      List<DartType> typeArg = const [];
      if (c == pointerClass) {
        typeArg = [
          InterfaceType(pointerClass.superclass, Nullability.nonNullable)
        ];
      }
      return TypeLiteralConstant(
          InterfaceType(c, Nullability.nonNullable, typeArg));
    }).toList();

    node.addAnnotation(ConstantExpression(
        InstanceConstant(pragmaClass.reference, [], {
          pragmaName.getterReference: StringConstant("vm:ffi:struct-fields"),
          // TODO(dartbug.com/38158): Wrap list in class to be able to encode
          // more information when needed.
          pragmaOptions.getterReference: ListConstant(
              InterfaceType(typeClass, Nullability.nonNullable), types)
        }),
        InterfaceType(pragmaClass, Nullability.nonNullable, [])));
  }

  Statement _generateGetterStatement(DartType dartType, NativeType type,
      int fileOffset, Map<Abi, int> offsets) {
    final bool isPointer = type == NativeType.kPointer;
    final bool isStruct = type == NativeType.kStruct;

    // Sample output:
    // int get x => _loadInt8(pointer, offset);
    //
    // Treat Pointer fields different to get correct behavior without casts:
    // Pointer<Int8> get x =>
    //   _fromAddress<Int8>(_loadIntPtr(pointer, offset));
    //
    // Nested structs:
    // MyStruct get x =>
    //   MyStruct.#fromTypedDataBase(
    //     _addressOf is Pointer ?
    //       _fromAddress<MyStruct>((_addressOf as Pointer).address + offset) :
    //       (_addressOf as TypedData).buffer.asInt8List(
    //         (_addressOf as TypedData).offsetInBytes + offset,
    //         size
    //       )
    //   );
    if (isStruct) {
      final clazz = (dartType as InterfaceType).classNode;
      final constructor = clazz.constructors
          .firstWhere((c) => c.name == Name("#fromTypedDataBase"));
      final lengths =
          structLayouts[clazz].map((key, value) => MapEntry(key, value.size));
      Expression thisDotAddressOf() =>
          PropertyGet(ThisExpression(), addressOfField.name, addressOfField)
            ..fileOffset = fileOffset;
      return ReturnStatement(ConstructorInvocation(
          constructor,
          Arguments([
            ConditionalExpression(
                IsExpression(thisDotAddressOf(),
                    InterfaceType(pointerClass, Nullability.legacy)),
                StaticInvocation(
                    fromAddressInternal,
                    Arguments([
                      MethodInvocation(
                          PropertyGet(thisDotAddressOf(), addressGetter.name,
                              addressGetter)
                            ..fileOffset = fileOffset,
                          numAddition.name,
                          Arguments([runtimeBranchOnLayout(offsets)]),
                          numAddition)
                    ], types: [
                      dartType
                    ]))
                  ..fileOffset = fileOffset,
                MethodInvocation(
                    PropertyGet(
                        StaticInvocation(
                            unsafeCastMethod,
                            Arguments([
                              thisDotAddressOf()
                            ], types: [
                              InterfaceType(typedDataClass, Nullability.legacy)
                            ]))
                          ..fileOffset = fileOffset,
                        typedDataBufferGetter.name,
                        typedDataBufferGetter)
                      ..fileOffset = fileOffset,
                    byteBufferAsUint8List.name,
                    Arguments([
                      MethodInvocation(
                          PropertyGet(
                              StaticInvocation(
                                  unsafeCastMethod,
                                  Arguments([
                                    thisDotAddressOf()
                                  ], types: [
                                    InterfaceType(
                                        typedDataClass, Nullability.legacy)
                                  ]))
                                ..fileOffset = fileOffset,
                              typedDataOffsetInBytesGetter.name,
                              typedDataOffsetInBytesGetter)
                            ..fileOffset = fileOffset,
                          numAddition.name,
                          Arguments([runtimeBranchOnLayout(offsets)]),
                          numAddition),
                      runtimeBranchOnLayout(lengths)
                    ]),
                    byteBufferAsUint8List),
                InterfaceType(objectClass, Nullability.nonNullable))
          ]))
        ..fileOffset = fileOffset);
    }
    final loadMethod =
        isPointer ? loadMethods[NativeType.kIntptr] : loadMethods[type];
    Expression getterReturnValue = StaticInvocation(
        loadMethod,
        Arguments([
          PropertyGet(ThisExpression(), addressOfField.name, addressOfField)
            ..fileOffset = fileOffset,
          runtimeBranchOnLayout(offsets)
        ]))
      ..fileOffset = fileOffset;
    if (isPointer) {
      final typeArg = (dartType as InterfaceType).typeArguments.single;
      getterReturnValue = StaticInvocation(
          fromAddressInternal, Arguments([getterReturnValue], types: [typeArg]))
        ..fileOffset = fileOffset;
    }
    return ReturnStatement(getterReturnValue);
  }

  Statement _generateSetterStatement(DartType dartType, NativeType type,
      int fileOffset, Map<Abi, int> offsets, VariableDeclaration argument) {
    final bool isPointer = type == NativeType.kPointer;
    final bool isStruct = type == NativeType.kStruct;

    // Sample output:
    // set x(int v) => _storeInt8(pointer, offset, v);
    //
    // Treat Pointer fields different to get correct behavior without casts:
    // set x(Pointer<Int8> v) =>
    //   _storeIntPtr(pointer, offset, (v as Pointer<Int8>).address);
    //
    // Nested structs:
    // set x(MyStruct v) =>
    //   _memCopy(this._address, offset, v._address, 0, size);
    if (isStruct) {
      final clazz = (dartType as InterfaceType).classNode;
      final lengths =
          structLayouts[clazz].map((key, value) => MapEntry(key, value.size));
      return ReturnStatement(StaticInvocation(
          memCopy,
          Arguments([
            PropertyGet(ThisExpression(), addressOfField.name, addressOfField)
              ..fileOffset = fileOffset,
            runtimeBranchOnLayout(offsets),
            PropertyGet(
                VariableGet(argument), addressOfField.name, addressOfField)
              ..fileOffset = fileOffset,
            ConstantExpression(IntConstant(0)),
            runtimeBranchOnLayout(lengths),
          ]))
        ..fileOffset = fileOffset);
    }
    final storeMethod =
        isPointer ? storeMethods[NativeType.kIntptr] : storeMethods[type];
    Expression argumentExpression = VariableGet(argument)
      ..fileOffset = fileOffset;
    if (isPointer) {
      argumentExpression =
          PropertyGet(argumentExpression, addressGetter.name, addressGetter)
            ..fileOffset = fileOffset;
    }
    return ReturnStatement(StaticInvocation(
        storeMethod,
        Arguments([
          PropertyGet(ThisExpression(), addressOfField.name, addressOfField)
            ..fileOffset = fileOffset,
          runtimeBranchOnLayout(offsets),
          argumentExpression
        ]))
      ..fileOffset = fileOffset);
  }

  List<Procedure> _generateMethodsForField(Field field, NativeType type,
      Map<Abi, int> offsets, IndexedClass indexedClass) {
    final getterStatement =
        _generateGetterStatement(field.type, type, field.fileOffset, offsets);
    final Procedure getter = Procedure(field.name, ProcedureKind.Getter,
        FunctionNode(getterStatement, returnType: field.type),
        fileUri: field.fileUri,
        reference: indexedClass?.lookupGetterReference(field.name))
      ..fileOffset = field.fileOffset
      ..isNonNullableByDefault = field.isNonNullableByDefault;

    Procedure setter = null;
    if (!field.isFinal) {
      final VariableDeclaration argument =
          VariableDeclaration('#v', type: field.type)
            ..fileOffset = field.fileOffset;
      final setterStatement = _generateSetterStatement(
          field.type, type, field.fileOffset, offsets, argument);
      setter = Procedure(
          field.name,
          ProcedureKind.Setter,
          FunctionNode(setterStatement,
              returnType: VoidType(), positionalParameters: [argument]),
          fileUri: field.fileUri,
          reference: indexedClass?.lookupSetterReference(field.name))
        ..fileOffset = field.fileOffset
        ..isNonNullableByDefault = field.isNonNullableByDefault;
    }

    replacedGetters[field] = getter;
    replacedSetters[field] = setter;

    return [getter, if (setter != null) setter];
  }

  /// Sample output:
  /// int #sizeOf => [24,24,16][_abi()];
  void _replaceSizeOfMethod(
      Class struct, Map<Abi, int> sizes, IndexedClass indexedClass) {
    var name = Name("#sizeOf");
    var getterReference = indexedClass?.lookupGetterReference(name);
    final Field sizeOf = Field.immutable(name,
        isStatic: true,
        isFinal: true,
        initializer: runtimeBranchOnLayout(sizes),
        type: InterfaceType(intClass, Nullability.legacy),
        fileUri: struct.fileUri,
        getterReference: getterReference)
      ..fileOffset = struct.fileOffset;
    _makeEntryPoint(sizeOf);
    struct.addField(sizeOf);
  }

  int _sizeInBytes(NativeType type, Class clazz, Abi abi) {
    if (type == NativeType.kStruct) {
      final structLayout = structLayouts[clazz];
      if (structLayout == null) {
        // We have a cycle, so we don't know the size.
        return 0;
      }
      return structLayout[abi].size;
    }
    final int size = nativeTypeSizes[type.index];
    if (size == WORD_SIZE) {
      return wordSize[abi];
    }
    return size;
  }

  int _alignmentOf(NativeType type, Class clazz, Abi abi) {
    if (type == NativeType.kStruct) {
      final structLayout = structLayouts[clazz];
      if (structLayout == null) {
        // We have a cycle, so we don't know the size.
        return 0;
      }
      return structLayout[abi].alignment;
    }
    final int alignment = nonSizeAlignment[abi][type];
    if (alignment != null) return alignment;
    return _sizeInBytes(type, clazz, abi);
  }

  int _alignOffset(int offset, int alignment) {
    final int remainder = offset % alignment;
    if (remainder != 0) {
      offset -= remainder;
      offset += alignment;
    }
    return offset;
  }

  // Keep consistent with runtime/vm/compiler/ffi/native_type.cc
  // NativeCompoundType::FromNativeTypes.
  StructLayout _calculateStructLayout(
      List<NativeType> types, List<Class> classes, Abi abi) {
    int offset = 0;
    final offsets = <int>[];
    int structAlignment = 1;
    for (int i = 0; i < types.length; i++) {
      final int size = _sizeInBytes(types[i], classes[i], abi);
      final int alignment = _alignmentOf(types[i], classes[i], abi);
      offset = _alignOffset(offset, alignment);
      offsets.add(offset);
      offset += size;
      structAlignment = math.max(structAlignment, alignment);
    }
    final int size = _alignOffset(offset, structAlignment);
    return StructLayout(size, structAlignment, offsets);
  }

  void _makeEntryPoint(Annotatable node) {
    node.addAnnotation(ConstantExpression(
        InstanceConstant(pragmaClass.reference, [], {
          pragmaName.getterReference: StringConstant("vm:entry-point"),
          pragmaOptions.getterReference: NullConstant()
        }),
        InterfaceType(pragmaClass, Nullability.legacy, [])));
  }

  NativeType _getFieldType(Class c) {
    final fieldType = getType(c);

    if (fieldType == NativeType.kVoid) {
      // Fields cannot have Void types.
      return null;
    }
    return fieldType;
  }

  Iterable<Class> _getNativeTypeAnnotations(Member node) {
    return node.annotations
        .whereType<ConstantExpression>()
        .map((expr) => expr.constant)
        .whereType<InstanceConstant>()
        .map((constant) => constant.classNode)
        .where((klass) => _getFieldType(klass) != null);
  }
}

/// The layout of a `Struct` in one [Abi].
class StructLayout {
  /// Size of the entire struct.
  final int size;

  /// Alignment of struct when nested in other struct.
  final int alignment;

  /// Offset in bytes for each field, indexed by field number.
  final List<int> offsets;

  StructLayout(this.size, this.alignment, this.offsets);
}
