@@ -104,6 +104,7 @@ class BytecodeGenerator extends RecursiveVisitor {
104104 final PragmaAnnotationParser pragmaParser;
105105 final RecognizedMethods recognizedMethods;
106106 final Map <Uri , Source > astUriToSource;
107+ final LibraryIndex ffiLibraryIndex;
107108 late StringTable stringTable;
108109 late ObjectTable objectTable;
109110 late Component bytecodeComponent;
@@ -164,7 +165,8 @@ class BytecodeGenerator extends RecursiveVisitor {
164165 this .pragmaParser,
165166 this .staticTypeContext)
166167 : recognizedMethods = new RecognizedMethods (staticTypeContext),
167- astUriToSource = component.uriToSource {
168+ astUriToSource = component.uriToSource,
169+ ffiLibraryIndex = LibraryIndex (component, const ['dart:ffi' ]) {
168170 bytecodeComponent = new Component (coreTypes);
169171 stringTable = bytecodeComponent.stringTable;
170172 objectTable = bytecodeComponent.objectTable;
@@ -596,6 +598,11 @@ class BytecodeGenerator extends RecursiveVisitor {
596598 if (member.isExternal) {
597599 final String ? externalName = getExternalName (coreTypes, member);
598600 if (externalName == null ) {
601+ if (pragmaParser
602+ .parsedPragmas <ParsedFfiNativePragma >(member.annotations)
603+ .isNotEmpty) {
604+ flags | = FunctionDeclaration .isNativeFlag;
605+ }
599606 flags | = FunctionDeclaration .isExternalFlag;
600607 } else {
601608 flags | = FunctionDeclaration .isNativeFlag;
@@ -741,6 +748,10 @@ class BytecodeGenerator extends RecursiveVisitor {
741748 if (node.isExternal) {
742749 if (getExternalName (coreTypes, node) != null ) {
743750 _genExternalCall (node);
751+ } else if (pragmaParser
752+ .parsedPragmas <ParsedFfiNativePragma >(node.annotations)
753+ .isNotEmpty) {
754+ _generateFfiCall (null );
744755 } else {
745756 _genNoSuchMethodForExternal (node);
746757 }
@@ -839,6 +850,21 @@ class BytecodeGenerator extends RecursiveVisitor {
839850 asm.emitExternalCall (externalCallCpIndex);
840851 }
841852
853+ void _generateFfiCall (Expression ? target) {
854+ final function = enclosingFunction! ;
855+ for (var param in function.positionalParameters) {
856+ asm.emitPush (locals.getVarIndexInFrame (param));
857+ }
858+ for (var param in locals.originalNamedParameters) {
859+ asm.emitPush (locals.getVarIndexInFrame (param));
860+ }
861+ if (target != null ) {
862+ _generateNode (target);
863+ }
864+ final ffiCallCpIndex = cp.addFfiCall ();
865+ asm.emitFfiCall (ffiCallCpIndex);
866+ }
867+
842868 LibraryIndex get libraryIndex => coreTypes.index;
843869
844870 late Procedure growableListLiteral =
@@ -976,7 +1002,11 @@ class BytecodeGenerator extends RecursiveVisitor {
9761002 late Field syncStarIteratorYieldStarIterable = libraryIndex.getField (
9771003 'dart:async' , '_SyncStarIterator' , '_yieldStarIterable' );
9781004
979- late Library ? dartFfiLibrary = libraryIndex.tryGetLibrary ('dart:ffi' );
1005+ late Library ? dartFfiLibrary = ffiLibraryIndex.tryGetLibrary ('dart:ffi' );
1006+
1007+ late Procedure ? ffiCall = (dartFfiLibrary != null )
1008+ ? ffiLibraryIndex.getTopLevelProcedure ('dart:ffi' , '_ffiCall' )
1009+ : null ;
9801010
9811011 // Selector for implicit dynamic calls 'foo(...)' where
9821012 // variable 'foo' has type 'dynamic'.
@@ -3436,6 +3466,10 @@ class BytecodeGenerator extends RecursiveVisitor {
34363466 // Skip over AST of the argument, return null.
34373467 asm.emitPushNull ();
34383468 return ;
3469+ } else if (target == ffiCall) {
3470+ assert (args.named.isEmpty);
3471+ _generateFfiCall (args.positional.single);
3472+ return ;
34393473 }
34403474 if (target.isFactory) {
34413475 final constructedClass = target.enclosingClass! ;
0 commit comments