Skip to content

Commit 0bada8c

Browse files
dcharkescommit-bot@chromium.org
authored andcommitted
[cfe/ffi] Refactor dart:ffi transformations
Introduces the `NativeTypeCfe` type hierarchy for cleaner calculation of sizes and offsets of native types and cleaner code generation. The transformation ensures we're only visiting the structs in topological order, which means the struct type can always look up its (indirectly) nested structs in the `structCache`. This simplifies adding inline arrays (https://dart-review.googlesource.com/c/sdk/+/183640), packed structs, and unions to this transformation. `typedDataBaseOffset` is moved to the `FfiTransformer` because the dependent CL uses it in the `FfiUseSiteTransformer`. Bug: #35763 Bug: #38158 Bug: #38491 TEST=tests/ffi(_2)/(.*)by_value(.*)_test.dart Change-Id: I345e02c48844ca795f9137a5addd5ba89992e1c9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/184421 Reviewed-by: Dmitry Stefantsov <[email protected]> Reviewed-by: Clement Skau <[email protected]> Commit-Queue: Daco Harkes <[email protected]>
1 parent fca959e commit 0bada8c

File tree

3 files changed

+435
-274
lines changed

3 files changed

+435
-274
lines changed

pkg/vm/lib/transformations/ffi.dart

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@ class FfiTransformer extends Transformer {
247247
/// Classes corresponding to [NativeType], indexed by [NativeType].
248248
final List<Class> nativeTypesClasses;
249249

250+
Library currentLibrary;
251+
IndexedLibrary currentLibraryIndex;
252+
250253
FfiTransformer(this.index, this.coreTypes, this.hierarchy,
251254
this.diagnosticReporter, this.referenceFromIndex)
252255
: env = new TypeEnvironment(coreTypes, hierarchy),
@@ -336,6 +339,16 @@ class FfiTransformer extends Transformer {
336339
'DynamicLibraryExtension',
337340
LibraryIndex.tearoffPrefix + 'lookupFunction');
338341

342+
@override
343+
TreeNode visitLibrary(Library node) {
344+
assert(currentLibrary == null);
345+
currentLibrary = node;
346+
currentLibraryIndex = referenceFromIndex?.lookupLibrary(node);
347+
final result = super.visitLibrary(node);
348+
currentLibrary = null;
349+
return result;
350+
}
351+
339352
/// Computes the Dart type corresponding to a ffi.[NativeType], returns null
340353
/// if it is not a valid NativeType.
341354
///
@@ -441,6 +454,111 @@ class FfiTransformer extends Transformer {
441454
Arguments([StaticInvocation(abiMethod, Arguments([]))]),
442455
listElementAt);
443456
}
457+
458+
/// Generates an expression that returns a new `Pointer<dartType>` offset
459+
/// by [offset] from [pointer].
460+
///
461+
/// Sample output:
462+
///
463+
/// ```
464+
/// _fromAddress<dartType>(pointer.address + #offset)
465+
/// ```
466+
Expression _pointerOffset(Expression pointer, Expression offset,
467+
DartType dartType, int fileOffset) =>
468+
StaticInvocation(
469+
fromAddressInternal,
470+
Arguments([
471+
MethodInvocation(
472+
PropertyGet(pointer, addressGetter.name, addressGetter)
473+
..fileOffset = fileOffset,
474+
numAddition.name,
475+
Arguments([offset]),
476+
numAddition)
477+
], types: [
478+
dartType
479+
]))
480+
..fileOffset = fileOffset;
481+
482+
/// Generates an expression that returns a new `TypedData` offset
483+
/// by [offset] from [typedData].
484+
///
485+
/// Sample output:
486+
///
487+
/// ```
488+
/// TypedData #typedData = typedData;
489+
/// #typedData.buffer.asInt8List(#typedData.offsetInBytes + offset, length)
490+
/// ```
491+
Expression _typedDataOffset(Expression typedData, Expression offset,
492+
Expression length, int fileOffset) {
493+
final typedDataVar = VariableDeclaration("#typedData",
494+
initializer: typedData,
495+
type: InterfaceType(typedDataClass, Nullability.nonNullable))
496+
..fileOffset = fileOffset;
497+
return Let(
498+
typedDataVar,
499+
MethodInvocation(
500+
PropertyGet(VariableGet(typedDataVar), typedDataBufferGetter.name,
501+
typedDataBufferGetter)
502+
..fileOffset = fileOffset,
503+
byteBufferAsUint8List.name,
504+
Arguments([
505+
MethodInvocation(
506+
PropertyGet(
507+
VariableGet(typedDataVar),
508+
typedDataOffsetInBytesGetter.name,
509+
typedDataOffsetInBytesGetter)
510+
..fileOffset = fileOffset,
511+
numAddition.name,
512+
Arguments([offset]),
513+
numAddition),
514+
length
515+
]),
516+
byteBufferAsUint8List));
517+
}
518+
519+
/// Generates an expression that returns a new `TypedDataBase` offset
520+
/// by [offset] from [typedDataBase].
521+
///
522+
/// If [typedDataBase] is a `Pointer`, returns a `Pointer<dartType>`.
523+
/// If [typedDataBase] is a `TypedData` returns a `TypedData`.
524+
///
525+
/// Sample output:
526+
///
527+
/// ```
528+
/// Object #typedDataBase = typedDataBase;
529+
/// int #offset = offset;
530+
/// #typedDataBase is Pointer ?
531+
/// _pointerOffset<dartType>(#typedDataBase, #offset) :
532+
/// _typedDataOffset((#typedDataBase as TypedData), #offset, length)
533+
/// ```
534+
Expression typedDataBaseOffset(Expression typedDataBase, Expression offset,
535+
Expression length, DartType dartType, int fileOffset) {
536+
final typedDataBaseVar = VariableDeclaration("#typedDataBase",
537+
initializer: typedDataBase, type: coreTypes.objectNonNullableRawType)
538+
..fileOffset = fileOffset;
539+
final offsetVar = VariableDeclaration("#offset",
540+
initializer: offset, type: coreTypes.intNonNullableRawType)
541+
..fileOffset = fileOffset;
542+
return BlockExpression(
543+
Block([typedDataBaseVar, offsetVar]),
544+
ConditionalExpression(
545+
IsExpression(VariableGet(typedDataBaseVar),
546+
InterfaceType(pointerClass, Nullability.nonNullable)),
547+
_pointerOffset(VariableGet(typedDataBaseVar),
548+
VariableGet(offsetVar), dartType, fileOffset),
549+
_typedDataOffset(
550+
StaticInvocation(
551+
unsafeCastMethod,
552+
Arguments([
553+
VariableGet(typedDataBaseVar)
554+
], types: [
555+
InterfaceType(typedDataClass, Nullability.nonNullable)
556+
])),
557+
VariableGet(offsetVar),
558+
length,
559+
fileOffset),
560+
coreTypes.objectNonNullableRawType));
561+
}
444562
}
445563

446564
/// Contains all information collected by _FfiDefinitionTransformer that is

0 commit comments

Comments
 (0)