From c57ca1478165e18fd788ba6e1cad1a8c1cccee3d Mon Sep 17 00:00:00 2001 From: Daco Harkes Date: Tue, 13 Apr 2021 12:50:17 +0000 Subject: [PATCH] [vm/ffi] Refactor CFE transform to `compound` In preparation of having `Union` besides `Struct`, renames all mentions of `Struct` to `Compound`. Also, changes the type checking to have `allowXYZ` named arguments always default to false, and remove redundant arguments. Bug: https://github.com/dart-lang/sdk/issues/38491 tools/test.py ffi ffi_2 TEST=tests/ffi(_2)/(.*)by_value_(*.)_test.dart Change-Id: Ie5f7cf4189dc315f896e3b3933ff0e0580ac540f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/194424 Commit-Queue: Daco Harkes Reviewed-by: Aske Simon Christensen --- pkg/vm/lib/transformations/ffi.dart | 23 +- .../lib/transformations/ffi_definitions.dart | 225 +++++++++--------- pkg/vm/lib/transformations/ffi_use_sites.dart | 81 ++++--- 3 files changed, 170 insertions(+), 159 deletions(-) diff --git a/pkg/vm/lib/transformations/ffi.dart b/pkg/vm/lib/transformations/ffi.dart index f43b8aea0e90..bd70fef2ed5e 100644 --- a/pkg/vm/lib/transformations/ffi.dart +++ b/pkg/vm/lib/transformations/ffi.dart @@ -229,6 +229,7 @@ class FfiTransformer extends Transformer { final Field arraySizeDimension5Field; final Field arraySizeDimensionsField; final Class pointerClass; + final Class compoundClass; final Class structClass; final Class ffiStructLayoutClass; final Field ffiStructLayoutTypesField; @@ -330,6 +331,7 @@ class FfiTransformer extends Transformer { arraySizeDimensionsField = index.getMember('dart:ffi', '_ArraySize', 'dimensions'), pointerClass = index.getClass('dart:ffi', 'Pointer'), + compoundClass = index.getClass('dart:ffi', '_Compound'), structClass = index.getClass('dart:ffi', 'Struct'), ffiStructLayoutClass = index.getClass('dart:ffi', '_FfiStructLayout'), ffiStructLayoutTypesField = @@ -459,8 +461,7 @@ class FfiTransformer extends Transformer { /// [NativeFunction] S1 Function(S2, S3) /// where DartRepresentationOf(Tn) -> Sn DartType convertNativeTypeToDartType(DartType nativeType, - {bool allowStructs = false, - bool allowStructItself = false, + {bool allowCompounds = false, bool allowHandle = false, bool allowInlineArray = false}) { if (nativeType is! InterfaceType) { @@ -476,11 +477,11 @@ class FfiTransformer extends Transformer { } return nativeType; } - if (hierarchy.isSubclassOf(nativeClass, structClass)) { - if (structClass == nativeClass) { - return allowStructItself ? nativeType : null; + if (hierarchy.isSubclassOf(nativeClass, compoundClass)) { + if (nativeClass == structClass) { + return null; } - return allowStructs ? nativeType : null; + return allowCompounds ? nativeType : null; } if (nativeType_ == null) { return null; @@ -514,11 +515,11 @@ class FfiTransformer extends Transformer { if (fun.typeParameters.length != 0) return null; final DartType returnType = convertNativeTypeToDartType(fun.returnType, - allowStructs: allowStructs, allowHandle: true); + allowCompounds: true, allowHandle: true); if (returnType == null) return null; final List argumentTypes = fun.positionalParameters .map((t) => convertNativeTypeToDartType(t, - allowStructs: allowStructs, allowHandle: true)) + allowCompounds: true, allowHandle: true)) .toList(); if (argumentTypes.contains(null)) return null; return FunctionType(argumentTypes, returnType, Nullability.legacy); @@ -740,7 +741,7 @@ class FfiTransformer extends Transformer { return dimensions; } - bool isStructSubtype(DartType type) { + bool isCompoundSubtype(DartType type) { if (type is InvalidType) { return false; } @@ -762,9 +763,9 @@ class FfiTransformer extends Transformer { class FfiTransformerData { final Map replacedGetters; final Map replacedSetters; - final Set emptyStructs; + final Set emptyCompounds; FfiTransformerData( - this.replacedGetters, this.replacedSetters, this.emptyStructs); + this.replacedGetters, this.replacedSetters, this.emptyCompounds); } /// Checks if any library depends on dart:ffi. diff --git a/pkg/vm/lib/transformations/ffi_definitions.dart b/pkg/vm/lib/transformations/ffi_definitions.dart index da947c3256cd..732a67664b87 100644 --- a/pkg/vm/lib/transformations/ffi_definitions.dart +++ b/pkg/vm/lib/transformations/ffi_definitions.dart @@ -34,7 +34,7 @@ import 'package:kernel/util/graph.dart'; import 'ffi.dart'; -/// Checks and elaborates the dart:ffi structs and fields. +/// Checks and elaborates the dart:ffi compounds and their fields. /// /// Input: /// class Coord extends Struct { @@ -87,30 +87,30 @@ FfiTransformerData transformLibraries( libraries.forEach(transformer.visitLibrary); transformer.manualVisitInTopologicalOrder(); return FfiTransformerData(transformer.replacedGetters, - transformer.replacedSetters, transformer.emptyStructs); + transformer.replacedSetters, transformer.emptyCompounds); } -class StructDependencyGraph implements Graph { +class CompoundDependencyGraph implements Graph { final Map> map; - StructDependencyGraph(this.map); + CompoundDependencyGraph(this.map); Iterable get vertices => map.keys; Iterable neighborsOf(T vertex) => map[vertex]; } -/// Checks and elaborates the dart:ffi structs and fields. +/// Checks and elaborates the dart:ffi compounds and their fields. class _FfiDefinitionTransformer extends FfiTransformer { final LibraryIndex index; // Data structures for topological navigation. - Map indexedStructClasses = {}; - Map> structClassDependencies = {}; + Map indexedCompoundClasses = {}; + Map> compoundClassDependencies = {}; Map fieldsValid = {}; - Map structCache = {}; + Map compoundCache = {}; Map replacedGetters = {}; Map replacedSetters = {}; - Set emptyStructs = {}; + Set emptyCompounds = {}; ChangedStructureNotifier changedStructureNotifier; @@ -127,8 +127,8 @@ class _FfiDefinitionTransformer extends FfiTransformer { referenceFromIndex) {} void manualVisitInTopologicalOrder() { - final connectedComponents = - computeStrongComponents(StructDependencyGraph(structClassDependencies)); + final connectedComponents = computeStrongComponents( + CompoundDependencyGraph(compoundClassDependencies)); connectedComponents.forEach((List component) { bool report = false; @@ -137,7 +137,7 @@ class _FfiDefinitionTransformer extends FfiTransformer { report = true; } if (component.length == 1) { - if (structClassDependencies[component.single] + if (compoundClassDependencies[component.single] .contains(component.single)) { // Direct cycle. report = true; @@ -173,15 +173,17 @@ class _FfiDefinitionTransformer extends FfiTransformer { @override visitClass(Class node) { - if (!hierarchy.isSubclassOf(node, structClass) || node == structClass) { + if (!hierarchy.isSubclassOf(node, compoundClass) || + node == compoundClass || + node == structClass) { return node; } - final packing = _checkStructClass(node); + final packing = _checkCompoundClass(node); final indexedClass = currentLibraryIndex?.lookupIndexedClass(node.name); _checkConstructors(node, indexedClass); - indexedStructClasses[node] = indexedClass; + indexedCompoundClasses[node] = indexedClass; fieldsValid[node] = _checkFieldAnnotations(node, packing); @@ -189,16 +191,16 @@ class _FfiDefinitionTransformer extends FfiTransformer { } void visitClassInTopologicalOrder(Class node) { - final indexedClass = indexedStructClasses[node]; + final indexedClass = indexedCompoundClasses[node]; if (fieldsValid[node]) { - final structSize = _replaceFields(node, indexedClass); - _replaceSizeOfMethod(node, structSize, indexedClass); + final compoundSize = _replaceFields(node, indexedClass); + _replaceSizeOfMethod(node, compoundSize, indexedClass); changedStructureNotifier?.registerClassMemberChange(node); } } /// Returns packing if any. - int _checkStructClass(Class node) { + int _checkCompoundClass(Class node) { if (node.typeParameters.length > 0) { diagnosticReporter.report( templateFfiStructGeneric.withArguments(node.name), @@ -207,7 +209,7 @@ class _FfiDefinitionTransformer extends FfiTransformer { node.location.file); } - if (node.supertype?.classNode != structClass) { + if (node.superclass != structClass) { // Not a struct, but extends a struct. The error will be emitted by // _FfiUseSiteTransformer. return null; @@ -233,17 +235,18 @@ class _FfiDefinitionTransformer extends FfiTransformer { } return packing; } + return null; } - /// Returns members of [node] that correspond to struct fields. + /// Returns members of [node] that correspond to compound fields. /// /// Note that getters and setters that originate from an external field have /// the same `fileOffset`, we always returns getters first. - List _structFieldMembers(Class node) { + List _compoundFieldMembers(Class node) { final externalGetterSetters = [...node.procedures] ..retainWhere((p) => p.isExternal && (p.isGetter || p.isSetter)); - final structMembers = [...node.fields, ...externalGetterSetters] + final compoundMembers = [...node.fields, ...externalGetterSetters] ..sort((m1, m2) { if (m1.fileOffset == m2.fileOffset) { // Getter and setter have same offset, getter comes first. @@ -251,10 +254,10 @@ class _FfiDefinitionTransformer extends FfiTransformer { } return m1.fileOffset - m2.fileOffset; }); - return structMembers; + return compoundMembers; } - DartType _structFieldMemberType(Member member) { + DartType _compoundFieldMemberType(Member member) { if (member is Field) { return member.type; } @@ -267,8 +270,8 @@ class _FfiDefinitionTransformer extends FfiTransformer { bool _checkFieldAnnotations(Class node, int packing) { bool success = true; - structClassDependencies[node] = {}; - final membersWithAnnotations = _structFieldMembers(node) + compoundClassDependencies[node] = {}; + final membersWithAnnotations = _compoundFieldMembers(node) ..retainWhere((m) => (m is Field) || (m is Procedure && m.isGetter)); for (final Member f in membersWithAnnotations) { if (f is Field) { @@ -283,7 +286,7 @@ class _FfiDefinitionTransformer extends FfiTransformer { } } final nativeTypeAnnos = _getNativeTypeAnnotations(f).toList(); - final type = _structFieldMemberType(f); + final type = _compoundFieldMemberType(f); if (type is NullType) { diagnosticReporter.report( templateFfiFieldNull.withArguments(f.name.text), @@ -293,7 +296,7 @@ class _FfiDefinitionTransformer extends FfiTransformer { // This class is invalid, but continue reporting other errors on it. success = false; } else if (isPointerType(type) || - isStructSubtype(type) || + isCompoundSubtype(type) || isArrayType(type)) { if (nativeTypeAnnos.length != 0) { diagnosticReporter.report( @@ -304,17 +307,17 @@ class _FfiDefinitionTransformer extends FfiTransformer { // This class is invalid, but continue reporting other errors on it. success = false; } - if (isStructSubtype(type)) { + if (isCompoundSubtype(type)) { final clazz = (type as InterfaceType).classNode; - structClassDependencies[node].add(clazz); + compoundClassDependencies[node].add(clazz); _checkPacking(node, packing, clazz, f); } else if (isArrayType(type)) { final sizeAnnotations = _getArraySizeAnnotations(f); if (sizeAnnotations.length == 1) { final singleElementType = arraySingleElementType(type); - if (isStructSubtype(singleElementType)) { + if (isCompoundSubtype(singleElementType)) { final clazz = (singleElementType as InterfaceType).classNode; - structClassDependencies[node].add(clazz); + compoundClassDependencies[node].add(clazz); _checkPacking(node, packing, clazz, f); } if (arrayDimensions(type) != sizeAnnotations.single.length) { @@ -348,7 +351,7 @@ class _FfiDefinitionTransformer extends FfiTransformer { Nullability.legacy); final DartType shouldBeDartType = convertNativeTypeToDartType( nativeType, - allowStructs: true, + allowCompounds: true, allowHandle: false); if (shouldBeDartType == null || !env.isSubtypeOf(type, shouldBeDartType, @@ -450,10 +453,10 @@ class _FfiDefinitionTransformer extends FfiTransformer { node.addConstructor(ctor); } - /// Computes the field offsets (for all ABIs) in the struct and replaces the - /// fields with getters and setters using these offsets. + /// Computes the field offsets (for all ABIs) in the compound and replaces + /// the fields with getters and setters using these offsets. /// - /// Returns the total size of the struct (for all ABIs). + /// Returns the total size of the compound (for all ABIs). Map _replaceFields(Class node, IndexedClass indexedClass) { final types = []; final fields = {}; @@ -461,8 +464,8 @@ class _FfiDefinitionTransformer extends FfiTransformer { final setters = {}; int i = 0; - for (final Member m in _structFieldMembers(node)) { - final dartType = _structFieldMemberType(m); + for (final Member m in _compoundFieldMembers(node)) { + final dartType = _compoundFieldMemberType(m); NativeTypeCfe type; if (isArrayType(dartType)) { @@ -470,10 +473,10 @@ class _FfiDefinitionTransformer extends FfiTransformer { if (sizeAnnotations.length == 1) { final arrayDimensions = sizeAnnotations.single; type = NativeTypeCfe(this, dartType, - structCache: structCache, arrayDimensions: arrayDimensions); + compoundCache: compoundCache, arrayDimensions: arrayDimensions); } - } else if (isPointerType(dartType) || isStructSubtype(dartType)) { - type = NativeTypeCfe(this, dartType, structCache: structCache); + } else if (isPointerType(dartType) || isCompoundSubtype(dartType)) { + type = NativeTypeCfe(this, dartType, compoundCache: compoundCache); } else { // The C type is in the annotation, not the field type itself. final nativeTypeAnnos = _getNativeTypeAnnotations(m).toList(); @@ -506,21 +509,21 @@ class _FfiDefinitionTransformer extends FfiTransformer { final packing = (!packingAnnotations.isEmpty) ? packingAnnotations.first : null; - _annoteStructWithFields(node, types, packing); + _annoteCompoundWithFields(node, types, packing); if (types.isEmpty) { diagnosticReporter.report(templateFfiEmptyStruct.withArguments(node.name), node.fileOffset, node.name.length, node.location.file); - emptyStructs.add(node); + emptyCompounds.add(node); } - final structType = StructNativeTypeCfe(node, types, packing: packing); - structCache[node] = structType; - final structLayout = structType.layout; + final compoundType = StructNativeTypeCfe(node, types, packing: packing); + compoundCache[node] = compoundType; + final compoundLayout = compoundType.layout; final unalignedAccess = packing != null; for (final i in fields.keys) { - final fieldOffsets = structLayout - .map((Abi abi, StructLayout v) => MapEntry(abi, v.offsets[i])); + final fieldOffsets = compoundLayout + .map((Abi abi, CompoundLayout v) => MapEntry(abi, v.offsets[i])); final methods = _generateMethodsForField( fields[i], types[i], fieldOffsets, unalignedAccess, indexedClass); methods.forEach((p) => node.addProcedure(p)); @@ -531,8 +534,8 @@ class _FfiDefinitionTransformer extends FfiTransformer { } for (final i in getters.keys) { - final fieldOffsets = structLayout - .map((Abi abi, StructLayout v) => MapEntry(abi, v.offsets[i])); + final fieldOffsets = compoundLayout + .map((Abi abi, CompoundLayout v) => MapEntry(abi, v.offsets[i])); Procedure getter = getters[i]; getter.function.body = types[i].generateGetterStatement( getter.function.returnType, @@ -544,8 +547,8 @@ class _FfiDefinitionTransformer extends FfiTransformer { } for (final i in setters.keys) { - final fieldOffsets = structLayout - .map((Abi abi, StructLayout v) => MapEntry(abi, v.offsets[i])); + final fieldOffsets = compoundLayout + .map((Abi abi, CompoundLayout v) => MapEntry(abi, v.offsets[i])); Procedure setter = setters[i]; setter.function.body = types[i].generateSetterStatement( setter.function.positionalParameters.single.type, @@ -557,11 +560,11 @@ class _FfiDefinitionTransformer extends FfiTransformer { setter.isExternal = false; } - return structLayout.map((k, v) => MapEntry(k, v.size)); + return compoundLayout.map((k, v) => MapEntry(k, v.size)); } // packing is `int?`. - void _annoteStructWithFields( + void _annoteCompoundWithFields( Class node, List types, int packing) { List constants = types.map((t) => t.generateConstant(this)).toList(); @@ -630,7 +633,7 @@ class _FfiDefinitionTransformer extends FfiTransformer { /// Sample output: /// int #sizeOf => [24,24,16][_abi()]; void _replaceSizeOfMethod( - Class struct, Map sizes, IndexedClass indexedClass) { + Class compound, Map sizes, IndexedClass indexedClass) { var name = Name("#sizeOf"); var getterReference = indexedClass?.lookupGetterReference(name); final Field sizeOf = Field.immutable(name, @@ -638,10 +641,10 @@ class _FfiDefinitionTransformer extends FfiTransformer { isFinal: true, initializer: runtimeBranchOnLayout(sizes), type: InterfaceType(intClass, Nullability.legacy), - fileUri: struct.fileUri, + fileUri: compound.fileUri, getterReference: getterReference) - ..fileOffset = struct.fileOffset; - struct.addField(sizeOf); + ..fileOffset = compound.fileOffset; + compound.addField(sizeOf); } NativeType _getFieldType(Class c) { @@ -712,18 +715,20 @@ class _FfiDefinitionTransformer extends FfiTransformer { } } -/// The layout of a `Struct` in one [Abi]. -class StructLayout { - /// Size of the entire struct. +/// The layout of a `Struct` or `Union` in one [Abi]. +class CompoundLayout { + /// Size of the entire struct or union. final int size; - /// Alignment of struct when nested in other struct. + /// Alignment of struct or union when nested in a struct. final int alignment; /// Offset in bytes for each field, indexed by field number. + /// + /// Always 0 for unions. final List offsets; - StructLayout(this.size, this.alignment, this.offsets); + CompoundLayout(this.size, this.alignment, this.offsets); } /// AST node wrapper for native types. @@ -733,7 +738,7 @@ class StructLayout { abstract class NativeTypeCfe { factory NativeTypeCfe(FfiTransformer transformer, DartType dartType, {List arrayDimensions, - Map structCache = const {}}) { + Map compoundCache = const {}}) { if (transformer.isPrimitiveType(dartType)) { final clazz = (dartType as InterfaceType).classNode; final nativeType = transformer.getType(clazz); @@ -742,12 +747,12 @@ abstract class NativeTypeCfe { if (transformer.isPointerType(dartType)) { return PointerNativeTypeCfe(); } - if (transformer.isStructSubtype(dartType)) { + if (transformer.isCompoundSubtype(dartType)) { final clazz = (dartType as InterfaceType).classNode; - if (structCache.containsKey(clazz)) { - return structCache[clazz]; + if (compoundCache.containsKey(clazz)) { + return compoundCache[clazz]; } else { - throw "$clazz not found in structCache"; + throw "$clazz not found in compoundCache"; } } if (transformer.isArrayType(dartType)) { @@ -756,7 +761,7 @@ abstract class NativeTypeCfe { } final elementType = transformer.arraySingleElementType(dartType); final elementCfeType = - NativeTypeCfe(transformer, elementType, structCache: structCache); + NativeTypeCfe(transformer, elementType, compoundCache: compoundCache); return ArrayNativeTypeCfe.multi(elementCfeType, arrayDimensions); } throw "Invalid type $dartType"; @@ -777,13 +782,13 @@ abstract class NativeTypeCfe { /// See runtime/vm/compiler/ffi/native_type.cc:NativeType::FromAbstractType. Constant generateConstant(FfiTransformer transformer); - /// Generates the return statement for a struct field getter with this type. + /// Generates the return statement for a compound field getter with this type. /// /// Takes [transformer] to be able to lookup classes and methods. ReturnStatement generateGetterStatement(DartType dartType, int fileOffset, Map offsets, bool unalignedAccess, FfiTransformer transformer); - /// Generates the return statement for a struct field setter with this type. + /// Generates the return statement for a compound field setter with this type. /// /// Takes [transformer] to be able to lookup classes and methods. ReturnStatement generateSetterStatement( @@ -963,46 +968,14 @@ class PointerNativeTypeCfe implements NativeTypeCfe { ..fileOffset = fileOffset); } -class StructNativeTypeCfe implements NativeTypeCfe { +abstract class CompoundNativeTypeCfe implements NativeTypeCfe { final Class clazz; final List members; - // Nullable int. - final int packing; - - final Map layout; - - factory StructNativeTypeCfe(Class clazz, List members, - {int packing}) { - final layout = Map.fromEntries(Abi.values - .map((abi) => MapEntry(abi, _calculateLayout(members, packing, abi)))); - return StructNativeTypeCfe._(clazz, members, packing, layout); - } - - // Keep consistent with runtime/vm/compiler/ffi/native_type.cc - // NativeCompoundType::FromNativeTypes. - static StructLayout _calculateLayout( - List types, int packing, Abi abi) { - int offset = 0; - final offsets = []; - int structAlignment = 1; - for (int i = 0; i < types.length; i++) { - final int size = types[i].size[abi]; - int alignment = types[i].alignment[abi]; - if (packing != null && packing < alignment) { - alignment = packing; - } - 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); - } + final Map layout; - StructNativeTypeCfe._(this.clazz, this.members, this.packing, this.layout); + CompoundNativeTypeCfe._(this.clazz, this.members, this.layout); @override Map get size => @@ -1079,6 +1052,44 @@ class StructNativeTypeCfe implements NativeTypeCfe { ..fileOffset = fileOffset); } +class StructNativeTypeCfe extends CompoundNativeTypeCfe { + // Nullable int. + final int packing; + + factory StructNativeTypeCfe(Class clazz, List members, + {int packing}) { + final layout = Map.fromEntries(Abi.values + .map((abi) => MapEntry(abi, _calculateLayout(members, packing, abi)))); + return StructNativeTypeCfe._(clazz, members, packing, layout); + } + + StructNativeTypeCfe._(Class clazz, List members, this.packing, + Map layout) + : super._(clazz, members, layout); + + // Keep consistent with runtime/vm/compiler/ffi/native_type.cc + // NativeStructType::FromNativeTypes. + static CompoundLayout _calculateLayout( + List types, int packing, Abi abi) { + int offset = 0; + final offsets = []; + int structAlignment = 1; + for (int i = 0; i < types.length; i++) { + final int size = types[i].size[abi]; + int alignment = types[i].alignment[abi]; + if (packing != null && packing < alignment) { + alignment = packing; + } + offset = _alignOffset(offset, alignment); + offsets.add(offset); + offset += size; + structAlignment = math.max(structAlignment, alignment); + } + final int size = _alignOffset(offset, structAlignment); + return CompoundLayout(size, structAlignment, offsets); + } +} + class ArrayNativeTypeCfe implements NativeTypeCfe { final NativeTypeCfe elementType; final int length; diff --git a/pkg/vm/lib/transformations/ffi_use_sites.dart b/pkg/vm/lib/transformations/ffi_use_sites.dart index 20cfbe86ea31..52075cec57bb 100644 --- a/pkg/vm/lib/transformations/ffi_use_sites.dart +++ b/pkg/vm/lib/transformations/ffi_use_sites.dart @@ -35,7 +35,7 @@ import 'ffi.dart' UNKNOWN, wordSize; -/// Checks and replaces calls to dart:ffi struct fields and methods. +/// Checks and replaces calls to dart:ffi compound fields and methods. void transformLibraries( Component component, CoreTypes coreTypes, @@ -64,15 +64,15 @@ void transformLibraries( referenceFromIndex, ffiTransformerData.replacedGetters, ffiTransformerData.replacedSetters, - ffiTransformerData.emptyStructs); + ffiTransformerData.emptyCompounds); libraries.forEach(transformer.visitLibrary); } -/// Checks and replaces calls to dart:ffi struct fields and methods. +/// Checks and replaces calls to dart:ffi compound fields and methods. class _FfiUseSiteTransformer extends FfiTransformer { final Map replacedGetters; final Map replacedSetters; - final Set emptyStructs; + final Set emptyCompounds; StaticTypeContext _staticTypeContext; bool get isFfiLibrary => currentLibrary == ffiLibrary; @@ -89,7 +89,7 @@ class _FfiUseSiteTransformer extends FfiTransformer { ReferenceFromIndex referenceFromIndex, this.replacedGetters, this.replacedSetters, - this.emptyStructs) + this.emptyCompounds) : super(index, coreTypes, hierarchy, diagnosticReporter, referenceFromIndex) {} @@ -179,33 +179,33 @@ class _FfiUseSiteTransformer extends FfiTransformer { if (target == structPointerRef || target == structPointerElemAt) { final DartType nativeType = node.arguments.types[0]; - _ensureNativeTypeValid(nativeType, node, allowStructItself: false); + _ensureNativeTypeValid(nativeType, node, allowCompounds: true); return _replaceRef(node); } else if (target == structArrayElemAt) { final DartType nativeType = node.arguments.types[0]; - _ensureNativeTypeValid(nativeType, node, allowStructItself: false); + _ensureNativeTypeValid(nativeType, node, allowCompounds: true); return _replaceRefArray(node); } else if (target == arrayArrayElemAt) { final DartType nativeType = node.arguments.types[0]; _ensureNativeTypeValid(nativeType, node, - allowStructItself: false, allowInlineArray: true); + allowInlineArray: true, allowCompounds: true); return _replaceArrayArrayElemAt(node); } else if (target == arrayArrayAssignAt) { final DartType nativeType = node.arguments.types[0]; _ensureNativeTypeValid(nativeType, node, - allowStructItself: false, allowInlineArray: true); + allowInlineArray: true, allowCompounds: true); return _replaceArrayArrayElemAt(node, setter: true); } else if (target == sizeOfMethod) { final DartType nativeType = node.arguments.types[0]; - _ensureNativeTypeValid(nativeType, node); + _ensureNativeTypeValid(nativeType, node, allowCompounds: true); if (nativeType is InterfaceType) { Expression inlineSizeOf = _inlineSizeOf(nativeType); @@ -220,7 +220,7 @@ class _FfiUseSiteTransformer extends FfiTransformer { _ensureNativeTypeValid(nativeType, node); _ensureNativeTypeToDartType(nativeType, dartType, node); - _ensureNoEmptyStructs(dartType, node); + _ensureNoEmptyCompounds(dartType, node); final replacement = _replaceLookupFunction(node); @@ -229,7 +229,7 @@ class _FfiUseSiteTransformer extends FfiTransformer { if (returnType is InterfaceType) { final clazz = returnType.classNode; if (clazz.superclass == structClass) { - return _invokeStructConstructor(replacement, clazz); + return _invokeCompoundConstructor(replacement, clazz); } } } @@ -241,7 +241,7 @@ class _FfiUseSiteTransformer extends FfiTransformer { _ensureNativeTypeValid(nativeType, node); _ensureNativeTypeToDartType(nativeType, dartType, node); - _ensureNoEmptyStructs(dartType, node); + _ensureNoEmptyCompounds(dartType, node); final DartType nativeSignature = (nativeType as InterfaceType).typeArguments[0]; @@ -257,7 +257,7 @@ class _FfiUseSiteTransformer extends FfiTransformer { if (returnType is InterfaceType) { final clazz = returnType.classNode; if (clazz.superclass == structClass) { - return _invokeStructConstructor(replacement, clazz); + return _invokeCompoundConstructor(replacement, clazz); } } } @@ -272,7 +272,7 @@ class _FfiUseSiteTransformer extends FfiTransformer { _ensureNativeTypeValid(nativeType, node); _ensureNativeTypeToDartType(nativeType, dartType, node); - _ensureNoEmptyStructs(dartType, node); + _ensureNoEmptyCompounds(dartType, node); final funcType = dartType as FunctionType; @@ -348,16 +348,16 @@ class _FfiUseSiteTransformer extends FfiTransformer { final replacement = _replaceFromFunction(node); - final structClasses = funcType.positionalParameters + final compoundClasses = funcType.positionalParameters .whereType() .map((t) => t.classNode) .where((c) => c.superclass == structClass) .toList(); - return _invokeStructConstructors(replacement, structClasses); + return _invokeCompoundConstructors(replacement, compoundClasses); } else if (target == allocateMethod) { final DartType nativeType = node.arguments.types[0]; - _ensureNativeTypeValid(nativeType, node); + _ensureNativeTypeValid(nativeType, node, allowCompounds: true); // Inline the body to get rid of a generic invocation of sizeOf. // TODO(http://dartbug.com/39964): Add `allignmentOf()` call. @@ -388,9 +388,9 @@ class _FfiUseSiteTransformer extends FfiTransformer { /// Prevents the struct from being tree-shaken in TFA by invoking its /// constructor in a `_nativeEffect` expression. - Expression _invokeStructConstructor( - Expression nestedExpression, Class compositeClass) { - final constructor = compositeClass.constructors + Expression _invokeCompoundConstructor( + Expression nestedExpression, Class compoundClass) { + final constructor = compoundClass.constructors .firstWhere((c) => c.name == Name("#fromTypedDataBase")); return BlockExpression( Block([ @@ -414,15 +414,17 @@ class _FfiUseSiteTransformer extends FfiTransformer { ..fileOffset = nestedExpression.fileOffset; } - Expression _invokeStructConstructors( - Expression nestedExpression, List structClasses) => - structClasses.distinct().fold(nestedExpression, _invokeStructConstructor); + Expression _invokeCompoundConstructors( + Expression nestedExpression, List compoundClasses) => + compoundClasses + .distinct() + .fold(nestedExpression, _invokeCompoundConstructor); Expression _inlineSizeOf(InterfaceType nativeType) { final Class nativeClass = nativeType.classNode; final NativeType nt = getType(nativeClass); if (nt == null) { - // User-defined structs. + // User-defined compounds. Field sizeOfField = nativeClass.fields.single; return StaticGet(sizeOfField); } @@ -699,7 +701,7 @@ class _FfiUseSiteTransformer extends FfiTransformer { node.receiver.getStaticType(_staticTypeContext); final DartType nativeType = _pointerTypeGetTypeArg(pointerType); - _ensureNativeTypeValid(nativeType, node); + _ensureNativeTypeValid(nativeType, node, allowCompounds: true); Expression inlineSizeOf = _inlineSizeOf(nativeType); if (inlineSizeOf != null) { @@ -735,7 +737,7 @@ class _FfiUseSiteTransformer extends FfiTransformer { {bool allowHandle: false}) { final DartType correspondingDartType = convertNativeTypeToDartType( nativeType, - allowStructs: true, + allowCompounds: true, allowHandle: allowHandle); if (dartType == correspondingDartType) return; if (env.isSubtypeOf(correspondingDartType, dartType, @@ -753,11 +755,10 @@ class _FfiUseSiteTransformer extends FfiTransformer { void _ensureNativeTypeValid(DartType nativeType, Expression node, {bool allowHandle: false, - bool allowStructItself = true, + bool allowCompounds: false, bool allowInlineArray = false}) { if (!_nativeTypeValid(nativeType, - allowStructs: true, - allowStructItself: allowStructItself, + allowCompounds: allowCompounds, allowHandle: allowHandle, allowInlineArray: allowInlineArray)) { diagnosticReporter.report( @@ -770,12 +771,12 @@ class _FfiUseSiteTransformer extends FfiTransformer { } } - void _ensureNoEmptyStructs(DartType nativeType, Expression node) { + void _ensureNoEmptyCompounds(DartType nativeType, Expression node) { // Error on structs with no fields. if (nativeType is InterfaceType) { final Class nativeClass = nativeType.classNode; - if (hierarchy.isSubclassOf(nativeClass, structClass)) { - if (emptyStructs.contains(nativeClass)) { + if (hierarchy.isSubclassOf(nativeClass, compoundClass)) { + if (emptyCompounds.contains(nativeClass)) { diagnosticReporter.report( templateFfiEmptyStruct.withArguments(nativeClass.name), node.fileOffset, @@ -788,21 +789,19 @@ class _FfiUseSiteTransformer extends FfiTransformer { // Recurse when seeing a function type. if (nativeType is FunctionType) { nativeType.positionalParameters - .forEach((e) => _ensureNoEmptyStructs(e, node)); - _ensureNoEmptyStructs(nativeType.returnType, node); + .forEach((e) => _ensureNoEmptyCompounds(e, node)); + _ensureNoEmptyCompounds(nativeType.returnType, node); } } /// The Dart type system does not enforce that NativeFunction return and /// parameter types are only NativeTypes, so we need to check this. bool _nativeTypeValid(DartType nativeType, - {bool allowStructs: false, - bool allowStructItself = false, + {bool allowCompounds: false, bool allowHandle = false, bool allowInlineArray = false}) { return convertNativeTypeToDartType(nativeType, - allowStructs: allowStructs, - allowStructItself: allowStructItself, + allowCompounds: allowCompounds, allowHandle: allowHandle, allowInlineArray: allowInlineArray) != null; @@ -822,14 +821,14 @@ class _FfiUseSiteTransformer extends FfiTransformer { } Class _extendsOrImplementsSealedClass(Class klass) { - final Class superClass = klass.supertype?.classNode; + final Class superClass = klass.superclass; // The Opaque and Struct classes can be extended, but subclasses // cannot be (nor implemented). if (klass != opaqueClass && klass != structClass && (hierarchy.isSubtypeOf(klass, opaqueClass) || - hierarchy.isSubtypeOf(klass, structClass))) { + hierarchy.isSubtypeOf(klass, compoundClass))) { return superClass != opaqueClass && superClass != structClass ? superClass : null;