Version 2.11.0-261.0.dev
Merge commit 'b62e715073df0e50e39a55a367b2263e3daf998a' into 'dev'
diff --git a/pkg/front_end/lib/src/fasta/builder/field_builder.dart b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
index 04790c5..d215d8f 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -1475,12 +1475,6 @@
ClassMember get concrete => this;
@override
- bool operator ==(Object other) {
- if (identical(this, other)) return true;
- return false;
- }
-
- @override
bool isSameDeclaration(ClassMember other) {
if (identical(this, other)) return true;
return other is _SynthesizedFieldClassMember &&
diff --git a/pkg/front_end/lib/src/fasta/builder/member_builder.dart b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
index 2ac1790..58d5882 100644
--- a/pkg/front_end/lib/src/fasta/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
@@ -288,11 +288,5 @@
ClassMember get concrete => this;
@override
- bool operator ==(Object other) {
- if (identical(this, other)) return true;
- return false;
- }
-
- @override
String toString() => '$runtimeType($fullName,forSetter=${forSetter})';
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
index ef7586e..51255bf 100644
--- a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
@@ -265,8 +265,6 @@
ClassMember get abstract;
ClassMember get concrete;
- bool operator ==(Object other);
-
void inferType(ClassHierarchyBuilder hierarchy);
void registerOverrideDependency(Set<ClassMember> overriddenMembers);
@@ -2960,32 +2958,6 @@
void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
// Do nothing; this is only for declared members.
}
-
- @override
- int get hashCode {
- int hash = classBuilder.hashCode * 13 +
- isSetter.hashCode * 17 +
- isProperty.hashCode * 19 +
- modifyKernel.hashCode * 23 +
- name.hashCode * 29;
- for (ClassMember declaration in declarations) {
- hash ^= declaration.hashCode;
- }
- return hash;
- }
-
- @override
- bool operator ==(Object other) {
- if (identical(this, other)) return true;
- return other is DelayedMember &&
- classBuilder == other.classBuilder &&
- isSetter == other.isSetter &&
- isProperty == other.isProperty &&
- modifyKernel == other.modifyKernel &&
- name == other.name &&
- declarations.length == other.declarations.length &&
- _equalsList(declarations, other.declarations, declarations.length);
- }
}
/// This represents a concrete implementation inherited from a superclass that
@@ -3025,21 +2997,6 @@
"[${declarations.join(', ')}])";
}
- @override
- int get hashCode =>
- super.hashCode +
- concreteMember.hashCode * 11 +
- isInheritableConflict.hashCode * 13;
-
- @override
- bool operator ==(Object other) {
- if (identical(this, other)) return true;
- return super == other &&
- other is InheritedImplementationInterfaceConflict &&
- concreteMember == other.concreteMember &&
- isInheritableConflict == other.isInheritableConflict;
- }
-
void _ensureMemberAndCovariance(ClassHierarchyBuilder hierarchy) {
if (_member == null) {
if (!classBuilder.isAbstract) {
@@ -3155,24 +3112,6 @@
"[${declarations.join(', ')}])";
}
- @override
- int get hashCode {
- int hash = super.hashCode;
- hash ^= isImplicitlyAbstract.hashCode;
- for (ClassMember declaration in declarations) {
- hash ^= declaration.hashCode;
- }
- return hash;
- }
-
- @override
- bool operator ==(Object other) {
- if (identical(this, other)) return true;
- return super == other &&
- other is InterfaceConflict &&
- isImplicitlyAbstract == other.isImplicitlyAbstract;
- }
-
void _ensureMemberAndCovariance(ClassHierarchyBuilder hierarchy) {
if (_member != null) {
return;
@@ -3408,12 +3347,6 @@
}
@override
- bool operator ==(Object other) {
- if (identical(this, other)) return true;
- return super == other && other is AbstractMemberOverridingImplementation;
- }
-
- @override
ClassMember get abstract => abstractMember;
@override
@@ -3580,17 +3513,6 @@
return declaration is ClassBuilder ? declaration : null;
}
-/// Returns `true` if the first [length] elements of [a] and [b] are the same.
-bool _equalsList<T>(List<T> a, List<T> b, int length) {
- if (a.length < length || b.length < length) return false;
- for (int index = 0; index < length; index++) {
- if (a[index] != b[index]) {
- return false;
- }
- }
- return true;
-}
-
Set<ClassMember> toSet(
ClassBuilder classBuilder, Iterable<ClassMember> members) {
Set<ClassMember> result = <ClassMember>{};
diff --git a/pkg/front_end/testcases/general/build_issue_2688.dart b/pkg/front_end/testcases/general/build_issue_2688.dart
new file mode 100644
index 0000000..016f457
--- /dev/null
+++ b/pkg/front_end/testcases/general/build_issue_2688.dart
@@ -0,0 +1,129 @@
+// Copyright (c) 2020, 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.
+
+// Regression test for https://github.com/dart-lang/build/issues/2688
+
+mixin M0 {
+ int get property;
+}
+mixin M1 implements M0 {
+ int get property;
+}
+mixin M2 implements M1 {
+ int get property;
+}
+mixin M3 implements M2 {
+ int get property;
+}
+mixin M4 implements M3 {
+ int get property;
+}
+mixin M5 implements M4 {
+ int get property;
+}
+mixin M6 implements M5 {
+ int get property;
+}
+mixin M7 implements M6 {
+ int get property;
+}
+mixin M8 implements M7 {
+ int get property;
+}
+mixin M9 implements M8 {
+ int get property;
+}
+mixin M10 implements M9 {
+ int get property;
+}
+mixin M11 implements M10 {
+ int get property;
+}
+mixin M12 implements M11 {
+ int get property;
+}
+mixin M13 implements M12 {
+ int get property;
+}
+mixin M14 implements M13 {
+ int get property;
+}
+mixin M15 implements M14 {
+ int get property;
+}
+mixin M16 implements M15 {
+ int get property;
+}
+mixin M17 implements M16 {
+ int get property;
+}
+mixin M18 implements M17 {
+ int get property;
+}
+mixin M19 implements M18 {
+ int get property;
+}
+mixin M20 implements M19 {
+ int get property;
+}
+mixin M21 implements M20 {
+ int get property;
+}
+mixin M22 implements M21 {
+ int get property;
+}
+mixin M23 implements M22 {
+ int get property;
+}
+mixin M24 implements M23 {
+ int get property;
+}
+mixin M25 implements M24 {
+ int get property;
+}
+mixin M26 implements M25 {
+ int get property;
+}
+mixin M27 implements M26 {
+ int get property;
+}
+
+abstract class Super {
+ int get property;
+}
+
+class Class extends Super
+ with
+ M0,
+ M1,
+ M2,
+ M3,
+ M4,
+ M5,
+ M6,
+ M7,
+ M8,
+ M9,
+ M10,
+ M11,
+ M12,
+ M13,
+ M14,
+ M15,
+ M16,
+ M17,
+ M18,
+ M19,
+ M20,
+ M21,
+ M22,
+ M23,
+ M24,
+ M25,
+ M26,
+ M27 {
+ int get property => 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/build_issue_2688.dart.outline.expect b/pkg/front_end/testcases/general/build_issue_2688.dart.outline.expect
new file mode 100644
index 0000000..43701f7
--- /dev/null
+++ b/pkg/front_end/testcases/general/build_issue_2688.dart.outline.expect
@@ -0,0 +1,531 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class M0 extends core::Object /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M1 extends core::Object implements self::M0 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M2 extends core::Object implements self::M1 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M3 extends core::Object implements self::M2 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M4 extends core::Object implements self::M3 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M5 extends core::Object implements self::M4 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M6 extends core::Object implements self::M5 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M7 extends core::Object implements self::M6 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M8 extends core::Object implements self::M7 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M9 extends core::Object implements self::M8 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M10 extends core::Object implements self::M9 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M11 extends core::Object implements self::M10 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M12 extends core::Object implements self::M11 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M13 extends core::Object implements self::M12 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M14 extends core::Object implements self::M13 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M15 extends core::Object implements self::M14 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M16 extends core::Object implements self::M15 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M17 extends core::Object implements self::M16 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M18 extends core::Object implements self::M17 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M19 extends core::Object implements self::M18 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M20 extends core::Object implements self::M19 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M21 extends core::Object implements self::M20 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M22 extends core::Object implements self::M21 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M23 extends core::Object implements self::M22 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M24 extends core::Object implements self::M23 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M25 extends core::Object implements self::M24 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M26 extends core::Object implements self::M25 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M27 extends core::Object implements self::M26 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class Super extends core::Object {
+ synthetic constructor •() → self::Super*
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0 = self::Super with self::M0 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0*
+ : super self::Super::•()
+ ;
+}
+abstract class _Class&Super&M0&M1 = self::_Class&Super&M0 with self::M1 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1*
+ : super self::_Class&Super&M0::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2 = self::_Class&Super&M0&M1 with self::M2 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2*
+ : super self::_Class&Super&M0&M1::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3 = self::_Class&Super&M0&M1&M2 with self::M3 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3*
+ : super self::_Class&Super&M0&M1&M2::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4 = self::_Class&Super&M0&M1&M2&M3 with self::M4 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4*
+ : super self::_Class&Super&M0&M1&M2&M3::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5 = self::_Class&Super&M0&M1&M2&M3&M4 with self::M5 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5*
+ : super self::_Class&Super&M0&M1&M2&M3&M4::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6 = self::_Class&Super&M0&M1&M2&M3&M4&M5 with self::M6 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6 with self::M7 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 with self::M8 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 with self::M9 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 with self::M10 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 with self::M11 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 with self::M12 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 with self::M13 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 with self::M14 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 with self::M15 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 with self::M16 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 with self::M17 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 with self::M18 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 with self::M19 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 with self::M20 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 with self::M21 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 with self::M22 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 with self::M23 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 with self::M24 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 with self::M25 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 with self::M26 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 with self::M27 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26::•()
+ ;
+}
+class Class extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 {
+ synthetic constructor •() → self::Class*
+ ;
+ get property() → core::int*
+ ;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/general/build_issue_2688.dart.strong.expect b/pkg/front_end/testcases/general/build_issue_2688.dart.strong.expect
new file mode 100644
index 0000000..eee4f5a
--- /dev/null
+++ b/pkg/front_end/testcases/general/build_issue_2688.dart.strong.expect
@@ -0,0 +1,532 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class M0 extends core::Object /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M1 extends core::Object implements self::M0 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M2 extends core::Object implements self::M1 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M3 extends core::Object implements self::M2 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M4 extends core::Object implements self::M3 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M5 extends core::Object implements self::M4 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M6 extends core::Object implements self::M5 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M7 extends core::Object implements self::M6 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M8 extends core::Object implements self::M7 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M9 extends core::Object implements self::M8 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M10 extends core::Object implements self::M9 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M11 extends core::Object implements self::M10 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M12 extends core::Object implements self::M11 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M13 extends core::Object implements self::M12 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M14 extends core::Object implements self::M13 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M15 extends core::Object implements self::M14 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M16 extends core::Object implements self::M15 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M17 extends core::Object implements self::M16 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M18 extends core::Object implements self::M17 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M19 extends core::Object implements self::M18 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M20 extends core::Object implements self::M19 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M21 extends core::Object implements self::M20 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M22 extends core::Object implements self::M21 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M23 extends core::Object implements self::M22 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M24 extends core::Object implements self::M23 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M25 extends core::Object implements self::M24 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M26 extends core::Object implements self::M25 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M27 extends core::Object implements self::M26 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class Super extends core::Object {
+ synthetic constructor •() → self::Super*
+ : super core::Object::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0 = self::Super with self::M0 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0*
+ : super self::Super::•()
+ ;
+}
+abstract class _Class&Super&M0&M1 = self::_Class&Super&M0 with self::M1 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1*
+ : super self::_Class&Super&M0::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2 = self::_Class&Super&M0&M1 with self::M2 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2*
+ : super self::_Class&Super&M0&M1::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3 = self::_Class&Super&M0&M1&M2 with self::M3 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3*
+ : super self::_Class&Super&M0&M1&M2::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4 = self::_Class&Super&M0&M1&M2&M3 with self::M4 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4*
+ : super self::_Class&Super&M0&M1&M2&M3::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5 = self::_Class&Super&M0&M1&M2&M3&M4 with self::M5 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5*
+ : super self::_Class&Super&M0&M1&M2&M3&M4::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6 = self::_Class&Super&M0&M1&M2&M3&M4&M5 with self::M6 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6 with self::M7 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 with self::M8 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 with self::M9 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 with self::M10 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 with self::M11 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 with self::M12 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 with self::M13 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 with self::M14 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 with self::M15 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 with self::M16 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 with self::M17 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 with self::M18 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 with self::M19 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 with self::M20 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 with self::M21 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 with self::M22 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 with self::M23 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 with self::M24 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 with self::M25 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 with self::M26 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 with self::M27 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26::•()
+ ;
+}
+class Class extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 {
+ synthetic constructor •() → self::Class*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27::•()
+ ;
+ get property() → core::int*
+ return 0;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/build_issue_2688.dart.strong.transformed.expect b/pkg/front_end/testcases/general/build_issue_2688.dart.strong.transformed.expect
new file mode 100644
index 0000000..bce18c0
--- /dev/null
+++ b/pkg/front_end/testcases/general/build_issue_2688.dart.strong.transformed.expect
@@ -0,0 +1,840 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class M0 extends core::Object /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M1 extends core::Object implements self::M0 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M2 extends core::Object implements self::M1 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M3 extends core::Object implements self::M2 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M4 extends core::Object implements self::M3 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M5 extends core::Object implements self::M4 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M6 extends core::Object implements self::M5 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M7 extends core::Object implements self::M6 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M8 extends core::Object implements self::M7 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M9 extends core::Object implements self::M8 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M10 extends core::Object implements self::M9 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M11 extends core::Object implements self::M10 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M12 extends core::Object implements self::M11 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M13 extends core::Object implements self::M12 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M14 extends core::Object implements self::M13 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M15 extends core::Object implements self::M14 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M16 extends core::Object implements self::M15 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M17 extends core::Object implements self::M16 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M18 extends core::Object implements self::M17 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M19 extends core::Object implements self::M18 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M20 extends core::Object implements self::M19 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M21 extends core::Object implements self::M20 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M22 extends core::Object implements self::M21 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M23 extends core::Object implements self::M22 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M24 extends core::Object implements self::M23 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M25 extends core::Object implements self::M24 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M26 extends core::Object implements self::M25 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class M27 extends core::Object implements self::M26 /*isMixinDeclaration*/ {
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class Super extends core::Object {
+ synthetic constructor •() → self::Super*
+ : super core::Object::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0 extends self::Super implements self::M0 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0*
+ : super self::Super::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1 extends self::_Class&Super&M0 implements self::M1 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1*
+ : super self::_Class&Super&M0::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2 extends self::_Class&Super&M0&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2*
+ : super self::_Class&Super&M0&M1::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3 extends self::_Class&Super&M0&M1&M2 implements self::M3 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3*
+ : super self::_Class&Super&M0&M1&M2::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4 extends self::_Class&Super&M0&M1&M2&M3 implements self::M4 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4*
+ : super self::_Class&Super&M0&M1&M2&M3::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5 extends self::_Class&Super&M0&M1&M2&M3&M4 implements self::M5 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5*
+ : super self::_Class&Super&M0&M1&M2&M3&M4::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6 extends self::_Class&Super&M0&M1&M2&M3&M4&M5 implements self::M6 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6 implements self::M7 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 implements self::M8 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 implements self::M9 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 implements self::M10 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 implements self::M11 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 implements self::M12 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 implements self::M13 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 implements self::M14 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 implements self::M15 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 implements self::M16 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 implements self::M17 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 implements self::M18 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 implements self::M19 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 implements self::M20 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 implements self::M21 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 implements self::M22 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 implements self::M23 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 implements self::M24 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 implements self::M25 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 implements self::M26 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 implements self::M27 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26::•()
+ ;
+ abstract get property() → core::int*;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class Class extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 {
+ synthetic constructor •() → self::Class*
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27::•()
+ ;
+ get property() → core::int*
+ return 0;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/build_issue_2688.dart.textual_outline.expect b/pkg/front_end/testcases/general/build_issue_2688.dart.textual_outline.expect
new file mode 100644
index 0000000..ed52349
--- /dev/null
+++ b/pkg/front_end/testcases/general/build_issue_2688.dart.textual_outline.expect
@@ -0,0 +1,123 @@
+mixin M0 {
+ int get property;
+}
+mixin M1 implements M0 {
+ int get property;
+}
+mixin M2 implements M1 {
+ int get property;
+}
+mixin M3 implements M2 {
+ int get property;
+}
+mixin M4 implements M3 {
+ int get property;
+}
+mixin M5 implements M4 {
+ int get property;
+}
+mixin M6 implements M5 {
+ int get property;
+}
+mixin M7 implements M6 {
+ int get property;
+}
+mixin M8 implements M7 {
+ int get property;
+}
+mixin M9 implements M8 {
+ int get property;
+}
+mixin M10 implements M9 {
+ int get property;
+}
+mixin M11 implements M10 {
+ int get property;
+}
+mixin M12 implements M11 {
+ int get property;
+}
+mixin M13 implements M12 {
+ int get property;
+}
+mixin M14 implements M13 {
+ int get property;
+}
+mixin M15 implements M14 {
+ int get property;
+}
+mixin M16 implements M15 {
+ int get property;
+}
+mixin M17 implements M16 {
+ int get property;
+}
+mixin M18 implements M17 {
+ int get property;
+}
+mixin M19 implements M18 {
+ int get property;
+}
+mixin M20 implements M19 {
+ int get property;
+}
+mixin M21 implements M20 {
+ int get property;
+}
+mixin M22 implements M21 {
+ int get property;
+}
+mixin M23 implements M22 {
+ int get property;
+}
+mixin M24 implements M23 {
+ int get property;
+}
+mixin M25 implements M24 {
+ int get property;
+}
+mixin M26 implements M25 {
+ int get property;
+}
+mixin M27 implements M26 {
+ int get property;
+}
+
+abstract class Super {
+ int get property;
+}
+
+class Class extends Super
+ with
+ M0,
+ M1,
+ M2,
+ M3,
+ M4,
+ M5,
+ M6,
+ M7,
+ M8,
+ M9,
+ M10,
+ M11,
+ M12,
+ M13,
+ M14,
+ M15,
+ M16,
+ M17,
+ M18,
+ M19,
+ M20,
+ M21,
+ M22,
+ M23,
+ M24,
+ M25,
+ M26,
+ M27 {
+ int get property => 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/build_issue_2688.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/build_issue_2688.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d2ec562
--- /dev/null
+++ b/pkg/front_end/testcases/general/build_issue_2688.dart.textual_outline_modelled.expect
@@ -0,0 +1,122 @@
+abstract class Super {
+ int get property;
+}
+
+class Class extends Super
+ with
+ M0,
+ M1,
+ M2,
+ M3,
+ M4,
+ M5,
+ M6,
+ M7,
+ M8,
+ M9,
+ M10,
+ M11,
+ M12,
+ M13,
+ M14,
+ M15,
+ M16,
+ M17,
+ M18,
+ M19,
+ M20,
+ M21,
+ M22,
+ M23,
+ M24,
+ M25,
+ M26,
+ M27 {
+ int get property => 0;
+}
+
+main() {}
+mixin M0 {
+ int get property;
+}
+mixin M1 implements M0 {
+ int get property;
+}
+mixin M10 implements M9 {
+ int get property;
+}
+mixin M11 implements M10 {
+ int get property;
+}
+mixin M12 implements M11 {
+ int get property;
+}
+mixin M13 implements M12 {
+ int get property;
+}
+mixin M14 implements M13 {
+ int get property;
+}
+mixin M15 implements M14 {
+ int get property;
+}
+mixin M16 implements M15 {
+ int get property;
+}
+mixin M17 implements M16 {
+ int get property;
+}
+mixin M18 implements M17 {
+ int get property;
+}
+mixin M19 implements M18 {
+ int get property;
+}
+mixin M2 implements M1 {
+ int get property;
+}
+mixin M20 implements M19 {
+ int get property;
+}
+mixin M21 implements M20 {
+ int get property;
+}
+mixin M22 implements M21 {
+ int get property;
+}
+mixin M23 implements M22 {
+ int get property;
+}
+mixin M24 implements M23 {
+ int get property;
+}
+mixin M25 implements M24 {
+ int get property;
+}
+mixin M26 implements M25 {
+ int get property;
+}
+mixin M27 implements M26 {
+ int get property;
+}
+mixin M3 implements M2 {
+ int get property;
+}
+mixin M4 implements M3 {
+ int get property;
+}
+mixin M5 implements M4 {
+ int get property;
+}
+mixin M6 implements M5 {
+ int get property;
+}
+mixin M7 implements M6 {
+ int get property;
+}
+mixin M8 implements M7 {
+ int get property;
+}
+mixin M9 implements M8 {
+ int get property;
+}
diff --git a/pkg/front_end/testcases/nnbd/build_issue_2688.dart b/pkg/front_end/testcases/nnbd/build_issue_2688.dart
new file mode 100644
index 0000000..016f457
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/build_issue_2688.dart
@@ -0,0 +1,129 @@
+// Copyright (c) 2020, 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.
+
+// Regression test for https://github.com/dart-lang/build/issues/2688
+
+mixin M0 {
+ int get property;
+}
+mixin M1 implements M0 {
+ int get property;
+}
+mixin M2 implements M1 {
+ int get property;
+}
+mixin M3 implements M2 {
+ int get property;
+}
+mixin M4 implements M3 {
+ int get property;
+}
+mixin M5 implements M4 {
+ int get property;
+}
+mixin M6 implements M5 {
+ int get property;
+}
+mixin M7 implements M6 {
+ int get property;
+}
+mixin M8 implements M7 {
+ int get property;
+}
+mixin M9 implements M8 {
+ int get property;
+}
+mixin M10 implements M9 {
+ int get property;
+}
+mixin M11 implements M10 {
+ int get property;
+}
+mixin M12 implements M11 {
+ int get property;
+}
+mixin M13 implements M12 {
+ int get property;
+}
+mixin M14 implements M13 {
+ int get property;
+}
+mixin M15 implements M14 {
+ int get property;
+}
+mixin M16 implements M15 {
+ int get property;
+}
+mixin M17 implements M16 {
+ int get property;
+}
+mixin M18 implements M17 {
+ int get property;
+}
+mixin M19 implements M18 {
+ int get property;
+}
+mixin M20 implements M19 {
+ int get property;
+}
+mixin M21 implements M20 {
+ int get property;
+}
+mixin M22 implements M21 {
+ int get property;
+}
+mixin M23 implements M22 {
+ int get property;
+}
+mixin M24 implements M23 {
+ int get property;
+}
+mixin M25 implements M24 {
+ int get property;
+}
+mixin M26 implements M25 {
+ int get property;
+}
+mixin M27 implements M26 {
+ int get property;
+}
+
+abstract class Super {
+ int get property;
+}
+
+class Class extends Super
+ with
+ M0,
+ M1,
+ M2,
+ M3,
+ M4,
+ M5,
+ M6,
+ M7,
+ M8,
+ M9,
+ M10,
+ M11,
+ M12,
+ M13,
+ M14,
+ M15,
+ M16,
+ M17,
+ M18,
+ M19,
+ M20,
+ M21,
+ M22,
+ M23,
+ M24,
+ M25,
+ M26,
+ M27 {
+ int get property => 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/build_issue_2688.dart.outline.expect b/pkg/front_end/testcases/nnbd/build_issue_2688.dart.outline.expect
new file mode 100644
index 0000000..8b55238
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/build_issue_2688.dart.outline.expect
@@ -0,0 +1,241 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class M0 extends core::Object /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M1 extends core::Object implements self::M0 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M2 extends core::Object implements self::M1 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M3 extends core::Object implements self::M2 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M4 extends core::Object implements self::M3 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M5 extends core::Object implements self::M4 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M6 extends core::Object implements self::M5 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M7 extends core::Object implements self::M6 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M8 extends core::Object implements self::M7 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M9 extends core::Object implements self::M8 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M10 extends core::Object implements self::M9 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M11 extends core::Object implements self::M10 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M12 extends core::Object implements self::M11 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M13 extends core::Object implements self::M12 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M14 extends core::Object implements self::M13 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M15 extends core::Object implements self::M14 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M16 extends core::Object implements self::M15 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M17 extends core::Object implements self::M16 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M18 extends core::Object implements self::M17 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M19 extends core::Object implements self::M18 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M20 extends core::Object implements self::M19 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M21 extends core::Object implements self::M20 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M22 extends core::Object implements self::M21 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M23 extends core::Object implements self::M22 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M24 extends core::Object implements self::M23 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M25 extends core::Object implements self::M24 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M26 extends core::Object implements self::M25 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M27 extends core::Object implements self::M26 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class Super extends core::Object {
+ synthetic constructor •() → self::Super
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0 = self::Super with self::M0 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0
+ : super self::Super::•()
+ ;
+}
+abstract class _Class&Super&M0&M1 = self::_Class&Super&M0 with self::M1 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1
+ : super self::_Class&Super&M0::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2 = self::_Class&Super&M0&M1 with self::M2 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2
+ : super self::_Class&Super&M0&M1::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3 = self::_Class&Super&M0&M1&M2 with self::M3 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3
+ : super self::_Class&Super&M0&M1&M2::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4 = self::_Class&Super&M0&M1&M2&M3 with self::M4 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4
+ : super self::_Class&Super&M0&M1&M2&M3::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5 = self::_Class&Super&M0&M1&M2&M3&M4 with self::M5 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5
+ : super self::_Class&Super&M0&M1&M2&M3&M4::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6 = self::_Class&Super&M0&M1&M2&M3&M4&M5 with self::M6 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6 with self::M7 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 with self::M8 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 with self::M9 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 with self::M10 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 with self::M11 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 with self::M12 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 with self::M13 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 with self::M14 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 with self::M15 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 with self::M16 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 with self::M17 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 with self::M18 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 with self::M19 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 with self::M20 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 with self::M21 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 with self::M22 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 with self::M23 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 with self::M24 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 with self::M25 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 with self::M26 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 with self::M27 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26::•()
+ ;
+}
+class Class extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 {
+ synthetic constructor •() → self::Class
+ ;
+ get property() → core::int
+ ;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/nnbd/build_issue_2688.dart.strong.expect b/pkg/front_end/testcases/nnbd/build_issue_2688.dart.strong.expect
new file mode 100644
index 0000000..974275d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/build_issue_2688.dart.strong.expect
@@ -0,0 +1,242 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class M0 extends core::Object /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M1 extends core::Object implements self::M0 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M2 extends core::Object implements self::M1 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M3 extends core::Object implements self::M2 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M4 extends core::Object implements self::M3 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M5 extends core::Object implements self::M4 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M6 extends core::Object implements self::M5 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M7 extends core::Object implements self::M6 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M8 extends core::Object implements self::M7 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M9 extends core::Object implements self::M8 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M10 extends core::Object implements self::M9 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M11 extends core::Object implements self::M10 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M12 extends core::Object implements self::M11 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M13 extends core::Object implements self::M12 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M14 extends core::Object implements self::M13 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M15 extends core::Object implements self::M14 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M16 extends core::Object implements self::M15 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M17 extends core::Object implements self::M16 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M18 extends core::Object implements self::M17 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M19 extends core::Object implements self::M18 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M20 extends core::Object implements self::M19 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M21 extends core::Object implements self::M20 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M22 extends core::Object implements self::M21 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M23 extends core::Object implements self::M22 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M24 extends core::Object implements self::M23 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M25 extends core::Object implements self::M24 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M26 extends core::Object implements self::M25 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M27 extends core::Object implements self::M26 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class Super extends core::Object {
+ synthetic constructor •() → self::Super
+ : super core::Object::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0 = self::Super with self::M0 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0
+ : super self::Super::•()
+ ;
+}
+abstract class _Class&Super&M0&M1 = self::_Class&Super&M0 with self::M1 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1
+ : super self::_Class&Super&M0::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2 = self::_Class&Super&M0&M1 with self::M2 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2
+ : super self::_Class&Super&M0&M1::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3 = self::_Class&Super&M0&M1&M2 with self::M3 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3
+ : super self::_Class&Super&M0&M1&M2::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4 = self::_Class&Super&M0&M1&M2&M3 with self::M4 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4
+ : super self::_Class&Super&M0&M1&M2&M3::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5 = self::_Class&Super&M0&M1&M2&M3&M4 with self::M5 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5
+ : super self::_Class&Super&M0&M1&M2&M3&M4::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6 = self::_Class&Super&M0&M1&M2&M3&M4&M5 with self::M6 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6 with self::M7 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 with self::M8 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 with self::M9 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 with self::M10 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 with self::M11 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 with self::M12 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 with self::M13 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 with self::M14 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 with self::M15 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 with self::M16 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 with self::M17 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 with self::M18 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 with self::M19 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 with self::M20 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 with self::M21 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 with self::M22 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 with self::M23 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 with self::M24 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 with self::M25 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 with self::M26 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 with self::M27 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26::•()
+ ;
+}
+class Class extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 {
+ synthetic constructor •() → self::Class
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27::•()
+ ;
+ get property() → core::int
+ return 0;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/build_issue_2688.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/build_issue_2688.dart.strong.transformed.expect
new file mode 100644
index 0000000..a9961fa
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/build_issue_2688.dart.strong.transformed.expect
@@ -0,0 +1,270 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class M0 extends core::Object /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M1 extends core::Object implements self::M0 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M2 extends core::Object implements self::M1 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M3 extends core::Object implements self::M2 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M4 extends core::Object implements self::M3 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M5 extends core::Object implements self::M4 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M6 extends core::Object implements self::M5 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M7 extends core::Object implements self::M6 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M8 extends core::Object implements self::M7 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M9 extends core::Object implements self::M8 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M10 extends core::Object implements self::M9 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M11 extends core::Object implements self::M10 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M12 extends core::Object implements self::M11 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M13 extends core::Object implements self::M12 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M14 extends core::Object implements self::M13 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M15 extends core::Object implements self::M14 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M16 extends core::Object implements self::M15 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M17 extends core::Object implements self::M16 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M18 extends core::Object implements self::M17 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M19 extends core::Object implements self::M18 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M20 extends core::Object implements self::M19 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M21 extends core::Object implements self::M20 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M22 extends core::Object implements self::M21 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M23 extends core::Object implements self::M22 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M24 extends core::Object implements self::M23 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M25 extends core::Object implements self::M24 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M26 extends core::Object implements self::M25 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M27 extends core::Object implements self::M26 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class Super extends core::Object {
+ synthetic constructor •() → self::Super
+ : super core::Object::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0 extends self::Super implements self::M0 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0
+ : super self::Super::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1 extends self::_Class&Super&M0 implements self::M1 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1
+ : super self::_Class&Super&M0::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2 extends self::_Class&Super&M0&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2
+ : super self::_Class&Super&M0&M1::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3 extends self::_Class&Super&M0&M1&M2 implements self::M3 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3
+ : super self::_Class&Super&M0&M1&M2::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4 extends self::_Class&Super&M0&M1&M2&M3 implements self::M4 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4
+ : super self::_Class&Super&M0&M1&M2&M3::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5 extends self::_Class&Super&M0&M1&M2&M3&M4 implements self::M5 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5
+ : super self::_Class&Super&M0&M1&M2&M3&M4::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6 extends self::_Class&Super&M0&M1&M2&M3&M4&M5 implements self::M6 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6 implements self::M7 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 implements self::M8 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 implements self::M9 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 implements self::M10 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 implements self::M11 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 implements self::M12 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 implements self::M13 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 implements self::M14 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 implements self::M15 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 implements self::M16 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 implements self::M17 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 implements self::M18 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 implements self::M19 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 implements self::M20 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 implements self::M21 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 implements self::M22 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 implements self::M23 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 implements self::M24 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 implements self::M25 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 implements self::M26 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 implements self::M27 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26::•()
+ ;
+ abstract get property() → core::int;
+}
+class Class extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 {
+ synthetic constructor •() → self::Class
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27::•()
+ ;
+ get property() → core::int
+ return 0;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/build_issue_2688.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/build_issue_2688.dart.textual_outline.expect
new file mode 100644
index 0000000..ed52349
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/build_issue_2688.dart.textual_outline.expect
@@ -0,0 +1,123 @@
+mixin M0 {
+ int get property;
+}
+mixin M1 implements M0 {
+ int get property;
+}
+mixin M2 implements M1 {
+ int get property;
+}
+mixin M3 implements M2 {
+ int get property;
+}
+mixin M4 implements M3 {
+ int get property;
+}
+mixin M5 implements M4 {
+ int get property;
+}
+mixin M6 implements M5 {
+ int get property;
+}
+mixin M7 implements M6 {
+ int get property;
+}
+mixin M8 implements M7 {
+ int get property;
+}
+mixin M9 implements M8 {
+ int get property;
+}
+mixin M10 implements M9 {
+ int get property;
+}
+mixin M11 implements M10 {
+ int get property;
+}
+mixin M12 implements M11 {
+ int get property;
+}
+mixin M13 implements M12 {
+ int get property;
+}
+mixin M14 implements M13 {
+ int get property;
+}
+mixin M15 implements M14 {
+ int get property;
+}
+mixin M16 implements M15 {
+ int get property;
+}
+mixin M17 implements M16 {
+ int get property;
+}
+mixin M18 implements M17 {
+ int get property;
+}
+mixin M19 implements M18 {
+ int get property;
+}
+mixin M20 implements M19 {
+ int get property;
+}
+mixin M21 implements M20 {
+ int get property;
+}
+mixin M22 implements M21 {
+ int get property;
+}
+mixin M23 implements M22 {
+ int get property;
+}
+mixin M24 implements M23 {
+ int get property;
+}
+mixin M25 implements M24 {
+ int get property;
+}
+mixin M26 implements M25 {
+ int get property;
+}
+mixin M27 implements M26 {
+ int get property;
+}
+
+abstract class Super {
+ int get property;
+}
+
+class Class extends Super
+ with
+ M0,
+ M1,
+ M2,
+ M3,
+ M4,
+ M5,
+ M6,
+ M7,
+ M8,
+ M9,
+ M10,
+ M11,
+ M12,
+ M13,
+ M14,
+ M15,
+ M16,
+ M17,
+ M18,
+ M19,
+ M20,
+ M21,
+ M22,
+ M23,
+ M24,
+ M25,
+ M26,
+ M27 {
+ int get property => 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/build_issue_2688.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/build_issue_2688.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d2ec562
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/build_issue_2688.dart.textual_outline_modelled.expect
@@ -0,0 +1,122 @@
+abstract class Super {
+ int get property;
+}
+
+class Class extends Super
+ with
+ M0,
+ M1,
+ M2,
+ M3,
+ M4,
+ M5,
+ M6,
+ M7,
+ M8,
+ M9,
+ M10,
+ M11,
+ M12,
+ M13,
+ M14,
+ M15,
+ M16,
+ M17,
+ M18,
+ M19,
+ M20,
+ M21,
+ M22,
+ M23,
+ M24,
+ M25,
+ M26,
+ M27 {
+ int get property => 0;
+}
+
+main() {}
+mixin M0 {
+ int get property;
+}
+mixin M1 implements M0 {
+ int get property;
+}
+mixin M10 implements M9 {
+ int get property;
+}
+mixin M11 implements M10 {
+ int get property;
+}
+mixin M12 implements M11 {
+ int get property;
+}
+mixin M13 implements M12 {
+ int get property;
+}
+mixin M14 implements M13 {
+ int get property;
+}
+mixin M15 implements M14 {
+ int get property;
+}
+mixin M16 implements M15 {
+ int get property;
+}
+mixin M17 implements M16 {
+ int get property;
+}
+mixin M18 implements M17 {
+ int get property;
+}
+mixin M19 implements M18 {
+ int get property;
+}
+mixin M2 implements M1 {
+ int get property;
+}
+mixin M20 implements M19 {
+ int get property;
+}
+mixin M21 implements M20 {
+ int get property;
+}
+mixin M22 implements M21 {
+ int get property;
+}
+mixin M23 implements M22 {
+ int get property;
+}
+mixin M24 implements M23 {
+ int get property;
+}
+mixin M25 implements M24 {
+ int get property;
+}
+mixin M26 implements M25 {
+ int get property;
+}
+mixin M27 implements M26 {
+ int get property;
+}
+mixin M3 implements M2 {
+ int get property;
+}
+mixin M4 implements M3 {
+ int get property;
+}
+mixin M5 implements M4 {
+ int get property;
+}
+mixin M6 implements M5 {
+ int get property;
+}
+mixin M7 implements M6 {
+ int get property;
+}
+mixin M8 implements M7 {
+ int get property;
+}
+mixin M9 implements M8 {
+ int get property;
+}
diff --git a/pkg/front_end/testcases/nnbd/build_issue_2688.dart.weak.expect b/pkg/front_end/testcases/nnbd/build_issue_2688.dart.weak.expect
new file mode 100644
index 0000000..974275d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/build_issue_2688.dart.weak.expect
@@ -0,0 +1,242 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class M0 extends core::Object /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M1 extends core::Object implements self::M0 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M2 extends core::Object implements self::M1 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M3 extends core::Object implements self::M2 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M4 extends core::Object implements self::M3 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M5 extends core::Object implements self::M4 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M6 extends core::Object implements self::M5 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M7 extends core::Object implements self::M6 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M8 extends core::Object implements self::M7 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M9 extends core::Object implements self::M8 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M10 extends core::Object implements self::M9 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M11 extends core::Object implements self::M10 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M12 extends core::Object implements self::M11 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M13 extends core::Object implements self::M12 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M14 extends core::Object implements self::M13 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M15 extends core::Object implements self::M14 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M16 extends core::Object implements self::M15 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M17 extends core::Object implements self::M16 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M18 extends core::Object implements self::M17 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M19 extends core::Object implements self::M18 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M20 extends core::Object implements self::M19 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M21 extends core::Object implements self::M20 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M22 extends core::Object implements self::M21 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M23 extends core::Object implements self::M22 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M24 extends core::Object implements self::M23 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M25 extends core::Object implements self::M24 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M26 extends core::Object implements self::M25 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M27 extends core::Object implements self::M26 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class Super extends core::Object {
+ synthetic constructor •() → self::Super
+ : super core::Object::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0 = self::Super with self::M0 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0
+ : super self::Super::•()
+ ;
+}
+abstract class _Class&Super&M0&M1 = self::_Class&Super&M0 with self::M1 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1
+ : super self::_Class&Super&M0::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2 = self::_Class&Super&M0&M1 with self::M2 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2
+ : super self::_Class&Super&M0&M1::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3 = self::_Class&Super&M0&M1&M2 with self::M3 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3
+ : super self::_Class&Super&M0&M1&M2::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4 = self::_Class&Super&M0&M1&M2&M3 with self::M4 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4
+ : super self::_Class&Super&M0&M1&M2&M3::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5 = self::_Class&Super&M0&M1&M2&M3&M4 with self::M5 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5
+ : super self::_Class&Super&M0&M1&M2&M3&M4::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6 = self::_Class&Super&M0&M1&M2&M3&M4&M5 with self::M6 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6 with self::M7 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 with self::M8 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 with self::M9 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 with self::M10 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 with self::M11 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 with self::M12 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 with self::M13 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 with self::M14 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 with self::M15 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 with self::M16 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 with self::M17 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 with self::M18 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 with self::M19 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 with self::M20 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 with self::M21 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 with self::M22 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 with self::M23 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 with self::M24 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 with self::M25 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 with self::M26 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25::•()
+ ;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 with self::M27 /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26::•()
+ ;
+}
+class Class extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 {
+ synthetic constructor •() → self::Class
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27::•()
+ ;
+ get property() → core::int
+ return 0;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/build_issue_2688.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/build_issue_2688.dart.weak.transformed.expect
new file mode 100644
index 0000000..a9961fa
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/build_issue_2688.dart.weak.transformed.expect
@@ -0,0 +1,270 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class M0 extends core::Object /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M1 extends core::Object implements self::M0 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M2 extends core::Object implements self::M1 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M3 extends core::Object implements self::M2 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M4 extends core::Object implements self::M3 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M5 extends core::Object implements self::M4 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M6 extends core::Object implements self::M5 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M7 extends core::Object implements self::M6 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M8 extends core::Object implements self::M7 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M9 extends core::Object implements self::M8 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M10 extends core::Object implements self::M9 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M11 extends core::Object implements self::M10 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M12 extends core::Object implements self::M11 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M13 extends core::Object implements self::M12 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M14 extends core::Object implements self::M13 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M15 extends core::Object implements self::M14 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M16 extends core::Object implements self::M15 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M17 extends core::Object implements self::M16 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M18 extends core::Object implements self::M17 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M19 extends core::Object implements self::M18 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M20 extends core::Object implements self::M19 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M21 extends core::Object implements self::M20 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M22 extends core::Object implements self::M21 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M23 extends core::Object implements self::M22 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M24 extends core::Object implements self::M23 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M25 extends core::Object implements self::M24 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M26 extends core::Object implements self::M25 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class M27 extends core::Object implements self::M26 /*isMixinDeclaration*/ {
+ abstract get property() → core::int;
+}
+abstract class Super extends core::Object {
+ synthetic constructor •() → self::Super
+ : super core::Object::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0 extends self::Super implements self::M0 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0
+ : super self::Super::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1 extends self::_Class&Super&M0 implements self::M1 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1
+ : super self::_Class&Super&M0::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2 extends self::_Class&Super&M0&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2
+ : super self::_Class&Super&M0&M1::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3 extends self::_Class&Super&M0&M1&M2 implements self::M3 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3
+ : super self::_Class&Super&M0&M1&M2::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4 extends self::_Class&Super&M0&M1&M2&M3 implements self::M4 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4
+ : super self::_Class&Super&M0&M1&M2&M3::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5 extends self::_Class&Super&M0&M1&M2&M3&M4 implements self::M5 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5
+ : super self::_Class&Super&M0&M1&M2&M3&M4::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6 extends self::_Class&Super&M0&M1&M2&M3&M4&M5 implements self::M6 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6 implements self::M7 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 implements self::M8 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 implements self::M9 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 implements self::M10 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 implements self::M11 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 implements self::M12 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 implements self::M13 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 implements self::M14 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 implements self::M15 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 implements self::M16 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 implements self::M17 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 implements self::M18 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 implements self::M19 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 implements self::M20 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 implements self::M21 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 implements self::M22 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 implements self::M23 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 implements self::M24 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 implements self::M25 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 implements self::M26 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25::•()
+ ;
+ abstract get property() → core::int;
+}
+abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 implements self::M27 /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26::•()
+ ;
+ abstract get property() → core::int;
+}
+class Class extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 {
+ synthetic constructor •() → self::Class
+ : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27::•()
+ ;
+ get property() → core::int
+ return 0;
+}
+static method main() → dynamic {}
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index bad218c..d36d3be 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -1535,14 +1535,13 @@
Args<Type> argumentTypes(Member member) => _summaries[member]?.argumentTypes;
+ Type argumentType(Member member, VariableDeclaration memberParam) {
+ return _summaries[member]?.argumentType(member, memberParam);
+ }
+
List<VariableDeclaration> uncheckedParameters(Member member) =>
_summaries[member]?.uncheckedParameters;
- // The set of optional and named parameters to this procedure which
- // are passed at all call-sites.
- Set<String> alwaysPassedOptionalParameters(Member member) =>
- _summaries[member]?.alwaysPassedOptionalParameters() ?? const {};
-
bool isTearOffTaken(Member member) => _tearOffTaken.contains(member);
/// Returns true if this member is called on a receiver with static type
@@ -1565,6 +1564,12 @@
_methodsAndSettersCalledDynamically.contains(member) ||
_calledViaInterfaceSelector.contains(member);
+ /// Update the summary parameters to reflect a signature change with moved
+ /// and/or removed parameters.
+ void adjustFunctionParameters(Member member) {
+ _summaries[member]?.adjustFunctionParameters(member);
+ }
+
/// ---- Implementation of [CallHandler] interface. ----
@override
@@ -1648,4 +1653,9 @@
void recordMemberCalledViaThis(Member target) {
_calledViaThis.add(target);
}
+
+ @override
+ void recordTearOff(Procedure target) {
+ _tearOffTaken.add(target);
+ }
}
diff --git a/pkg/vm/lib/transformations/type_flow/calls.dart b/pkg/vm/lib/transformations/type_flow/calls.dart
index cdd0d0a..f935383 100644
--- a/pkg/vm/lib/transformations/type_flow/calls.dart
+++ b/pkg/vm/lib/transformations/type_flow/calls.dart
@@ -187,20 +187,15 @@
final List<T> values;
final List<String> names;
- // Whether it is not known which optional arguments are passed or not.
- final bool unknownArity;
-
int _hashCode;
- Args(this.values,
- {this.names = const <String>[], this.unknownArity = false}) {
+ Args(this.values, {this.names = const <String>[]}) {
assert(isSorted(names));
}
Args.withReceiver(Args<T> args, T receiver)
: values = new List.from(args.values),
- names = args.names,
- unknownArity = args.unknownArity {
+ names = args.names {
values[0] = receiver;
}
@@ -220,7 +215,6 @@
for (var n in names) {
hash = (((hash * 31) & kHashMask) + n.hashCode) & kHashMask;
}
- if (unknownArity) hash ^= -1;
return hash;
}
@@ -240,7 +234,7 @@
return false;
}
}
- return unknownArity == other.unknownArity;
+ return true;
}
return false;
}
@@ -263,11 +257,7 @@
buf.write(': ');
buf.write(values[positionalCount + i]);
}
- if (unknownArity) {
- buf.write(", <unknown arity>)");
- } else {
- buf.write(")");
- }
+ buf.write(")");
return buf.toString();
}
}
diff --git a/pkg/vm/lib/transformations/type_flow/native_code.dart b/pkg/vm/lib/transformations/type_flow/native_code.dart
index 0d00188..ba8a56d 100644
--- a/pkg/vm/lib/transformations/type_flow/native_code.dart
+++ b/pkg/vm/lib/transformations/type_flow/native_code.dart
@@ -32,6 +32,9 @@
/// Record the fact that given member is called from this.
void recordMemberCalledViaThis(Member target);
+
+ /// Record the fact that given method is torn off.
+ void recordTearOff(Procedure target) {}
}
class PragmaEntryPointsVisitor extends RecursiveVisitor {
diff --git a/pkg/vm/lib/transformations/type_flow/signature_shaking.dart b/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
new file mode 100644
index 0000000..e1a947c
--- /dev/null
+++ b/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
@@ -0,0 +1,523 @@
+// Copyright (c) 2020, 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:kernel/ast.dart';
+import 'package:kernel/external_name.dart';
+import 'package:kernel/type_environment.dart';
+
+import 'analysis.dart';
+import 'table_selector_assigner.dart';
+import 'types.dart';
+import 'utils.dart';
+import '../../metadata/procedure_attributes.dart';
+
+/// Transform parameters from optional to required when they are always passed,
+/// and remove parameters which are never passed or never used.
+///
+/// Signatures of static functions are considered on their own. Instance methods
+/// are grouped by table selector ID and thus can cover several implementations.
+///
+/// Definitions:
+/// - A parameter is used if it is mentioned in the body (or, for constructors,
+/// an initializer) of any implementation.
+/// - A parameter can be eliminated if either:
+/// 1. it is not used; or
+/// 2. it is never passed and is not written to in any implementation.
+/// - A function is eligible if it is not external and is guaranteed to not be
+/// called with an unknown call signature.
+///
+/// All eligible signatures are transformed such that they contain, in order:
+/// 1. All used positional parameters that are always passed, as required
+/// positional parameters.
+/// 2. All used named parameters that are always passed, as required positional
+/// parameters, alphabetically by name.
+/// 3. All used positional parameters that are not always passed and can't be
+/// eliminated, as positional parameters, each one required iff it was
+/// originally required.
+/// 4. All used named parameters that are not always passed and can't be
+/// eliminated, as named parameters in alphabetical order.
+class SignatureShaker {
+ final TypeFlowAnalysis typeFlowAnalysis;
+ final TableSelectorAssigner tableSelectorAssigner;
+
+ final Map<Member, _ProcedureInfo> _memberInfo = {};
+ final Map<int, _ProcedureInfo> _selectorInfo = {};
+
+ SignatureShaker(this.typeFlowAnalysis, this.tableSelectorAssigner);
+
+ _ProcedureInfo _infoForMember(Member member) {
+ if (!(member is Procedure &&
+ (member.kind == ProcedureKind.Method ||
+ member.kind == ProcedureKind.Factory) ||
+ member is Constructor)) {
+ return null;
+ }
+ if (member.isInstanceMember) {
+ final selectorId = tableSelectorAssigner.methodOrSetterSelectorId(member);
+ assert(selectorId != ProcedureAttributesMetadata.kInvalidSelectorId);
+ return _selectorInfo.putIfAbsent(selectorId, () => _ProcedureInfo());
+ } else {
+ return _memberInfo.putIfAbsent(member, () => _ProcedureInfo());
+ }
+ }
+
+ void transformComponent(Component component) {
+ _Collect(this).visitComponent(component);
+ _Transform(this).visitComponent(component);
+ }
+}
+
+class _ProcedureInfo {
+ final List<_ParameterInfo> positional = [];
+ final Map<String, _ParameterInfo> named = {};
+ int callCount = 0;
+ bool eligible = true;
+
+ _ParameterInfo ensurePositional(int i) {
+ if (positional.length <= i) {
+ assert(positional.length == i);
+ positional.add(_ParameterInfo(this, i));
+ }
+ return positional[i];
+ }
+
+ _ParameterInfo ensureNamed(String name) {
+ return named.putIfAbsent(name, () => _ParameterInfo(this, null));
+ }
+
+ bool transformNeeded(FunctionNode function) {
+ return positional.any((param) =>
+ param.canBeEliminated ||
+ (param.isAlwaysPassed &&
+ param.index >= function.requiredParameterCount)) ||
+ named.values
+ .any((param) => param.canBeEliminated || param.isAlwaysPassed);
+ }
+}
+
+class _ParameterInfo {
+ final _ProcedureInfo info;
+ final int index;
+
+ int passCount = 0;
+ bool isRead = false;
+ bool isWritten = false;
+
+ _ParameterInfo(this.info, this.index);
+
+ bool get isNamed => index == null;
+
+ bool get isUsed => isRead || isWritten;
+
+ bool get isAlwaysPassed => passCount == info.callCount;
+
+ bool get isNeverPassed => passCount == 0;
+
+ bool get canBeEliminated => !isUsed || isNeverPassed && !isWritten;
+
+ void observeImplicitChecks(
+ Member member, VariableDeclaration param, SignatureShaker shaker) {
+ if (param.isCovariant || param.isGenericCovariantImpl) {
+ // Covariant parameters have implicit type checks, which count as reads.
+ isRead = true;
+ } else if (param.type.nullability == Nullability.nonNullable) {
+ // When run in weak mode with null assertions enabled, parameters with
+ // non-nullable types have implicit null checks, which count as reads.
+ Type type = shaker.typeFlowAnalysis.argumentType(member, param);
+ if (type == null || type is NullableType) {
+ // TFA can't guarantee that the value isn't null. Preserve check.
+ isRead = true;
+ }
+ }
+ }
+}
+
+class _Collect extends RecursiveVisitor<void> {
+ final SignatureShaker shaker;
+
+ final Map<VariableDeclaration, _ParameterInfo> localParameters = {};
+
+ _Collect(this.shaker);
+
+ void enterFunction(Member member) {
+ final _ProcedureInfo info = shaker._infoForMember(member);
+ if (info == null) return;
+
+ localParameters.clear();
+ final FunctionNode fun = member.function;
+ for (int i = 0; i < fun.positionalParameters.length; i++) {
+ final VariableDeclaration param = fun.positionalParameters[i];
+ localParameters[param] = info.ensurePositional(i)
+ ..observeImplicitChecks(member, param, shaker);
+ }
+ for (VariableDeclaration param in fun.namedParameters) {
+ localParameters[param] = info.ensureNamed(param.name)
+ ..observeImplicitChecks(member, param, shaker);
+ }
+
+ if (shaker.typeFlowAnalysis.isCalledDynamically(member) ||
+ shaker.typeFlowAnalysis.isTearOffTaken(member) ||
+ shaker.typeFlowAnalysis.nativeCodeOracle
+ .isMemberReferencedFromNativeCode(member) ||
+ getExternalName(member) != null) {
+ info.eligible = false;
+ }
+ }
+
+ @override
+ void visitProcedure(Procedure node) {
+ enterFunction(node);
+ super.visitProcedure(node);
+ }
+
+ @override
+ void visitConstructor(Constructor node) {
+ enterFunction(node);
+ super.visitConstructor(node);
+ }
+
+ @override
+ void visitVariableGet(VariableGet node) {
+ localParameters[node.variable]?.isRead = true;
+ super.visitVariableGet(node);
+ }
+
+ @override
+ void visitVariableSet(VariableSet node) {
+ localParameters[node.variable]?.isWritten = true;
+ super.visitVariableSet(node);
+ }
+
+ void collectCall(Member member, Arguments args) {
+ final _ProcedureInfo info = shaker._infoForMember(member);
+ if (info == null) return;
+
+ for (int i = 0; i < args.positional.length; i++) {
+ info.ensurePositional(i).passCount++;
+ }
+ for (NamedExpression named in args.named) {
+ info.ensureNamed(named.name).passCount++;
+ }
+ info.callCount++;
+ }
+
+ @override
+ void visitMethodInvocation(MethodInvocation node) {
+ collectCall(node.interfaceTarget, node.arguments);
+ super.visitMethodInvocation(node);
+ }
+
+ @override
+ void visitSuperMethodInvocation(SuperMethodInvocation node) {
+ collectCall(node.interfaceTarget, node.arguments);
+ super.visitSuperMethodInvocation(node);
+ }
+
+ @override
+ void visitStaticInvocation(StaticInvocation node) {
+ collectCall(node.target, node.arguments);
+ super.visitStaticInvocation(node);
+ }
+
+ @override
+ void visitConstructorInvocation(ConstructorInvocation node) {
+ collectCall(node.target, node.arguments);
+ super.visitConstructorInvocation(node);
+ }
+
+ @override
+ void visitRedirectingInitializer(RedirectingInitializer node) {
+ collectCall(node.target, node.arguments);
+ super.visitRedirectingInitializer(node);
+ }
+
+ @override
+ void visitSuperInitializer(SuperInitializer node) {
+ collectCall(node.target, node.arguments);
+ super.visitSuperInitializer(node);
+ }
+}
+
+class _Transform extends RecursiveVisitor<void> {
+ final SignatureShaker shaker;
+
+ StaticTypeContext typeContext;
+ final Set<VariableDeclaration> eliminatedParams = {};
+ final List<LocalInitializer> addedInitializers = [];
+
+ _Transform(this.shaker);
+
+ void transformMemberSignature(Member member) {
+ typeContext =
+ StaticTypeContext(member, shaker.typeFlowAnalysis.environment);
+ eliminatedParams.clear();
+
+ final _ProcedureInfo info = shaker._infoForMember(member);
+ if (info == null || !info.eligible || info.callCount == 0) return;
+
+ final FunctionNode function = member.function;
+
+ if (!info.transformNeeded(function)) return;
+
+ final List<VariableDeclaration> positional = [];
+ final List<VariableDeclaration> named = [];
+ // 1. All used positional parameters that are always passed, as required
+ // positional parameters.
+ for (int i = 0; i < function.positionalParameters.length; i++) {
+ final _ParameterInfo param = info.positional[i];
+ if (!param.isAlwaysPassed) break;
+ if (param.isUsed) {
+ final VariableDeclaration variable = function.positionalParameters[i];
+ positional.add(variable);
+ variable.initializer = null;
+ }
+ }
+ // 2. All used named parameters that are always passed, as required
+ // positional parameters, alphabetically by name.
+ final List<VariableDeclaration> sortedNamed = function.namedParameters
+ .toList()
+ ..sort((var1, var2) => var1.name.compareTo(var2.name));
+ for (VariableDeclaration variable in sortedNamed) {
+ final _ParameterInfo param = info.named[variable.name];
+ if (param.isUsed && param.isAlwaysPassed) {
+ variable.initializer = null;
+ variable.isRequired = false;
+ positional.add(variable);
+ }
+ }
+ int requiredParameterCount = positional.length;
+ // 3. All used positional parameters that are not always passed and can't be
+ // eliminated, as positional parameters, each one required iff it was
+ // originally required.
+ for (int i = 0; i < function.positionalParameters.length; i++) {
+ final _ParameterInfo param = info.positional[i];
+ if (param.isUsed) {
+ final VariableDeclaration variable = function.positionalParameters[i];
+ if (param.canBeEliminated) {
+ assert(variable.initializer == null ||
+ variable.initializer is ConstantExpression);
+ eliminatedParams.add(variable);
+ } else if (!param.isAlwaysPassed) {
+ positional.add(variable);
+ if (i < function.requiredParameterCount) {
+ // The parameter is required, but it is not always passed. This is
+ // possible if the method is overridden by a method which makes the
+ // parameter optional.
+ assert(variable.initializer == null);
+ requiredParameterCount++;
+ }
+ }
+ }
+ }
+ // 4. All used named parameters that are not always passed and can't be
+ // eliminated, as named parameters in alphabetical order.
+ for (VariableDeclaration variable in sortedNamed) {
+ final _ParameterInfo param = info.named[variable.name];
+ if (param.isUsed) {
+ if (param.canBeEliminated) {
+ assert(variable.initializer == null ||
+ variable.initializer is ConstantExpression);
+ eliminatedParams.add(variable);
+ } else if (!param.isAlwaysPassed) {
+ named.add(variable);
+ }
+ }
+ }
+
+ assert(requiredParameterCount <= positional.length);
+ function.requiredParameterCount = requiredParameterCount;
+ function.positionalParameters = positional;
+ function.namedParameters = named;
+
+ shaker.typeFlowAnalysis.adjustFunctionParameters(member);
+ }
+
+ @override
+ void visitVariableGet(VariableGet node) {
+ if (eliminatedParams.contains(node.variable)) {
+ final ConstantExpression initializer = node.variable.initializer;
+ node.replaceWith(
+ ConstantExpression(initializer?.constant ?? NullConstant()));
+ }
+ }
+
+ @override
+ void visitConstructor(Constructor node) {
+ transformMemberSignature(node);
+ super.visitConstructor(node);
+ if (addedInitializers.isNotEmpty) {
+ // Insert hoisted constructor arguments before this/super initializer.
+ assert(node.initializers.last is RedirectingInitializer ||
+ node.initializers.last is SuperInitializer);
+ node.initializers
+ .insertAll(node.initializers.length - 1, addedInitializers.reversed);
+ addedInitializers.clear();
+ }
+ }
+
+ @override
+ void visitProcedure(Procedure node) {
+ transformMemberSignature(node);
+ super.visitProcedure(node);
+ }
+
+ static void forEachArgumentRev(Arguments args, _ProcedureInfo info,
+ void Function(Expression, _ParameterInfo) fun) {
+ for (int i = args.named.length - 1; i >= 0; i--) {
+ final NamedExpression namedExp = args.named[i];
+ fun(namedExp.value, info.named[namedExp.name]);
+ }
+ for (int i = args.positional.length - 1; i >= 0; i--) {
+ fun(args.positional[i], info.positional[i]);
+ }
+ }
+
+ void transformCall(
+ Member target, TreeNode call, Expression receiver, Arguments args) {
+ final _ProcedureInfo info = shaker._infoForMember(target);
+ if (info == null || !info.eligible) return;
+
+ bool transformNeeded = false;
+ bool hoistingNeeded = false;
+ forEachArgumentRev(args, info, (Expression arg, _ParameterInfo param) {
+ assert(!param.isNeverPassed);
+ if (!param.isUsed || param.isNamed && param.isAlwaysPassed) {
+ transformNeeded = true;
+ if (mayHaveSideEffects(arg)) {
+ hoistingNeeded = true;
+ }
+ }
+ });
+
+ if (!transformNeeded) return;
+
+ Map<Expression, VariableDeclaration> hoisted = {};
+ if (hoistingNeeded) {
+ if (call is Initializer) {
+ final Constructor constructor = call.parent;
+ forEachArgumentRev(args, info, (Expression arg, _ParameterInfo param) {
+ if (mayHaveOrSeeSideEffects(arg)) {
+ VariableDeclaration argVar = VariableDeclaration(null,
+ initializer: arg,
+ type: arg.getStaticType(typeContext),
+ isFinal: true);
+ addedInitializers
+ .add(LocalInitializer(argVar)..parent = constructor);
+ hoisted[arg] = argVar;
+ }
+ });
+ } else {
+ final TreeNode parent = call.parent;
+ Expression current = call;
+ forEachArgumentRev(args, info, (Expression arg, _ParameterInfo param) {
+ if (mayHaveOrSeeSideEffects(arg)) {
+ VariableDeclaration argVar = VariableDeclaration(null,
+ initializer: arg,
+ type: arg.getStaticType(typeContext),
+ isFinal: true);
+ current = Let(argVar, current);
+ hoisted[arg] = argVar;
+ }
+ });
+ if (receiver != null && mayHaveOrSeeSideEffects(receiver)) {
+ assert(receiver.parent == call);
+ final VariableDeclaration receiverVar = VariableDeclaration(null,
+ initializer: receiver,
+ type: receiver.getStaticType(typeContext),
+ isFinal: true);
+ current = Let(receiverVar, current);
+ call.replaceChild(receiver, VariableGet(receiverVar));
+ }
+
+ parent.replaceChild(call, current);
+ }
+ }
+
+ Expression getMaybeHoistedArg(Expression arg) {
+ final variable = hoisted[arg];
+ if (variable == null) return arg;
+ return VariableGet(variable);
+ }
+
+ final List<Expression> positional = [];
+ final List<NamedExpression> named = [];
+ // 1. All used positional parameters that are always passed, as required
+ // positional parameters.
+ for (int i = 0; i < args.positional.length; i++) {
+ final _ParameterInfo param = info.positional[i];
+ final Expression arg = args.positional[i];
+ if (param.isUsed && param.isAlwaysPassed) {
+ positional.add(getMaybeHoistedArg(arg));
+ }
+ }
+ // 2. All used named parameters that are always passed, as required
+ // positional parameters, alphabetically by name.
+ final List<NamedExpression> sortedNamed = args.named.toList()
+ ..sort((var1, var2) => var1.name.compareTo(var2.name));
+ for (NamedExpression arg in sortedNamed) {
+ final _ParameterInfo param = info.named[arg.name];
+ if (param.isUsed && param.isAlwaysPassed) {
+ positional.add(getMaybeHoistedArg(arg.value));
+ }
+ }
+ // 3. All used positional parameters that are not always passed and can't be
+ // eliminated, as positional parameters, each one required iff it was
+ // originally required.
+ for (int i = 0; i < args.positional.length; i++) {
+ final _ParameterInfo param = info.positional[i];
+ final Expression arg = args.positional[i];
+ if (param.isUsed && !param.isAlwaysPassed) {
+ positional.add(getMaybeHoistedArg(arg));
+ }
+ }
+ // 4. All used named parameters that are not always passed and can't be
+ // eliminated, as named parameters in alphabetical order.
+ // (Arguments are kept in original order.)
+ for (NamedExpression arg in args.named) {
+ final _ParameterInfo param = info.named[arg.name];
+ if (param.isUsed && !param.isAlwaysPassed) {
+ arg.value = getMaybeHoistedArg(arg.value)..parent = arg;
+ named.add(arg);
+ }
+ }
+
+ args.replaceWith(Arguments(positional, named: named, types: args.types));
+ }
+
+ @override
+ void visitMethodInvocation(MethodInvocation node) {
+ super.visitMethodInvocation(node);
+ transformCall(node.interfaceTarget, node, node.receiver, node.arguments);
+ }
+
+ @override
+ void visitSuperMethodInvocation(SuperMethodInvocation node) {
+ super.visitSuperMethodInvocation(node);
+ transformCall(node.interfaceTarget, node, null, node.arguments);
+ }
+
+ @override
+ void visitStaticInvocation(StaticInvocation node) {
+ super.visitStaticInvocation(node);
+ transformCall(node.target, node, null, node.arguments);
+ }
+
+ @override
+ void visitConstructorInvocation(ConstructorInvocation node) {
+ super.visitConstructorInvocation(node);
+ transformCall(node.target, node, null, node.arguments);
+ }
+
+ @override
+ void visitRedirectingInitializer(RedirectingInitializer node) {
+ super.visitRedirectingInitializer(node);
+ transformCall(node.target, node, null, node.arguments);
+ }
+
+ @override
+ void visitSuperInitializer(SuperInitializer node) {
+ super.visitSuperInitializer(node);
+ transformCall(node.target, node, null, node.arguments);
+ }
+}
diff --git a/pkg/vm/lib/transformations/type_flow/summary.dart b/pkg/vm/lib/transformations/type_flow/summary.dart
index ef97516..d529e68 100644
--- a/pkg/vm/lib/transformations/type_flow/summary.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary.dart
@@ -74,9 +74,6 @@
Type defaultValue;
Type _argumentType = const EmptyType();
- // Whether this parameter is passed at all call-sites.
- bool isAlwaysPassed = true;
-
Parameter(this.name, this.staticTypeForNarrowing);
@override
@@ -108,7 +105,6 @@
}
Type _observeNotPassed(TypeHierarchy typeHierarchy) {
- isAlwaysPassed = false;
final Type argType = defaultValue.specialize(typeHierarchy);
_observeArgumentType(argType, typeHierarchy);
return argType;
@@ -590,9 +586,9 @@
/// Summary is a linear sequence of statements representing a type flow in
/// one member, function or initializer.
class Summary {
- final int parameterCount;
- final int positionalParameterCount;
- final int requiredParameterCount;
+ int parameterCount;
+ int positionalParameterCount;
+ int requiredParameterCount;
List<Statement> _statements = <Statement>[];
TypeExpr result = null;
@@ -643,12 +639,6 @@
List<Type> types = new List<Type>(_statements.length);
- if (arguments.unknownArity) {
- for (int i = 0; i < parameterCount; ++i) {
- (_statements[i] as Parameter).isAlwaysPassed = false;
- }
- }
-
for (int i = 0; i < positionalArgCount; i++) {
final Parameter param = _statements[i] as Parameter;
if (args[i] is RuntimeType) {
@@ -726,6 +716,26 @@
return new Args<Type>(argTypes, names: argNames);
}
+ Type argumentType(Member member, VariableDeclaration memberParam) {
+ final int firstParamIndex =
+ numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
+ final positional = member.function.positionalParameters;
+ for (int i = 0; i < positional.length; i++) {
+ if (positional[i] == memberParam) {
+ final Parameter param = _statements[firstParamIndex + i] as Parameter;
+ assert(param.name == memberParam.name);
+ return param.argumentType;
+ }
+ }
+ for (int i = positionalParameterCount; i < parameterCount; i++) {
+ final Parameter param = _statements[i] as Parameter;
+ if (param.name == memberParam.name) {
+ return param.argumentType;
+ }
+ }
+ throw "Could not find argument type of parameter ${memberParam.name}";
+ }
+
List<VariableDeclaration> get uncheckedParameters {
final params = List<VariableDeclaration>();
for (Statement statement in _statements) {
@@ -738,14 +748,29 @@
return params;
}
- Set<String> alwaysPassedOptionalParameters() {
- final params = Set<String>();
- for (int i = requiredParameterCount; i < parameterCount; ++i) {
- final Parameter p = _statements[i] as Parameter;
- if (p.isAlwaysPassed) {
- params.add(p.name);
- }
+ /// Update the summary parameters to reflect a signature change with moved
+ /// and/or removed parameters.
+ void adjustFunctionParameters(Member member) {
+ // Just keep the parameters part of the summary, assuming that the rest is
+ // not used in later phases. The index values in the statements will be
+ // incorrect, but those are assumed to be not used either.
+ final int implicit =
+ (hasReceiverArg(member) ? 1 : 0) + numTypeParams(member);
+ final Map<String, Parameter> paramsByName = {};
+ for (int i = implicit; i < parameterCount; i++) {
+ final Parameter param = statements[i];
+ paramsByName[param.name] = param;
}
- return params;
+ FunctionNode function = member.function;
+ statements.length = implicit;
+ for (VariableDeclaration param in function.positionalParameters) {
+ statements.add(paramsByName[param.name]);
+ }
+ positionalParameterCount = statements.length;
+ for (VariableDeclaration param in function.namedParameters) {
+ statements.add(paramsByName[param.name]);
+ }
+ parameterCount = statements.length;
+ requiredParameterCount = implicit + function.requiredParameterCount;
}
}
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index b545936..64170aa 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -847,7 +847,7 @@
break;
}
- return new Args<Type>(args, names: names, unknownArity: true);
+ return new Args<Type>(args, names: names);
}
TypeExpr _visit(TreeNode node) => node.accept(this);
@@ -2423,6 +2423,7 @@
final Procedure procedure = constant.procedure;
summaryCollector._entryPointsListener
.addRawCall(new DirectSelector(procedure));
+ summaryCollector._entryPointsListener.recordTearOff(procedure);
return _getStaticType(constant);
}
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index cf64db8..53f5219 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -13,10 +13,10 @@
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/library_index.dart' show LibraryIndex;
import 'package:kernel/type_environment.dart';
-import 'package:kernel/external_name.dart';
import 'analysis.dart';
import 'calls.dart';
+import 'signature_shaking.dart';
import 'protobuf_handler.dart' show ProtobufHandler;
import 'summary.dart';
import 'table_selector_assigner.dart';
@@ -86,7 +86,6 @@
final transformsStopWatch = new Stopwatch()..start();
final treeShaker = new TreeShaker(component, typeFlowAnalysis,
- treeShakeSignatures: treeShakeSignatures,
treeShakeWriteOnlyFields: treeShakeWriteOnlyFields);
treeShaker.transformComponent(component);
@@ -96,6 +95,12 @@
final tableSelectorAssigner = new TableSelectorAssigner(component);
+ if (treeShakeSignatures) {
+ final signatureShaker =
+ new SignatureShaker(typeFlowAnalysis, tableSelectorAssigner);
+ signatureShaker.transformComponent(component);
+ }
+
final unboxingInfo = new UnboxingInfoManager(typeFlowAnalysis)
..analyzeComponent(component, typeFlowAnalysis, tableSelectorAssigner);
@@ -103,8 +108,6 @@
tableSelectorAssigner, unboxingInfo)
.visitComponent(component);
- treeShaker.finalizeSignatures();
-
transformsStopWatch.stop();
statPrint("TF analysis took ${analysisStopWatch.elapsedMilliseconds}ms");
@@ -510,17 +513,14 @@
_TreeShakerConstantVisitor constantVisitor;
_TreeShakerPass1 _pass1;
_TreeShakerPass2 _pass2;
- _SignatureShaker _signatureShaker;
TreeShaker(Component component, this.typeFlowAnalysis,
- {bool treeShakeSignatures: true, this.treeShakeWriteOnlyFields: true}) {
+ {this.treeShakeWriteOnlyFields: true}) {
fieldMorpher = new FieldMorpher(this);
typeVisitor = new _TreeShakerTypeVisitor(this);
constantVisitor = new _TreeShakerConstantVisitor(this, typeVisitor);
_pass1 = new _TreeShakerPass1(this);
_pass2 = new _TreeShakerPass2(this);
- _signatureShaker = new _SignatureShaker(this.typeFlowAnalysis,
- treeShakeSignatures: treeShakeSignatures);
}
transformComponent(Component component) {
@@ -528,10 +528,6 @@
_pass2.transform(component);
}
- finalizeSignatures() {
- _signatureShaker.transform();
- }
-
bool isClassReferencedFromNativeCode(Class c) =>
typeFlowAnalysis.nativeCodeOracle.isClassReferencedFromNativeCode(c);
bool isClassUsed(Class c) => _usedClasses.contains(c);
@@ -795,7 +791,6 @@
final TreeShaker shaker;
final FieldMorpher fieldMorpher;
final TypeEnvironment environment;
- final List<Initializer> additionalInitializers = [];
Procedure _unsafeCast;
StaticTypeContext _staticTypeContext;
@@ -923,20 +918,6 @@
}
@override
- Constructor visitConstructor(Constructor node) {
- additionalInitializers.clear();
- node = defaultMember(node);
- if (additionalInitializers.isNotEmpty) {
- assert(node.initializers.last is SuperInitializer ||
- node.initializers.last is RedirectingInitializer);
- additionalInitializers.forEach((i) => i.parent = node);
- node.initializers
- .insertAll(node.initializers.length - 1, additionalInitializers);
- }
- return node;
- }
-
- @override
TreeNode defaultMember(Member node) {
currentMember = node;
if (shaker.isMemberBodyReachable(node)) {
@@ -1078,83 +1059,6 @@
}
}
- Expression _fixArgumentEvaluationOrder(
- Expression invocation, Arguments args) {
- if (args.named.isEmpty) return invocation;
-
- Expression outer = invocation;
- for (int i = args.named.length - 1; i >= 0; --i) {
- final arg = args.named[i];
- final variable = VariableDeclaration(null,
- initializer: arg.value,
- type: arg.value.getStaticType(staticTypeContext));
- arg.value = VariableGet(variable)..parent = arg;
- outer = Let(variable, outer);
- }
- for (int i = args.positional.length - 1; i >= 0; --i) {
- final variable = VariableDeclaration(null,
- initializer: args.positional[i],
- type: args.positional[i].getStaticType(staticTypeContext));
- args.positional[i] = VariableGet(variable)..parent = args;
- outer = Let(variable, outer);
- }
- return outer;
- }
-
- void _fixArgumentEvaluationOrderInInitializer(Arguments args) {
- if (args.named.isEmpty) return;
-
- for (int i = 0; i < args.positional.length; ++i) {
- final variable =
- VariableDeclaration(null, initializer: args.positional[i]);
- args.positional[i] = VariableGet(variable)..parent = args;
- additionalInitializers.add(LocalInitializer(variable));
- }
- for (int i = 0; i < args.named.length; ++i) {
- final variable =
- VariableDeclaration(null, initializer: args.named[i].value);
- args.named[i].value = VariableGet(variable)..parent = args.named[i];
- additionalInitializers.add(LocalInitializer(variable));
- }
- }
-
- void _rewriteArguments(Arguments args, Member member) {
- final alwaysPassedParams =
- shaker.typeFlowAnalysis.alwaysPassedOptionalParameters(member);
- final func = member.function;
- final positional = args.positional.toList();
- final newPositional = args.positional;
- newPositional.removeRange(
- func.requiredParameterCount, newPositional.length);
-
- for (int i = func.requiredParameterCount; i < positional.length; ++i) {
- if (alwaysPassedParams.contains(func.positionalParameters[i].name)) {
- newPositional.add(positional[i]);
- }
- }
-
- final newNamed = <NamedExpression>[];
- final namedPositionals = <NamedExpression>[];
- for (int i = 0; i < args.named.length; i++) {
- final arg = args.named[i];
- if (alwaysPassedParams.contains(arg.name)) {
- namedPositionals.add(arg);
- } else {
- newNamed.add(arg);
- }
- }
- args.named = newNamed;
- namedPositionals.sort((x, y) => x.name.compareTo(y.name));
- newPositional
- .addAll(namedPositionals.map((expr) => expr.value..parent = args));
-
- for (int i = func.requiredParameterCount; i < positional.length; ++i) {
- if (!alwaysPassedParams.contains(func.positionalParameters[i].name)) {
- newPositional.add(positional[i]);
- }
- }
- }
-
@override
TreeNode visitStaticInvocation(StaticInvocation node) {
node.transformChildren(this);
@@ -1166,10 +1070,7 @@
assert(shaker.isMemberBodyReachable(target),
"Member body is not reachable: $target");
- if (!shaker._signatureShaker.isShakingSignature(target)) return node;
- final result = _fixArgumentEvaluationOrder(node, node.arguments);
- _rewriteArguments(node.arguments, target);
- return result;
+ return node;
}
@override
@@ -1220,10 +1121,7 @@
assert(node.isConst);
shaker.addUsedMember(node.target);
}
- if (!shaker._signatureShaker.isShakingSignature(node.target)) return node;
- final result = _fixArgumentEvaluationOrder(node, node.arguments);
- _rewriteArguments(node.arguments, node.target);
- return result;
+ return node;
}
}
@@ -1235,9 +1133,6 @@
} else {
assert(shaker.isMemberBodyReachable(node.target),
"Target should be reachable: ${node.target}");
- if (!shaker._signatureShaker.isShakingSignature(node.target)) return node;
- _fixArgumentEvaluationOrderInInitializer(node.arguments);
- _rewriteArguments(node.arguments, node.target);
return node;
}
}
@@ -1249,9 +1144,6 @@
return _makeUnreachableInitializer(_flattenArguments(node.arguments));
} else {
// Can't assert that node.target is used due to partial mixin resolution.
- if (!shaker._signatureShaker.isShakingSignature(node.target)) return node;
- _fixArgumentEvaluationOrderInInitializer(node.arguments);
- _rewriteArguments(node.arguments, node.target);
return node;
}
}
@@ -1408,34 +1300,6 @@
node.enclosingClass.isEnum;
@override
- Member visitProcedure(Procedure proc) {
- proc = defaultMember(proc);
- if (proc == null || !shaker._signatureShaker.isShakingSignature(proc)) {
- return proc;
- }
- final optionals =
- shaker.typeFlowAnalysis.alwaysPassedOptionalParameters(proc);
- if (optionals.isNotEmpty) {
- shaker._signatureShaker.defer(proc);
- }
- return proc;
- }
-
- @override
- Member visitConstructor(Constructor ctor) {
- ctor = defaultMember(ctor);
- if (ctor == null || !shaker._signatureShaker.isShakingSignature(ctor)) {
- return ctor;
- }
- final optionals =
- shaker.typeFlowAnalysis.alwaysPassedOptionalParameters(ctor);
- if (optionals.isNotEmpty) {
- shaker._signatureShaker.defer(ctor);
- }
- return ctor;
- }
-
- @override
Member defaultMember(Member node) {
if (!shaker.isMemberUsed(node) && !_preserveSpecialMember(node)) {
// Ensure that kernel file writer will not be able to
@@ -1514,86 +1378,6 @@
}
}
-// Transform signatures of functions to convert optional named and
-// positional parameters to required parameters if we know that all call sites
-// will pass them.
-//
-// Because the AnnotateKernel pass expects signatures to match up with the
-// corresponding summaries, we enqueue the functions which need to be transformed
-// during the _TreeShakerPass1 and delay the actual transformation until after
-// AnnotateKernel has run.
-class _SignatureShaker {
- final TypeFlowAnalysis analysis;
- final List<Member> deferred = [];
- final bool treeShakeSignatures;
- _SignatureShaker(this.analysis, {this.treeShakeSignatures});
-
- bool isShakingSignature(Member member) {
- if (!treeShakeSignatures) return false;
- if (member is Procedure && member.isStatic || member is Constructor) {
- if (getExternalName(member) != null) {
- // This member has a native implementation which we cannot rewrite
- // to accomodate the new signature.
- return false;
- }
- } else {
- return false;
- }
- final alwaysPassedParams = analysis.alwaysPassedOptionalParameters(member);
- return alwaysPassedParams.isNotEmpty;
- }
-
- void defer(Member m) {
- assert(isShakingSignature(m));
- deferred.add(m);
- }
-
- void transform() => deferred.forEach(_update);
-
- void _update(Member member) {
- final alwaysPassedOptionals =
- analysis.alwaysPassedOptionalParameters(member);
- assert(alwaysPassedOptionals.isNotEmpty);
-
- final func = member.function;
- final newPositional =
- func.positionalParameters.sublist(0, func.requiredParameterCount);
- final optionalPositional =
- func.positionalParameters.sublist(func.requiredParameterCount);
-
- for (final param in optionalPositional) {
- if (alwaysPassedOptionals.contains(param.name)) {
- newPositional.add(param..initializer = null);
- }
- }
-
- final namedPositionals = <VariableDeclaration>[];
- final namedParameters = <VariableDeclaration>[];
- for (final param in func.namedParameters) {
- if (alwaysPassedOptionals.contains(param.name)) {
- // Make sure to clear the isRequired flag in case it was set.
- param.isRequired = false;
- namedPositionals.add(param..initializer = null);
- } else {
- namedParameters.add(param);
- }
- }
- namedPositionals.sort((x, y) => x.name.compareTo(y.name));
- newPositional.addAll(namedPositionals);
-
- func.requiredParameterCount = newPositional.length;
-
- for (final param in optionalPositional) {
- if (!alwaysPassedOptionals.contains(param.name)) {
- newPositional.add(param);
- }
- }
-
- func.positionalParameters = newPositional;
- func.namedParameters = namedParameters;
- }
-}
-
class _TreeShakerConstantVisitor extends ConstantVisitor<Null> {
final TreeShaker shaker;
final _TreeShakerTypeVisitor typeVisitor;
@@ -1671,26 +1455,3 @@
constant.type.accept(typeVisitor);
}
}
-
-bool mayHaveSideEffects(Expression node) {
- if (node is BasicLiteral ||
- node is ConstantExpression ||
- node is ThisExpression) {
- return false;
- }
- if (node is VariableGet && !node.variable.isLate) {
- return false;
- }
- if (node is StaticGet) {
- final target = node.target;
- if (target is Field && !target.isLate) {
- final initializer = target.initializer;
- if (initializer == null ||
- initializer is BasicLiteral ||
- initializer is ConstantExpression) {
- return false;
- }
- }
- }
- return true;
-}
diff --git a/pkg/vm/lib/transformations/type_flow/utils.dart b/pkg/vm/lib/transformations/type_flow/utils.dart
index ca2e212..2502904 100644
--- a/pkg/vm/lib/transformations/type_flow/utils.dart
+++ b/pkg/vm/lib/transformations/type_flow/utils.dart
@@ -329,3 +329,45 @@
bool isComparisonWithNull(MethodInvocation node) =>
getArgumentOfComparisonWithNull(node) != null;
+
+bool mayHaveSideEffects(Expression node) {
+ // Keep this function in sync with mayHaveOrSeeSideEffects:
+ // If new false cases are added here, add the corresponding visibility cases
+ // to mayHaveOrSeeSideEffects.
+ if (node is BasicLiteral ||
+ node is ConstantExpression ||
+ node is ThisExpression) {
+ return false;
+ }
+ if (node is VariableGet && !node.variable.isLate) {
+ return false;
+ }
+ if (node is StaticGet) {
+ final target = node.target;
+ if (target is Field && !target.isLate) {
+ final initializer = target.initializer;
+ if (initializer == null ||
+ initializer is BasicLiteral ||
+ initializer is ConstantExpression) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool mayHaveOrSeeSideEffects(Expression node) {
+ if (mayHaveSideEffects(node)) {
+ return true;
+ }
+ if (node is VariableGet && !node.variable.isFinal) {
+ return true;
+ }
+ if (node is StaticGet) {
+ final target = node.target;
+ if (target is Field && !target.isFinal) {
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
index 969556a..1e63109 100644
--- a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
+++ b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
@@ -56,6 +56,9 @@
@override
void recordMemberCalledViaThis(Member target) {}
+
+ @override
+ void recordTearOff(Procedure target) {}
}
class PrintSummaries extends RecursiveVisitor<Null> {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
index a67cf66..28378be 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
@@ -28,7 +28,7 @@
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] @#C8
method instanceMethod() → void {}
}
-[@vm.unboxing-info.metadata=(b)->i]static method foo([@vm.inferred-type.metadata=dart.core::Null? (value: null)] (core::List<core::int*>*) →* void a) → core::int* {
+[@vm.unboxing-info.metadata=()->i]static method foo() → core::int* {
@#C9 core::int* x = 2;
return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] x.{core::num::+}(2);
}
@@ -36,5 +36,5 @@
static method main(core::List<core::String*>* args) → dynamic {
self::A::staticMethod();
[@vm.direct-call.metadata=#lib::B.instanceMethod] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::instanceMethod}();
- self::foo(null);
+ self::foo();
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect
index 76d2329..8d122c1 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect
@@ -20,11 +20,11 @@
[@vm.unboxing-info.metadata=(i)->b]static method test0([@vm.inferred-type.metadata=dart.core::_Smi (value: 40)] core::int* arg) → void {
core::print(arg);
}
-static method test1([[@vm.inferred-type.metadata=dart.core::_Smi (value: 42)] core::int* arg = #C1]) → void {
- core::print(arg);
+static method test1() → void {
+ core::print(#C1);
}
-static method test2({[@vm.inferred-type.metadata=dart.core::_Smi (value: 43)] core::int* arg = #C2}) → void {
- core::print(arg);
+static method test2() → void {
+ core::print(#C2);
}
[@vm.unboxing-info.metadata=()->d]static get getD() → dynamic
return 100.0;
@@ -45,9 +45,9 @@
}
static method getList() → dynamic
return #C6;
-static method testList([@vm.inferred-type.metadata=dart.core::_ImmutableList (value: const <dart.core::int*>[1, 2, 3])] dynamic arg1, [[@vm.inferred-type.metadata=dart.core::_ImmutableList (value: const <dart.core::int*>[4, 5])] dynamic arg2 = #C9]) → void {
+static method testList([@vm.inferred-type.metadata=dart.core::_ImmutableList (value: const <dart.core::int*>[1, 2, 3])] dynamic arg1) → void {
core::print(arg1);
- core::print(arg2);
+ core::print(#C9);
}
static method main() → dynamic {
self::test0(40);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
index 4c6d0e1..79e29be 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
@@ -58,7 +58,7 @@
self::callerA1(new self::B::•());
self::callerA1(new self::C::•());
self::callerA2(new self::B::•());
- let self::C* #t1 = new self::C::•() in self::callerA3(#t1);
+ let final self::C* #t1 = new self::C::•() in self::callerA3(#t1);
self::callerA4([@vm.inferred-type.metadata=#lib::D?] self::dd);
self::dd = new self::D::•();
self::callerE1("abc");
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart b/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart
index 3fb1a95..f253547 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart
@@ -4,14 +4,31 @@
import 'dart:async';
+dynamic usedObject;
+
+void use(dynamic object) {
+ usedObject ??= object;
+}
+
class A {}
class B extends A {}
-void foo1_a1(x) {}
-void foo1_a2(x) {}
-void foo1_a3(x) {}
-void foo1_a4(x) {}
+void foo1_a1(x) {
+ use(x);
+}
+
+void foo1_a2(x) {
+ use(x);
+}
+
+void foo1_a3(x) {
+ use(x);
+}
+
+void foo1_a4(x) {
+ use(x);
+}
void foo1(Future<A> a1, A a2, FutureOr<A> a3, FutureOr<A> a4) {
foo1_a1(a1);
@@ -20,10 +37,21 @@
foo1_a4(a4);
}
-void foo2_a1(x) {}
-void foo2_a2(x) {}
-void foo2_a3(x) {}
-void foo2_a4(x) {}
+void foo2_a1(x) {
+ use(x);
+}
+
+void foo2_a2(x) {
+ use(x);
+}
+
+void foo2_a3(x) {
+ use(x);
+}
+
+void foo2_a4(x) {
+ use(x);
+}
void foo2(Future<A> a1, A a2, FutureOr<A> a3, FutureOr<A> a4) {
foo2_a1(a1);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect
index be9cfcc..32c6fb4 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect
@@ -15,21 +15,41 @@
: super self::A::•()
;
}
+static field dynamic usedObject;
[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
-static method foo1_a1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] dynamic x) → void {}
-static method foo1_a2([@vm.inferred-type.metadata=#lib::B] dynamic x) → void {}
-static method foo1_a3([@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] dynamic x) → void {}
-static method foo1_a4([@vm.inferred-type.metadata=#lib::B] dynamic x) → void {}
+static method use(dynamic object) → void {
+ [@vm.inferred-type.metadata=!? (receiver not int)] self::usedObject.{core::Object::==}(null) ?{dynamic} self::usedObject = object : null;
+}
+static method foo1_a1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] dynamic x) → void {
+ self::use(x);
+}
+static method foo1_a2([@vm.inferred-type.metadata=#lib::B] dynamic x) → void {
+ self::use(x);
+}
+static method foo1_a3([@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] dynamic x) → void {
+ self::use(x);
+}
+static method foo1_a4([@vm.inferred-type.metadata=#lib::B] dynamic x) → void {
+ self::use(x);
+}
static method foo1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] asy::Future<self::A*>* a1, [@vm.inferred-type.metadata=#lib::B] self::A* a2, [@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] FutureOr<self::A*>* a3, [@vm.inferred-type.metadata=#lib::B] FutureOr<self::A*>* a4) → void {
self::foo1_a1(a1);
self::foo1_a2(a2);
self::foo1_a3(a3);
self::foo1_a4(a4);
}
-static method foo2_a1([@vm.inferred-type.metadata=dart.async::_Future?] dynamic x) → void {}
-static method foo2_a2([@vm.inferred-type.metadata=#lib::B?] dynamic x) → void {}
-static method foo2_a3(dynamic x) → void {}
-static method foo2_a4(dynamic x) → void {}
+static method foo2_a1([@vm.inferred-type.metadata=dart.async::_Future?] dynamic x) → void {
+ self::use(x);
+}
+static method foo2_a2([@vm.inferred-type.metadata=#lib::B?] dynamic x) → void {
+ self::use(x);
+}
+static method foo2_a3(dynamic x) → void {
+ self::use(x);
+}
+static method foo2_a4(dynamic x) → void {
+ self::use(x);
+}
static method foo2([@vm.inferred-type.metadata=dart.async::_Future?] asy::Future<self::A*>* a1, [@vm.inferred-type.metadata=#lib::B?] self::A* a2, FutureOr<self::A*>* a3, FutureOr<self::A*>* a4) → void {
self::foo2_a1(a1);
self::foo2_a2(a2);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart.expect
index 089aa81..387080e 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart.expect
@@ -67,8 +67,8 @@
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method super_foobar2([@vm.inferred-type.metadata=dart.core::Null? (value: null)] (dynamic) →* void onData) → dynamic {
super.{self::StreamView::foobar}(onData);
}
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method super_foobar3({[@vm.inferred-type.metadata=dart.core::Null? (value: null)] (dynamic) →* void onData = #C1, [@vm.inferred-type.metadata=dart.core::Null? (value: null)] core::Function* onError = #C1}) → dynamic {
- super.{self::StreamView::foobar}(onData, onError: onError);
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method super_foobar3() → dynamic {
+ super.{self::StreamView::foobar}(#C1, onError: #C1);
}
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:13] get super_stream() → self::Stream*
return [@vm.inferred-type.metadata=!] super.{self::StreamView::_stream};
@@ -81,28 +81,28 @@
static method round0() → void {
new self::ByteStream::•(new self::ByteStream::•(new self::_GeneratedStreamImpl::•()));
}
-static method round1({[@vm.inferred-type.metadata=dart.core::Null? (value: null)] (dynamic) →* void onData = #C1}) → void {
+static method round1() → void {
self::ByteStream* x = new self::ByteStream::•(new self::ByteStream::•(new self::_GeneratedStreamImpl::•()));
- [@vm.direct-call.metadata=#lib::ByteStream.super_foobar1] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar1}(onData);
+ [@vm.direct-call.metadata=#lib::ByteStream.super_foobar1] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar1}(#C1);
}
-static method round2({[@vm.inferred-type.metadata=dart.core::Null? (value: null)] (dynamic) →* void onData = #C1, [@vm.inferred-type.metadata=dart.core::Null? (value: null)] core::Function* onError = #C1}) → void {
+static method round2() → void {
new self::_ControllerStream::•();
self::Stream* x = new self::_GeneratedStreamImpl::•();
x = new self::ByteStream::•(x);
- [@vm.direct-call.metadata=#lib::StreamView.foobar] [@vm.inferred-type.metadata=!? (skip check)] x.{self::Stream::foobar}(onData, onError: onError);
+ [@vm.direct-call.metadata=#lib::StreamView.foobar] [@vm.inferred-type.metadata=!? (skip check)] x.{self::Stream::foobar}(#C1, onError: #C1);
}
-static method round3({[@vm.inferred-type.metadata=dart.core::Null? (value: null)] (dynamic) →* void onData = #C1, [@vm.inferred-type.metadata=dart.core::Null? (value: null)] core::Function* onError = #C1}) → void {
+static method round3() → void {
self::Stream* x = new self::_GeneratedStreamImpl::•();
x = new self::ByteStream::•(x);
x = new self::_ControllerStream::•();
- [@vm.direct-call.metadata=#lib::_StreamImpl.foobar] [@vm.inferred-type.metadata=!? (skip check)] x.{self::Stream::foobar}(onData, onError: onError);
+ [@vm.direct-call.metadata=#lib::_StreamImpl.foobar] [@vm.inferred-type.metadata=!? (skip check)] x.{self::Stream::foobar}(#C1, onError: #C1);
}
-static method round4({[@vm.inferred-type.metadata=dart.core::Null? (value: null)] (dynamic) →* void onData = #C1}) → void {
+static method round4() → void {
self::ByteStream* x = new self::ByteStream::•(new self::_ControllerStream::•());
self::Stream* y = [@vm.direct-call.metadata=#lib::ByteStream.super_stream] [@vm.inferred-type.metadata=!] x.{self::ByteStream::super_stream};
self::Stream* z = [@vm.direct-call.metadata=#lib::StreamView._stream] [@vm.inferred-type.metadata=!] x.{self::StreamView::_stream};
if([@vm.direct-call.metadata=dart.core::Object.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] y.{self::Stream::==}(z)) {
- [@vm.direct-call.metadata=#lib::ByteStream.super_foobar2] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar2}(onData);
+ [@vm.direct-call.metadata=#lib::ByteStream.super_foobar2] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar2}(#C1);
}
}
static method round5() → void {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/lists.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/lists.dart.expect
index a639710..0fd6e10 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/lists.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/lists.dart.expect
@@ -13,15 +13,15 @@
[@vm.inferred-type.metadata=dart.core::_List<dart.core::int*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:7] final field core::List<core::int*>* filledFactory1 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int*>] core::_List::filled<core::int*>(2, 0);
[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:8] final field core::List<core::int*>* filledFactory2 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] core::_GrowableList::filled<core::int*>(2, 0);
[@vm.inferred-type.metadata=dart.core::_List<dart.core::int*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:9] final field core::List<core::int*>* filledFactory3 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int*>] core::_List::filled<core::int*>(2, 0);
-[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:10] final field core::List<core::int*>* filledFactory4 = let core::int* #t1 = 2 in let core::int* #t2 = 0 in let core::bool #t3 = _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::nonConstant()) in [@vm.inferred-type.metadata=!] core::List::filled<core::int*>(#t1, #t2, #t3);
+[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:10] final field core::List<core::int*>* filledFactory4 = let final core::bool #t1 = _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::nonConstant()) in [@vm.inferred-type.metadata=!] core::List::filled<core::int*>(2, 0, #t1);
[@vm.inferred-type.metadata=dart.core::_List<dart.core::int*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:11] final field core::List<core::int*>* filledFactory5 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int*>] core::_List::•<core::int*>(2);
[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:12] final field core::List<core::int*>* filledFactory6 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] core::_GrowableList::•<core::int*>(2);
[@vm.inferred-type.metadata=dart.core::_List<dart.core::int*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:13] final field core::List<core::int*>* filledFactory7 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int*>] core::_List::•<core::int*>(2);
-[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:14] final field core::List<core::int*>* filledFactory8 = let core::int* #t4 = 2 in let core::Null? #t5 = null in let core::bool #t6 = _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::nonConstant()) in [@vm.inferred-type.metadata=!] core::List::filled<core::int*>(#t4, #t5, #t6);
+[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:14] final field core::List<core::int*>* filledFactory8 = let final core::bool #t2 = _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::nonConstant()) in [@vm.inferred-type.metadata=!] core::List::filled<core::int*>(2, null, #t2);
[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:15] final field core::List<core::int*>* generateFactory1 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] core::_GrowableList::generate<core::int*>(2, (core::int* i) → core::int* => i);
[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:16] final field core::List<core::int*>* generateFactory2 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] core::_GrowableList::generate<core::int*>(2, (core::int* i) → core::int* => i);
[@vm.inferred-type.metadata=dart.core::_List<dart.core::int*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:17] final field core::List<core::int*>* generateFactory3 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int*>] core::_List::generate<core::int*>(2, (core::int* i) → core::int* => i);
-[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:18] final field core::List<core::int*>* generateFactory4 = let core::int* #t7 = 2 in let (core::int*) →* core::int* #t8 = (core::int* i) → core::int* => i in let core::bool #t9 = _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::nonConstant()) in [@vm.inferred-type.metadata=!] core::List::generate<core::int*>(#t7, #t8, #t9);
+[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:18] final field core::List<core::int*>* generateFactory4 = let final (core::int*) →* core::int* #t3 = (core::int* i) → core::int* => i in let final core::bool #t4 = _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::nonConstant()) in [@vm.inferred-type.metadata=!] core::List::generate<core::int*>(2, #t3, #t4);
[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::List<dart.core::int*>*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:19] final field core::List<core::List<core::int*>*>* generateFactory5 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::List<dart.core::int*>*>] core::_GrowableList::generate<core::List<core::int*>*>(2, (core::int* _) → core::List<core::int*>* => <core::int*>[]);
synthetic constructor •() → self::A*
: super core::Object::•()
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/lists_nnbd.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/lists_nnbd.dart.expect
index fa6d7c9..8a54bb1 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/lists_nnbd.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/lists_nnbd.dart.expect
@@ -11,15 +11,15 @@
[@vm.inferred-type.metadata=dart.core::_List<dart.core::int>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] final field core::List<core::int> filledFactory1 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int>] core::_List::filled<core::int>(2, 0);
[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:6] final field core::List<core::int> filledFactory2 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::filled<core::int>(2, 0);
[@vm.inferred-type.metadata=dart.core::_List<dart.core::int>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:7] final field core::List<core::int> filledFactory3 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int>] core::_List::filled<core::int>(2, 0);
-[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:8] final field core::List<core::int> filledFactory4 = let core::int #t1 = 2 in let core::int #t2 = 0 in let core::bool #t3 = _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::nonConstant()) in [@vm.inferred-type.metadata=!] core::List::filled<core::int>(#t1, #t2, #t3);
+[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:8] final field core::List<core::int> filledFactory4 = let final core::bool #t1 = _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::nonConstant()) in [@vm.inferred-type.metadata=!] core::List::filled<core::int>(2, 0, #t1);
[@vm.inferred-type.metadata=dart.core::_List<dart.core::int?>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:9] final field core::List<core::int?> filledFactory5 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int?>] core::_List::•<core::int?>(2);
[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int?>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:10] final field core::List<core::int?> filledFactory6 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int?>] core::_GrowableList::•<core::int?>(2);
[@vm.inferred-type.metadata=dart.core::_List<dart.core::int?>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:11] final field core::List<core::int?> filledFactory7 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int?>] core::_List::•<core::int?>(2);
-[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:12] final field core::List<core::int?> filledFactory8 = let core::int #t4 = 2 in let core::Null? #t5 = null in let core::bool #t6 = _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::nonConstant()) in [@vm.inferred-type.metadata=!] core::List::filled<core::int?>(#t4, #t5, #t6);
+[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:12] final field core::List<core::int?> filledFactory8 = let final core::bool #t2 = _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::nonConstant()) in [@vm.inferred-type.metadata=!] core::List::filled<core::int?>(2, null, #t2);
[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:13] final field core::List<core::int> generateFactory1 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::generate<core::int>(2, (core::int i) → core::int => i);
[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:14] final field core::List<core::int> generateFactory2 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::generate<core::int>(2, (core::int i) → core::int => i);
[@vm.inferred-type.metadata=dart.core::_List<dart.core::int>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:15] final field core::List<core::int> generateFactory3 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int>] core::_List::generate<core::int>(2, (core::int i) → core::int => i);
-[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:16] final field core::List<core::int> generateFactory4 = let core::int #t7 = 2 in let (core::int) → core::int #t8 = (core::int i) → core::int => i in let core::bool #t9 = _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::nonConstant()) in [@vm.inferred-type.metadata=!] core::List::generate<core::int>(#t7, #t8, #t9);
+[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:16] final field core::List<core::int> generateFactory4 = let final (core::int) → core::int #t3 = (core::int i) → core::int => i in let final core::bool #t4 = _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::nonConstant()) in [@vm.inferred-type.metadata=!] core::List::generate<core::int>(2, #t3, #t4);
[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::List<dart.core::int>>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:17] final field core::List<core::List<core::int>> generateFactory5 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::List<dart.core::int>>] core::_GrowableList::generate<core::List<core::int>>(2, (core::int _) → core::List<core::int> => <core::int>[]);
synthetic constructor •() → self::A
: super core::Object::•()
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart.expect
index 1eb445c..4aff357 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart.expect
@@ -9,15 +9,15 @@
import "package:expect/expect.dart";
abstract class TestNamedOrderBase extends core::Object {
-[@vm.unboxing-info.metadata=(i)->b] constructor •([@vm.inferred-type.metadata=int] dynamic w, [@vm.inferred-type.metadata=int] core::int* x, [@vm.inferred-type.metadata=int] core::int* y, [@vm.inferred-type.metadata=int] core::int* z) → self::TestNamedOrderBase*
+[@vm.unboxing-info.metadata=(i,i,i,i)->b] constructor •([@vm.inferred-type.metadata=int] dynamic w, [@vm.inferred-type.metadata=int] core::int* x, [@vm.inferred-type.metadata=int] core::int* y, [@vm.inferred-type.metadata=int] core::int* z) → self::TestNamedOrderBase*
: super core::Object::•() {
- let core::int* #t1 = _in::unsafeCast<core::int*>(w) in let core::int* #t2 = z in let core::int* #t3 = y in let core::int* #t4 = x in self::testNamedOrder(#t1, #t4, #t3, #t2);
+ self::testNamedOrder(_in::unsafeCast<core::int*>(w), x, y, z);
}
}
class TestNamedOrderSub extends self::TestNamedOrderBase {
[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i)->i] field core::int* x;
constructor •() → self::TestNamedOrderSub*
- : self::TestNamedOrderSub::x = [@vm.inferred-type.metadata=int] self::dec(), dynamic #t5 = [@vm.inferred-type.metadata=int] self::inc(), dynamic #t6 = [@vm.inferred-type.metadata=int] self::inc(), dynamic #t7 = [@vm.inferred-type.metadata=int] self::inc(), dynamic #t8 = [@vm.inferred-type.metadata=int] self::dec(), super self::TestNamedOrderBase::•(#t5, #t8, #t7, #t6) {
+ : self::TestNamedOrderSub::x = [@vm.inferred-type.metadata=int] self::dec(), final core::int* #t1 = [@vm.inferred-type.metadata=int] self::inc(), final core::int* #t2 = [@vm.inferred-type.metadata=int] self::inc(), final core::int* #t3 = [@vm.inferred-type.metadata=int] self::inc(), final core::int* #t4 = [@vm.inferred-type.metadata=int] self::dec(), super self::TestNamedOrderBase::•(#t1, #t4, #t3, #t2) {
exp::Expect::equals([@vm.direct-call.metadata=#lib::TestNamedOrderSub.x] [@vm.inferred-type.metadata=int] this.{self::TestNamedOrderSub::x}, 0);
}
}
@@ -26,14 +26,14 @@
return self::global = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=int?] self::global.{core::num::+}(1);
[@vm.unboxing-info.metadata=()->i]static method dec() → core::int*
return self::global = [@vm.inferred-type.metadata=int] math::max<core::int*>(0, self::global = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.-??] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=int?] self::global.{core::num::-}(1));
-[@vm.unboxing-info.metadata=(i)->b]static method testNamedOrder([@vm.inferred-type.metadata=int] core::int* w, [@vm.inferred-type.metadata=int] core::int* x, [@vm.inferred-type.metadata=int] core::int* y, [@vm.inferred-type.metadata=int] core::int* z) → void {
+[@vm.unboxing-info.metadata=(i,i,i,i)->b]static method testNamedOrder([@vm.inferred-type.metadata=int] core::int* w, [@vm.inferred-type.metadata=int] core::int* x, [@vm.inferred-type.metadata=int] core::int* y, [@vm.inferred-type.metadata=int] core::int* z) → void {
exp::Expect::equals(w, 1);
exp::Expect::equals(z, 2);
exp::Expect::equals(y, 3);
exp::Expect::equals(x, 2);
}
static method main() → dynamic {
- let core::int* #t9 = [@vm.inferred-type.metadata=int] self::inc() in let core::int* #t10 = [@vm.inferred-type.metadata=int] self::inc() in let core::int* #t11 = [@vm.inferred-type.metadata=int] self::inc() in let core::int* #t12 = [@vm.inferred-type.metadata=int] self::dec() in self::testNamedOrder(#t9, #t12, #t11, #t10);
+ let final core::int* #t5 = [@vm.inferred-type.metadata=int] self::inc() in let final core::int* #t6 = [@vm.inferred-type.metadata=int] self::inc() in let final core::int* #t7 = [@vm.inferred-type.metadata=int] self::inc() in let final core::int* #t8 = [@vm.inferred-type.metadata=int] self::dec() in self::testNamedOrder(#t5, #t8, #t7, #t6);
self::global = 1;
new self::TestNamedOrderSub::•();
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
index c1f1292e..5b69347 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
@@ -39,7 +39,7 @@
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] abstract method foo() → dynamic;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] abstract get bar() → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] [@vm.unboxing-info.metadata=(i,i,i)->b] abstract method bazz(dynamic a1, dynamic a2, dynamic a3, [dynamic a4 = #C1, dynamic a5 = #C1]) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] [@vm.unboxing-info.metadata=(i,i,i,i)->b] abstract method bazz(dynamic a1, dynamic a2, dynamic a3, dynamic a4) → dynamic;
}
class B extends self::A {
synthetic constructor •() → self::B*
@@ -49,11 +49,11 @@
return new self::T1::•();
}
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] no-such-method-forwarder get bar() → dynamic
- return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))));
+ return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))));
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] no-such-method-forwarder method foo() → dynamic
- return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C3, #C4, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))));
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] [@vm.unboxing-info.metadata=(i,i,i)->b] no-such-method-forwarder method bazz([@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] dynamic a1, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic a2, [@vm.inferred-type.metadata=dart.core::_Smi (value: 3)] dynamic a3, [[@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::Null? (value: null)] dynamic a5 = #C1]) → dynamic
- return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[a1, a2, a3, a4, a5]), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))));
+ return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))));
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] [@vm.unboxing-info.metadata=(i,i,i,i)->b] no-such-method-forwarder method bazz([@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] dynamic a1, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic a2, [@vm.inferred-type.metadata=dart.core::_Smi (value: 3)] dynamic a3, [@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] dynamic a4) → dynamic
+ return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[a1, a2, a3, a4, #C7]), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))));
}
abstract class C extends core::Object {
synthetic constructor •() → self::C*
@@ -68,11 +68,11 @@
: super self::C::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] no-such-method-forwarder get bar() → dynamic
- return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))));
+ return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))));
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] no-such-method-forwarder method foo() → dynamic
- return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C3, #C4, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))));
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] [@vm.unboxing-info.metadata=(i,i,i)->b] no-such-method-forwarder method bazz([@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] dynamic a1, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic a2, [@vm.inferred-type.metadata=dart.core::_Smi (value: 3)] dynamic a3, [[@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::Null? (value: null)] dynamic a5 = #C1]) → dynamic
- return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[a1, a2, a3, a4, a5]), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))));
+ return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))));
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] [@vm.unboxing-info.metadata=(i,i,i,i)->b] no-such-method-forwarder method bazz([@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] dynamic a1, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic a2, [@vm.inferred-type.metadata=dart.core::_Smi (value: 3)] dynamic a3, [@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] dynamic a4) → dynamic
+ return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[a1, a2, a3, a4, #C7]), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))));
}
class E extends core::Object implements self::A {
synthetic constructor •() → self::E*
@@ -82,7 +82,7 @@
return new self::T4::•();
}
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] no-such-method-forwarder get bar() → dynamic
- return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::E.noSuchMethod] [@vm.inferred-type.metadata=#lib::T4 (skip check)] this.{self::E::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))));
+ return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::E.noSuchMethod] [@vm.inferred-type.metadata=#lib::T4 (skip check)] this.{self::E::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))));
}
class F extends core::Object {
synthetic constructor •() → self::F*
@@ -104,7 +104,7 @@
synthetic constructor •() → self::H*
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8,getterSelectorId:9] method foo({[@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] dynamic left = #C1, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic right = #C1}) → dynamic
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8,getterSelectorId:9] method foo({[@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] dynamic left = #C7, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic right = #C7}) → dynamic
return new self::T6::•();
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] method noSuchMethod(core::Invocation* invocation) → dynamic {
return new self::T7::•();
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/null_check_elimination_nnbd.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/null_check_elimination_nnbd.dart.expect
index 9d38510..d80f88a 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/null_check_elimination_nnbd.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/null_check_elimination_nnbd.dart.expect
@@ -11,7 +11,7 @@
: self::A::nonNullable = nonNullable, self::A::nullable = nullable, self::A::alwaysNull = alwaysNull, super core::Object::•()
;
}
-[@vm.inferred-type.metadata=#lib::A?]static field self::A staticField = let core::String #t1 = "hi" in let core::String #t2 = "bye" in new self::A::•(#t1, #t2);
+[@vm.inferred-type.metadata=#lib::A?]static field self::A staticField = new self::A::•("hi", "bye");
static method testNonNullable([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic
return _in::unsafeCast<core::String>([@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable});
static method testNullable([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic
@@ -19,7 +19,7 @@
static method testAlwaysNull([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic
return [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}!;
static method main() → void {
- final core::List<self::A> list = <self::A>[let core::String #t3 = "foo" in let core::Null? #t4 = null in let core::Null? #t5 = null in new self::A::•(#t3, #t4, alwaysNull: #t5), self::staticField];
+ final core::List<self::A> list = <self::A>[new self::A::•("foo", null, alwaysNull: null), self::staticField];
{
core::Iterator<self::A> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A>] list.{core::Iterable::iterator};
for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(); ) {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect
index 1e8033d2..615c0d7 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect
@@ -11,9 +11,9 @@
: self::A::nonNullable = nonNullable, self::A::nullable = nullable, self::A::alwaysNull = alwaysNull, super core::Object::•()
;
}
-[@vm.inferred-type.metadata=#lib::A?]static field self::A* staticField = let core::String* #t1 = "hi" in let core::String* #t2 = "bye" in new self::A::•(#t1, #t2);
+[@vm.inferred-type.metadata=#lib::A?]static field self::A* staticField = new self::A::•("hi", "bye");
static method testNonNullableIf1([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
- if(let dynamic #t3 = [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable} in false) {
+ if(let dynamic #t1 = [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable} in false) {
core::print("null");
}
}
@@ -23,12 +23,12 @@
}
}
static method testAlwaysNullIf1([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
- if(let dynamic #t4 = [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull} in true) {
+ if(let dynamic #t2 = [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull} in true) {
core::print("null");
}
}
static method testNonNullableIf2([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
- if(!(let dynamic #t5 = [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable} in false) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
+ if(!(let dynamic #t3 = [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable} in false) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
core::print("not null");
}
}
@@ -38,20 +38,20 @@
}
}
static method testAlwaysNullIf2([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
- if(!(let dynamic #t6 = [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull} in true) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
+ if(!(let dynamic #t4 = [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull} in true) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
core::print("not null");
}
}
static method testNonNullableCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic
- return !(let dynamic #t7 = [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable} in false) ?{core::String*} "not null" : "null";
+ return !(let dynamic #t5 = [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable} in false) ?{core::String*} "not null" : "null";
static method testNullableCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic
return ![@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}.{core::String::==}(null) ?{core::String*} "not null" : "null";
static method testAlwaysNullCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic
- return !(let dynamic #t8 = [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull} in true) ?{core::String*} "not null" : "null";
+ return !(let dynamic #t6 = [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull} in true) ?{core::String*} "not null" : "null";
static method someCondition() → dynamic
return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.inferred-type.metadata=int] core::int::parse("1").{core::num::==}(1);
static method main() → void {
- final core::List<self::A*>* list = <self::A*>[let core::String* #t9 = "foo" in let core::Null? #t10 = null in let core::Null? #t11 = null in new self::A::•(#t9, #t10, alwaysNull: #t11), self::staticField];
+ final core::List<self::A*>* list = <self::A*>[new self::A::•("foo", null, alwaysNull: null), self::staticField];
{
core::Iterator<self::A*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A*>] list.{core::Iterable::iterator};
for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(); ) {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart.expect
index 2e584fa..ad7ce96 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart.expect
@@ -35,14 +35,14 @@
import "package:protobuf/protobuf.dart" as $pb;
class FooKeep extends pro::GeneratedMessage {
-[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t1 = new pro::BuilderInfo::•("FooKeep", createEmptyInstance: #C1) in block {
- [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::BarKeep*>(1, "barKeep", protoName: "barKeep", subBuilder: #C2);
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t1 = new pro::BuilderInfo::•("FooKeep") in block {
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::BarKeep*>(1, "barKeep", #C1);
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
- [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String*, self::BarKeep*>(3, "mapKeep", protoName: "mapKeep", entryClassName: "FooKeep.MapKeepEntry", keyFieldType: #C3, valueFieldType: #C4, valueCreator: #C2);
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String*, self::BarKeep*>(3, "mapKeep", "FooKeep.MapKeepEntry", #C2, "mapKeep", #C1, #C3);
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
- [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int*>(5, "aKeep", #C5, protoName: "aKeep");
- [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::HasKeep*>(6, "hasKeep", protoName: "hasKeep", subBuilder: #C6);
- [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::ClearKeep*>(7, "clearKeep", protoName: "clearKeep", subBuilder: #C7);
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int*>(5, "aKeep", #C4);
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::HasKeep*>(6, "hasKeep", #C5);
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::ClearKeep*>(7, "clearKeep", #C6);
[@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::hasRequiredFields} = false;
} =>#t1;
constructor _() → self::FooKeep*
@@ -52,36 +52,36 @@
return [@vm.inferred-type.metadata=foo.pb.dart::FooKeep] self::FooKeep::create();
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] get info_() → pro::BuilderInfo*
return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::FooKeep::_i;
- @#C10
+ @#C9
static method create() → self::FooKeep*
return new self::FooKeep::_();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3] @#C12
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3] @#C11
get barKeep() → self::BarKeep*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getN] [@vm.inferred-type.metadata=foo.pb.dart::BarKeep? (skip check)] this.{pro::GeneratedMessage::$_getN}<self::BarKeep*>(0);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3] @#C12
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3] @#C11
set barKeep([@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.setField] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::setField}(1, v);
}
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] @#C14
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] @#C13
get mapKeep() → core::Map<core::String*, self::BarKeep*>*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getMap] [@vm.inferred-type.metadata=! (skip check)] this.{pro::GeneratedMessage::$_getMap}<core::String*, self::BarKeep*>(2);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=()->i] @#C16
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=()->i] @#C15
get aKeep() → core::int*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(4);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(i)->b] @#C16
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(i)->b] @#C15
set aKeep([@vm.inferred-type.metadata=dart.core::_Smi (value: 43)] core::int* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(4, v);
}
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] @#C18
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] @#C17
method hasHasKeep() → core::bool*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_has] [@vm.inferred-type.metadata=dart.core::bool (skip check)] this.{pro::GeneratedMessage::$_has}(5);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] @#C20
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] @#C19
method clearClearKeep() → void
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.clearField] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] this.{pro::GeneratedMessage::clearField}(7);
}
class BarKeep extends pro::GeneratedMessage {
-[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t2 = new pro::BuilderInfo::•("BarKeep", createEmptyInstance: #C2) in block {
- [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::a}<core::int*>(1, "aKeep", #C5, protoName: "aKeep");
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t2 = new pro::BuilderInfo::•("BarKeep") in block {
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::a}<core::int*>(1, "aKeep", #C4);
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
[@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::hasRequiredFields} = false;
} =>#t2;
@@ -92,19 +92,19 @@
return [@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep::create();
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] get info_() → pro::BuilderInfo*
return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::BarKeep::_i;
- @#C10
+ @#C9
static method create() → self::BarKeep*
return new self::BarKeep::_();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] [@vm.unboxing-info.metadata=()->i] @#C12
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] [@vm.unboxing-info.metadata=()->i] @#C11
get aKeep() → core::int*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(0);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] [@vm.unboxing-info.metadata=(i)->b] @#C12
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] [@vm.unboxing-info.metadata=(i)->b] @#C11
set aKeep([@vm.inferred-type.metadata=dart.core::_Smi] core::int* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(0, v);
}
}
class HasKeep extends pro::GeneratedMessage {
-[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t3 = new pro::BuilderInfo::•("HasKeep", createEmptyInstance: #C6) in block {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t3 = new pro::BuilderInfo::•("HasKeep") in block {
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
[@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pro::BuilderInfo::hasRequiredFields} = false;
} =>#t3;
@@ -113,12 +113,12 @@
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] get info_() → pro::BuilderInfo*
return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::HasKeep::_i;
- @#C10
+ @#C9
static method create() → self::HasKeep*
return new self::HasKeep::_();
}
class ClearKeep extends pro::GeneratedMessage {
-[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t4 = new pro::BuilderInfo::•("ClearKeep", createEmptyInstance: #C7) in block {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t4 = new pro::BuilderInfo::•("ClearKeep") in block {
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
[@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::BuilderInfo::hasRequiredFields} = false;
} =>#t4;
@@ -127,7 +127,7 @@
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] get info_() → pro::BuilderInfo*
return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::ClearKeep::_i;
- @#C10
+ @#C9
static method create() → self::ClearKeep*
return new self::ClearKeep::_();
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart.expect
index 7ce67f5..a65b51a 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart.expect
@@ -28,14 +28,14 @@
import "package:protobuf/protobuf.dart" as $pb;
class FooKeep extends pro::GeneratedMessage {
-[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t1 = new pro::BuilderInfo::•("FooKeep", createEmptyInstance: #C1) in block {
- [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::BarKeep*>(1, "barKeep", protoName: "barKeep", subBuilder: #C2);
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t1 = new pro::BuilderInfo::•("FooKeep") in block {
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::BarKeep*>(1, "barKeep", #C1);
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
- [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String*, self::BarKeep*>(3, "mapKeep", protoName: "mapKeep", entryClassName: "FooKeep.MapKeepEntry", keyFieldType: #C3, valueFieldType: #C4, valueCreator: #C2);
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String*, self::BarKeep*>(3, "mapKeep", "FooKeep.MapKeepEntry", #C2, "mapKeep", #C1, #C3);
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
- [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int*>(5, "aKeep", #C5, protoName: "aKeep");
- [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::HasKeep*>(6, "hasKeep", protoName: "hasKeep", subBuilder: #C6);
- [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::ClearKeep*>(7, "clearKeep", protoName: "clearKeep", subBuilder: #C7);
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int*>(5, "aKeep", #C4);
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::HasKeep*>(6, "hasKeep", #C5);
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::ClearKeep*>(7, "clearKeep", #C6);
[@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::hasRequiredFields} = false;
} =>#t1;
constructor _() → self::FooKeep*
@@ -43,9 +43,9 @@
;
static factory •() → self::FooKeep*
return [@vm.inferred-type.metadata=foo.pb.dart::FooKeep] self::FooKeep::create();
- static factory fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList?<dart.core::int*>] core::List<core::int*>* i, [[@vm.inferred-type.metadata=protobuf::_EmptyExtensionRegistry (value: const protobuf::_EmptyExtensionRegistry{})] pro::ExtensionRegistry* r = #C8]) → self::FooKeep*
+ static factory fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList?<dart.core::int*>] core::List<core::int*>* i) → self::FooKeep*
return let final self::FooKeep* #t2 = [@vm.inferred-type.metadata=foo.pb.dart::FooKeep] self::FooKeep::create() in block {
- [@vm.direct-call.metadata=protobuf::GeneratedMessage.mergeFromBuffer] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::GeneratedMessage::mergeFromBuffer}(i, r);
+ [@vm.direct-call.metadata=protobuf::GeneratedMessage.mergeFromBuffer] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::GeneratedMessage::mergeFromBuffer}(i, #C7);
} =>#t2;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method clone() → self::FooKeep*
return let final self::FooKeep* #t3 = [@vm.inferred-type.metadata=foo.pb.dart::FooKeep] self::FooKeep::•() in block {
@@ -53,28 +53,28 @@
} =>#t3;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] get info_() → pro::BuilderInfo*
return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::FooKeep::_i;
- @#C11
+ @#C10
static method create() → self::FooKeep*
return new self::FooKeep::_();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] @#C13
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] @#C12
get barKeep() → self::BarKeep*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getN] [@vm.inferred-type.metadata=foo.pb.dart::BarKeep? (skip check)] this.{pro::GeneratedMessage::$_getN}<self::BarKeep*>(0);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] @#C15
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] @#C14
get mapKeep() → core::Map<core::String*, self::BarKeep*>*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getMap] [@vm.inferred-type.metadata=! (skip check)] this.{pro::GeneratedMessage::$_getMap}<core::String*, self::BarKeep*>(2);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:6] [@vm.unboxing-info.metadata=()->i] @#C17
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:6] [@vm.unboxing-info.metadata=()->i] @#C16
get aKeep() → core::int*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(4);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] @#C19
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] @#C18
method hasHasKeep() → core::bool*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_has] [@vm.inferred-type.metadata=dart.core::bool (skip check)] this.{pro::GeneratedMessage::$_has}(5);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] @#C21
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] @#C20
method clearClearKeep() → void
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.clearField] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] this.{pro::GeneratedMessage::clearField}(7);
}
class BarKeep extends pro::GeneratedMessage {
-[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t4 = new pro::BuilderInfo::•("BarKeep", createEmptyInstance: #C2) in block {
- [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::BuilderInfo::a}<core::int*>(1, "aKeep", #C5, protoName: "aKeep");
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t4 = new pro::BuilderInfo::•("BarKeep") in block {
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::BuilderInfo::a}<core::int*>(1, "aKeep", #C4);
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
[@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::BuilderInfo::hasRequiredFields} = false;
} =>#t4;
@@ -89,15 +89,15 @@
} =>#t5;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] get info_() → pro::BuilderInfo*
return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::BarKeep::_i;
- @#C11
+ @#C10
static method create() → self::BarKeep*
return new self::BarKeep::_();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:11] [@vm.unboxing-info.metadata=()->i] @#C13
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:11] [@vm.unboxing-info.metadata=()->i] @#C12
get aKeep() → core::int*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(0);
}
class HasKeep extends pro::GeneratedMessage {
-[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t6 = new pro::BuilderInfo::•("HasKeep", createEmptyInstance: #C6) in block {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t6 = new pro::BuilderInfo::•("HasKeep") in block {
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t6.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
[@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t6.{pro::BuilderInfo::hasRequiredFields} = false;
} =>#t6;
@@ -112,12 +112,12 @@
} =>#t7;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] get info_() → pro::BuilderInfo*
return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::HasKeep::_i;
- @#C11
+ @#C10
static method create() → self::HasKeep*
return new self::HasKeep::_();
}
class ClearKeep extends pro::GeneratedMessage {
-[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t8 = new pro::BuilderInfo::•("ClearKeep", createEmptyInstance: #C7) in block {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t8 = new pro::BuilderInfo::•("ClearKeep") in block {
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t8.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
[@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t8.{pro::BuilderInfo::hasRequiredFields} = false;
} =>#t8;
@@ -132,7 +132,7 @@
} =>#t9;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] get info_() → pro::BuilderInfo*
return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::ClearKeep::_i;
- @#C11
+ @#C10
static method create() → self::ClearKeep*
return new self::ClearKeep::_();
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart.expect
index ebf9b06..22768c2 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart.expect
@@ -42,14 +42,14 @@
import "package:protobuf/protobuf.dart" as $pb;
class FooKeep extends pro::GeneratedMessage {
-[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t1 = new pro::BuilderInfo::•("FooKeep", createEmptyInstance: #C1) in block {
- [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::BarKeep*>(1, "barKeep", protoName: "barKeep", subBuilder: #C2);
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t1 = new pro::BuilderInfo::•("FooKeep") in block {
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::BarKeep*>(1, "barKeep", #C1);
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
- [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String*, self::BarKeep*>(3, "mapKeep", protoName: "mapKeep", entryClassName: "FooKeep.MapKeepEntry", keyFieldType: #C3, valueFieldType: #C4, valueCreator: #C2);
- [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String*, self::ZopDrop*>(4, "mapDrop", protoName: "mapDrop", entryClassName: "FooKeep.MapDropEntry", keyFieldType: #C3, valueFieldType: #C4, valueCreator: #C5);
- [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int*>(5, "aKeep", #C6, protoName: "aKeep");
- [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::HasKeep*>(6, "hasKeep", protoName: "hasKeep", subBuilder: #C7);
- [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::ClearKeep*>(7, "clearKeep", protoName: "clearKeep", subBuilder: #C8);
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String*, self::BarKeep*>(3, "mapKeep", "FooKeep.MapKeepEntry", #C2, "mapKeep", #C1, #C3);
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String*, self::ZopDrop*>(4, "mapDrop", "FooKeep.MapDropEntry", #C2, "mapDrop", #C4, #C3);
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int*>(5, "aKeep", #C5);
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::HasKeep*>(6, "hasKeep", #C6);
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::ClearKeep*>(7, "clearKeep", #C7);
[@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::hasRequiredFields} = false;
} =>#t1;
constructor _() → self::FooKeep*
@@ -59,36 +59,36 @@
return [@vm.inferred-type.metadata=foo.pb.dart::FooKeep] self::FooKeep::create();
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] get info_() → pro::BuilderInfo*
return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::FooKeep::_i;
- @#C11
+ @#C10
static method create() → self::FooKeep*
return new self::FooKeep::_();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2] @#C13
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2] @#C12
set barKeep([@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.setField] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::setField}(1, v);
}
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] @#C15
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] @#C14
get mapKeep() → core::Map<core::String*, self::BarKeep*>*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getMap] [@vm.inferred-type.metadata=! (skip check)] this.{pro::GeneratedMessage::$_getMap}<core::String*, self::BarKeep*>(2);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] @#C17
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] @#C16
get mapDrop() → core::Map<core::String*, self::ZopDrop*>*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getMap] [@vm.inferred-type.metadata=! (skip check)] this.{pro::GeneratedMessage::$_getMap}<core::String*, self::ZopDrop*>(3);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5] [@vm.unboxing-info.metadata=(i)->b] @#C19
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5] [@vm.unboxing-info.metadata=(i)->b] @#C18
set aKeep([@vm.inferred-type.metadata=dart.core::_Smi (value: 43)] core::int* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(4, v);
}
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6] @#C21
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6] @#C20
set hasKeep([@vm.inferred-type.metadata=foo.pb.dart::HasKeep] self::HasKeep* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.setField] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::setField}(6, v);
}
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7] @#C23
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7] @#C22
set clearKeep([@vm.inferred-type.metadata=foo.pb.dart::ClearKeep] self::ClearKeep* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.setField] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::setField}(7, v);
}
}
class BarKeep extends pro::GeneratedMessage {
-[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t2 = new pro::BuilderInfo::•("BarKeep", createEmptyInstance: #C2) in block {
- [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::a}<core::int*>(1, "aKeep", #C6, protoName: "aKeep");
- [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::a}<core::int*>(2, "bDrop", #C6, protoName: "bDrop");
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t2 = new pro::BuilderInfo::•("BarKeep") in block {
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::a}<core::int*>(1, "aKeep", #C5);
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::a}<core::int*>(2, "bDrop", #C5);
[@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::hasRequiredFields} = false;
} =>#t2;
constructor _() → self::BarKeep*
@@ -98,20 +98,20 @@
return [@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep::create();
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] get info_() → pro::BuilderInfo*
return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::BarKeep::_i;
- @#C11
+ @#C10
static method create() → self::BarKeep*
return new self::BarKeep::_();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8] [@vm.unboxing-info.metadata=(i)->b] @#C13
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8] [@vm.unboxing-info.metadata=(i)->b] @#C12
set aKeep([@vm.inferred-type.metadata=dart.core::_Smi] core::int* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(0, v);
}
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9] [@vm.unboxing-info.metadata=(i)->b] @#C25
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9] [@vm.unboxing-info.metadata=(i)->b] @#C24
set bDrop([@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] core::int* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(1, v);
}
}
class HasKeep extends pro::GeneratedMessage {
-[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t3 = new pro::BuilderInfo::•("HasKeep", createEmptyInstance: #C7) in block {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t3 = new pro::BuilderInfo::•("HasKeep") in block {
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
[@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pro::BuilderInfo::hasRequiredFields} = false;
} =>#t3;
@@ -122,12 +122,12 @@
return [@vm.inferred-type.metadata=foo.pb.dart::HasKeep] self::HasKeep::create();
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] get info_() → pro::BuilderInfo*
return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::HasKeep::_i;
- @#C11
+ @#C10
static method create() → self::HasKeep*
return new self::HasKeep::_();
}
class ClearKeep extends pro::GeneratedMessage {
-[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t4 = new pro::BuilderInfo::•("ClearKeep", createEmptyInstance: #C8) in block {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t4 = new pro::BuilderInfo::•("ClearKeep") in block {
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
[@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::BuilderInfo::hasRequiredFields} = false;
} =>#t4;
@@ -138,13 +138,13 @@
return [@vm.inferred-type.metadata=foo.pb.dart::ClearKeep] self::ClearKeep::create();
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] get info_() → pro::BuilderInfo*
return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::ClearKeep::_i;
- @#C11
+ @#C10
static method create() → self::ClearKeep*
return new self::ClearKeep::_();
}
class ZopDrop extends pro::GeneratedMessage {
-[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t5 = new pro::BuilderInfo::•("ZopDrop", createEmptyInstance: #C5) in block {
- [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t5.{pro::BuilderInfo::a}<core::int*>(1, "aDrop", #C6, protoName: "aDrop");
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t5 = new pro::BuilderInfo::•("ZopDrop") in block {
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t5.{pro::BuilderInfo::a}<core::int*>(1, "aDrop", #C5);
[@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t5.{pro::BuilderInfo::hasRequiredFields} = false;
} =>#t5;
constructor _() → self::ZopDrop*
@@ -154,10 +154,10 @@
return [@vm.inferred-type.metadata=foo.pb.dart::ZopDrop] self::ZopDrop::create();
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] get info_() → pro::BuilderInfo*
return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::ZopDrop::_i;
- @#C11
+ @#C10
static method create() → self::ZopDrop*
return new self::ZopDrop::_();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:10] [@vm.unboxing-info.metadata=(i)->b] @#C13
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:10] [@vm.unboxing-info.metadata=(i)->b] @#C12
set aDrop([@vm.inferred-type.metadata=dart.core::_Smi (value: 3)] core::int* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(0, v);
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart.expect
index b0155db..15020be 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart.expect
@@ -39,14 +39,14 @@
import "package:protobuf/protobuf.dart" as $pb;
class FooKeep extends pro::GeneratedMessage {
-[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t1 = new pro::BuilderInfo::•("FooKeep", createEmptyInstance: #C1) in block {
- [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::BarKeep*>(1, "barKeep", protoName: "barKeep", subBuilder: #C2);
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t1 = new pro::BuilderInfo::•("FooKeep") in block {
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::BarKeep*>(1, "barKeep", #C1);
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
- [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String*, self::BarKeep*>(3, "mapKeep", protoName: "mapKeep", entryClassName: "FooKeep.MapKeepEntry", keyFieldType: #C3, valueFieldType: #C4, valueCreator: #C2);
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String*, self::BarKeep*>(3, "mapKeep", "FooKeep.MapKeepEntry", #C2, "mapKeep", #C1, #C3);
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
- [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int*>(5, "aKeep", #C5, protoName: "aKeep");
- [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::HasKeep*>(6, "hasKeep", protoName: "hasKeep", subBuilder: #C6);
- [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::ClearKeep*>(7, "clearKeep", protoName: "clearKeep", subBuilder: #C7);
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int*>(5, "aKeep", #C4);
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::HasKeep*>(6, "hasKeep", #C5);
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::ClearKeep*>(7, "clearKeep", #C6);
[@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::hasRequiredFields} = false;
} =>#t1;
constructor _() → self::FooKeep*
@@ -56,36 +56,36 @@
return [@vm.inferred-type.metadata=foo.pb.dart::FooKeep] self::FooKeep::create();
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] get info_() → pro::BuilderInfo*
return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::FooKeep::_i;
- @#C10
+ @#C9
static method create() → self::FooKeep*
return new self::FooKeep::_();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3] @#C12
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3] @#C11
get barKeep() → self::BarKeep*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getN] [@vm.inferred-type.metadata=foo.pb.dart::BarKeep? (skip check)] this.{pro::GeneratedMessage::$_getN}<self::BarKeep*>(0);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3] @#C12
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3] @#C11
set barKeep([@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.setField] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::setField}(1, v);
}
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] @#C14
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] @#C13
get mapKeep() → core::Map<core::String*, self::BarKeep*>*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getMap] [@vm.inferred-type.metadata=! (skip check)] this.{pro::GeneratedMessage::$_getMap}<core::String*, self::BarKeep*>(2);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=()->i] @#C16
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=()->i] @#C15
get aKeep() → core::int*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(4);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(i)->b] @#C16
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(i)->b] @#C15
set aKeep([@vm.inferred-type.metadata=dart.core::_Smi (value: 43)] core::int* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(4, v);
}
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] @#C18
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] @#C17
method hasHasKeep() → core::bool*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_has] [@vm.inferred-type.metadata=dart.core::bool (skip check)] this.{pro::GeneratedMessage::$_has}(5);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] @#C20
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] @#C19
method clearClearKeep() → void
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.clearField] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] this.{pro::GeneratedMessage::clearField}(7);
}
class BarKeep extends pro::GeneratedMessage {
-[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t2 = new pro::BuilderInfo::•("BarKeep", createEmptyInstance: #C2) in block {
- [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::a}<core::int*>(1, "aKeep", #C5, protoName: "aKeep");
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t2 = new pro::BuilderInfo::•("BarKeep") in block {
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::a}<core::int*>(1, "aKeep", #C4);
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
[@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::hasRequiredFields} = false;
} =>#t2;
@@ -96,19 +96,19 @@
return [@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep::create();
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] get info_() → pro::BuilderInfo*
return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::BarKeep::_i;
- @#C10
+ @#C9
static method create() → self::BarKeep*
return new self::BarKeep::_();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] [@vm.unboxing-info.metadata=()->i] @#C12
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] [@vm.unboxing-info.metadata=()->i] @#C11
get aKeep() → core::int*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(0);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] [@vm.unboxing-info.metadata=(i)->b] @#C12
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] [@vm.unboxing-info.metadata=(i)->b] @#C11
set aKeep([@vm.inferred-type.metadata=dart.core::_Smi] core::int* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(0, v);
}
}
class HasKeep extends pro::GeneratedMessage {
-[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t3 = new pro::BuilderInfo::•("HasKeep", createEmptyInstance: #C6) in block {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t3 = new pro::BuilderInfo::•("HasKeep") in block {
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
[@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pro::BuilderInfo::hasRequiredFields} = false;
} =>#t3;
@@ -117,12 +117,12 @@
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] get info_() → pro::BuilderInfo*
return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::HasKeep::_i;
- @#C10
+ @#C9
static method create() → self::HasKeep*
return new self::HasKeep::_();
}
class ClearKeep extends pro::GeneratedMessage {
-[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t4 = new pro::BuilderInfo::•("ClearKeep", createEmptyInstance: #C7) in block {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t4 = new pro::BuilderInfo::•("ClearKeep") in block {
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
[@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::BuilderInfo::hasRequiredFields} = false;
} =>#t4;
@@ -131,7 +131,7 @@
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] get info_() → pro::BuilderInfo*
return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::ClearKeep::_i;
- @#C10
+ @#C9
static method create() → self::ClearKeep*
return new self::ClearKeep::_();
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart.expect
index c392e78..599d0eb 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart.expect
@@ -21,7 +21,7 @@
import "package:protobuf/protobuf.dart" as $pb;
class AKeep extends pro::GeneratedMessage {
-[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t1 = let core::String* #t2 = "AKeep" in let () →* self::AKeep* #t3 = #C1 in new pro::BuilderInfo::•(#t2, #t3) in block {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t1 = new pro::BuilderInfo::•("AKeep") in block {
[@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::hasRequiredFields} = false;
} =>#t1;
constructor _() → self::AKeep*
@@ -30,39 +30,39 @@
static factory •() → self::AKeep*
return [@vm.inferred-type.metadata=name_mangling.pb.dart::AKeep] self::AKeep::create();
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method clone() → self::AKeep*
- return let final self::AKeep* #t4 = [@vm.inferred-type.metadata=name_mangling.pb.dart::AKeep] self::AKeep::•() in block {
- [@vm.direct-call.metadata=protobuf::GeneratedMessage.mergeFromMessage] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::GeneratedMessage::mergeFromMessage}(this);
- } =>#t4;
+ return let final self::AKeep* #t2 = [@vm.inferred-type.metadata=name_mangling.pb.dart::AKeep] self::AKeep::•() in block {
+ [@vm.direct-call.metadata=protobuf::GeneratedMessage.mergeFromMessage] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::GeneratedMessage::mergeFromMessage}(this);
+ } =>#t2;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] get info_() → pro::BuilderInfo*
return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::AKeep::_i;
- @#C4
+ @#C3
static method create() → self::AKeep*
return new self::AKeep::_();
}
class NameManglingKeep extends pro::GeneratedMessage {
-[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t5 = let core::String* #t6 = "NameManglingKeep" in let () →* self::NameManglingKeep* #t7 = #C5 in new pro::BuilderInfo::•(#t6, #t7) in block {
- [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t5.{pro::BuilderInfo::aOM}<self::AKeep*>(10, "clone", subBuilder: #C1);
- [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t5.{pro::BuilderInfo::hasRequiredFields} = false;
- } =>#t5;
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t3 = new pro::BuilderInfo::•("NameManglingKeep") in block {
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pro::BuilderInfo::aOM}<self::AKeep*>(10, "clone", #C4);
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pro::BuilderInfo::hasRequiredFields} = false;
+ } =>#t3;
constructor _() → self::NameManglingKeep*
: super pro::GeneratedMessage::•()
;
static factory •() → self::NameManglingKeep*
return [@vm.inferred-type.metadata=name_mangling.pb.dart::NameManglingKeep] self::NameManglingKeep::create();
- static factory fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] core::List<core::int*>* i, [[@vm.inferred-type.metadata=protobuf::_EmptyExtensionRegistry (value: const protobuf::_EmptyExtensionRegistry{})] pro::ExtensionRegistry* r = #C6]) → self::NameManglingKeep*
- return let final self::NameManglingKeep* #t8 = [@vm.inferred-type.metadata=name_mangling.pb.dart::NameManglingKeep] self::NameManglingKeep::create() in block {
- [@vm.direct-call.metadata=protobuf::GeneratedMessage.mergeFromBuffer] [@vm.inferred-type.metadata=!? (skip check)] #t8.{pro::GeneratedMessage::mergeFromBuffer}(i, r);
- } =>#t8;
+ static factory fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] core::List<core::int*>* i) → self::NameManglingKeep*
+ return let final self::NameManglingKeep* #t4 = [@vm.inferred-type.metadata=name_mangling.pb.dart::NameManglingKeep] self::NameManglingKeep::create() in block {
+ [@vm.direct-call.metadata=protobuf::GeneratedMessage.mergeFromBuffer] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::GeneratedMessage::mergeFromBuffer}(i, #C5);
+ } =>#t4;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method clone() → self::NameManglingKeep*
- return let final self::NameManglingKeep* #t9 = [@vm.inferred-type.metadata=name_mangling.pb.dart::NameManglingKeep] self::NameManglingKeep::•() in block {
- [@vm.direct-call.metadata=protobuf::GeneratedMessage.mergeFromMessage] [@vm.inferred-type.metadata=!? (skip check)] #t9.{pro::GeneratedMessage::mergeFromMessage}(this);
- } =>#t9;
+ return let final self::NameManglingKeep* #t5 = [@vm.inferred-type.metadata=name_mangling.pb.dart::NameManglingKeep] self::NameManglingKeep::•() in block {
+ [@vm.direct-call.metadata=protobuf::GeneratedMessage.mergeFromMessage] [@vm.inferred-type.metadata=!? (skip check)] #t5.{pro::GeneratedMessage::mergeFromMessage}(this);
+ } =>#t5;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] get info_() → pro::BuilderInfo*
return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::NameManglingKeep::_i;
- @#C4
+ @#C3
static method create() → self::NameManglingKeep*
return new self::NameManglingKeep::_();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] @#C8
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] @#C7
method hasClone_10() → core::bool*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_has] [@vm.inferred-type.metadata=dart.core::bool (skip check)] this.{pro::GeneratedMessage::$_has}(0);
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/set_map_constructor_concrete.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/set_map_constructor_concrete.dart.expect
index fa2eda6..413720d 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/set_map_constructor_concrete.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/set_map_constructor_concrete.dart.expect
@@ -9,15 +9,15 @@
[@vm.inferred-type.metadata=dart.collection::_CompactLinkedHashSet?<dynamic>]static field core::Set<dynamic>* globalSet = new col::_CompactLinkedHashSet::•<dynamic>();
[@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashSet?<dynamic>]static field core::Set<dynamic>* identitySet = [@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashSet<dynamic>] col::LinkedHashSet::identity<dynamic>();
[@vm.inferred-type.metadata=dart.collection::_CompactLinkedHashSet?<dart.core::String*>]static field core::Set<core::String*>* linkedSet = new col::_CompactLinkedHashSet::•<core::String*>();
-static field core::Set<core::String*>* linkedIdentitySet = let (core::Object?, core::Object?) → core::bool #t1 = #C1 in let (core::Object?) → core::int #t2 = #C2 in [@vm.inferred-type.metadata=!] col::LinkedHashSet::•<core::String*>(#t1, #t2);
-static field core::Set<core::String*>* linkedCustomSet = let (core::String*, core::String*) →* core::bool* #t3 = (core::String* a, core::String* b) → core::bool* => a.{core::String::==}(b) in let (core::String*) →* core::int* #t4 = (core::String* o) → core::int* => o.{core::String::hashCode} in let (dynamic) →* core::bool* #t5 = (dynamic o) → core::bool* => true in [@vm.inferred-type.metadata=!] col::LinkedHashSet::•<core::String*>(#t3, #t4, isValidKey: #t5);
+static field core::Set<core::String*>* linkedIdentitySet = [@vm.inferred-type.metadata=!] col::LinkedHashSet::•<core::String*>(#C1, #C2);
+static field core::Set<core::String*>* linkedCustomSet = let final (core::String*, core::String*) →* core::bool* #t1 = (core::String* a, core::String* b) → core::bool* => a.{core::String::==}(b) in let final (core::String*) →* core::int* #t2 = (core::String* o) → core::int* => o.{core::String::hashCode} in let final (dynamic) →* core::bool* #t3 = (dynamic o) → core::bool* => true in [@vm.inferred-type.metadata=!] col::LinkedHashSet::•<core::String*>(#t1, #t2, isValidKey: #t3);
[@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dynamic, dynamic>]static field core::Map<dynamic, dynamic>* globalMap = [@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap<dynamic, dynamic>] core::Map::•<dynamic, dynamic>();
[@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashMap?<dynamic, dynamic>]static field core::Map<dynamic, dynamic>* identityMap = [@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashMap<dynamic, dynamic>] col::LinkedHashMap::identity<dynamic, dynamic>();
[@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView?<dynamic, dynamic>]static field core::Map<dynamic, dynamic>* unmodifiableMap = [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dynamic, dynamic>] core::Map::unmodifiable<dynamic, dynamic>([@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashMap?<dynamic, dynamic>] self::identityMap);
[@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dynamic, dynamic>]static field core::Map<dynamic, dynamic>* globalMapLiteral = <dynamic, dynamic>{};
[@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dart.core::String*, dart.core::String*>]static field core::Map<core::String*, core::String*>* linkedMap = new col::_InternalLinkedHashMap::•<core::String*, core::String*>();
-static field core::Map<core::String*, core::String*>* linkedIdentityMap = let (core::Object?, core::Object?) → core::bool #t6 = #C1 in let (core::Object?) → core::int #t7 = #C2 in [@vm.inferred-type.metadata=!] col::LinkedHashMap::•<core::String*, core::String*>(#t6, #t7);
-static field core::Map<core::String*, core::String*>* linkedCustomMap = let (core::String*, core::String*) →* core::bool* #t8 = (core::String* a, core::String* b) → core::bool* => a.{core::String::==}(b) in let (core::String*) →* core::int* #t9 = (core::String* o) → core::int* => o.{core::String::hashCode} in let (dynamic) →* core::bool* #t10 = (dynamic o) → core::bool* => true in [@vm.inferred-type.metadata=!] col::LinkedHashMap::•<core::String*, core::String*>(#t8, #t9, isValidKey: #t10);
+static field core::Map<core::String*, core::String*>* linkedIdentityMap = [@vm.inferred-type.metadata=!] col::LinkedHashMap::•<core::String*, core::String*>(#C1, #C2);
+static field core::Map<core::String*, core::String*>* linkedCustomMap = let final (core::String*, core::String*) →* core::bool* #t4 = (core::String* a, core::String* b) → core::bool* => a.{core::String::==}(b) in let final (core::String*) →* core::int* #t5 = (core::String* o) → core::int* => o.{core::String::hashCode} in let final (dynamic) →* core::bool* #t6 = (dynamic o) → core::bool* => true in [@vm.inferred-type.metadata=!] col::LinkedHashMap::•<core::String*, core::String*>(#t4, #t5, isValidKey: #t6);
static method main() → dynamic {
core::print([@vm.inferred-type.metadata=dart.collection::_CompactLinkedHashSet?<dynamic>] self::globalSet);
core::print([@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashSet?<dynamic>] self::identitySet);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart
index 4de6f85..726b6c9 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart
@@ -6,6 +6,11 @@
final bool kFalse = int.parse('1') == 2 ? true : false;
int get mint => 0xaabbccddaabbccdd;
int get smiOrMint => kTrue ? 1 : mint;
+dynamic usedObject;
+
+void use(dynamic object) {
+ usedObject ??= object;
+}
abstract class BI1 {
int get value;
@@ -86,5 +91,3 @@
final ubib = UBIB(); // getter returns smiOrMint
use((kTrue ? ubia : ubib).value);
}
-
-void use(dynamic object) {}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart.expect
index be40648..4dbd258 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart.expect
@@ -69,10 +69,14 @@
return [@vm.inferred-type.metadata=int] self::smiOrMint;
}
[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kTrue = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.inferred-type.metadata=int] core::int::parse("1").{core::num::==}(1) ?{core::bool*} true : false;
+[@vm.inferred-type.metadata=int?]static field dynamic usedObject;
[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
return -6144092014192636707;
[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int*
return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : [@vm.inferred-type.metadata=int] self::mint;
+static method use([@vm.inferred-type.metadata=int?] dynamic object) → void {
+ [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.inferred-type.metadata=int?] self::usedObject.{core::Object::==}(null) ?{dynamic} self::usedObject = object : null;
+}
static method main() → dynamic {
final self::BI1A* bi1a = new self::BI1A::•([@vm.inferred-type.metadata=int] self::smiOrMint);
final self::BI1B* bi1b = new self::BI1B::•();
@@ -88,4 +92,3 @@
final self::UBIB* ubib = new self::UBIB::•();
self::use([@vm.inferred-type.metadata=int]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::UBI*} ubia : ubib).{self::UBI::value});
}
-static method use([@vm.inferred-type.metadata=int?] dynamic object) → void {}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_fields.dart b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_fields.dart
index 8ab5bc9..ff1a20e 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_fields.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_fields.dart
@@ -6,6 +6,11 @@
final bool kFalse = int.parse('1') == 2 ? true : false;
int get mint => 0xaabbccddaabbccdd;
int get smiOrMint => kTrue ? 1 : mint;
+dynamic usedObject;
+
+void use(dynamic object) {
+ usedObject ??= object;
+}
class X {}
@@ -64,5 +69,3 @@
use(a.boxedNullableX);
use(a.boxedX);
}
-
-void use(dynamic object) {}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_fields.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_fields.dart.expect
index bce3568..65b0969 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_fields.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_fields.dart.expect
@@ -23,10 +23,14 @@
}
[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kTrue = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.inferred-type.metadata=int] core::int::parse("1").{core::num::==}(1) ?{core::bool*} true : false;
[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kFalse = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.inferred-type.metadata=int] core::int::parse("1").{core::num::==}(2) ?{core::bool*} true : false;
+static field dynamic usedObject;
[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
return -6144092014192636707;
[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int*
return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : [@vm.inferred-type.metadata=int] self::mint;
+static method use(dynamic object) → void {
+ [@vm.inferred-type.metadata=!? (receiver not int)] self::usedObject.{core::Object::==}(null) ?{dynamic} self::usedObject = object : null;
+}
static method main() → dynamic {
final self::A* a = new self::A::•([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, new self::X::•());
[@vm.direct-call.metadata=#lib::A.unboxedSmi] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::unboxedSmi} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2;
@@ -48,4 +52,3 @@
self::use([@vm.direct-call.metadata=#lib::A.boxedNullableX] [@vm.inferred-type.metadata=#lib::X?] a.{self::A::boxedNullableX});
self::use([@vm.direct-call.metadata=#lib::A.boxedX] [@vm.inferred-type.metadata=#lib::X] a.{self::A::boxedX});
}
-static method use(dynamic object) → void {}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart
index bf63d64..f37b67e 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart
@@ -6,6 +6,11 @@
final bool kFalse = int.parse('1') == 2 ? true : false;
int get mint => 0xaabbccddaabbccdd;
int get smiOrMint => kTrue ? 1 : mint;
+dynamic usedObject;
+
+void use(dynamic object) {
+ usedObject ??= object;
+}
class X {}
@@ -42,7 +47,16 @@
dynamic boxedNonNullableIntOrDouble,
dynamic boxedNullableIntOrDouble,
dynamic boxedNullableX,
- dynamic boxedX) {}
+ dynamic boxedX) {
+ use(unboxedInt);
+ use(unboxedDouble);
+ use(boxedNullableInt);
+ use(boxedNullableDouble);
+ use(boxedNonNullableIntOrDouble);
+ use(boxedNullableIntOrDouble);
+ use(boxedNullableX);
+ use(boxedX);
+ }
dynamic returnUnboxedSmi(X ignored) => 1;
dynamic returnUnboxedInt(X ignored) => 1;
@@ -65,7 +79,16 @@
dynamic boxedNonNullableIntOrDouble,
dynamic boxedNullableIntOrDouble,
dynamic boxedNullableX,
- dynamic boxedX) {}
+ dynamic boxedX) {
+ use(unboxedInt);
+ use(unboxedDouble);
+ use(boxedNullableInt);
+ use(boxedNullableDouble);
+ use(boxedNonNullableIntOrDouble);
+ use(boxedNullableIntOrDouble);
+ use(boxedNullableX);
+ use(boxedX);
+ }
dynamic returnUnboxedSmi(X ignored) => 2;
dynamic returnUnboxedInt(X ignored) => mint;
@@ -88,7 +111,16 @@
dynamic boxedNonNullableIntOrDouble,
dynamic boxedNullableIntOrDouble,
dynamic boxedNullableX,
- dynamic boxedX) {}
+ dynamic boxedX) {
+ use(unboxedInt);
+ use(unboxedDouble);
+ use(boxedNullableInt);
+ use(boxedNullableDouble);
+ use(boxedNonNullableIntOrDouble);
+ use(boxedNullableIntOrDouble);
+ use(boxedNullableX);
+ use(boxedX);
+ }
dynamic returnUnboxedSmi(X ignored) => 3;
dynamic returnUnboxedInt(X ignored) => mint;
@@ -154,5 +186,3 @@
use(d.returnBoxedNullableX(null));
use(d.returnBoxedX(null));
}
-
-void use(dynamic value) {}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart.expect
index e019e26..34bb4b0 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart.expect
@@ -8,136 +8,166 @@
;
}
abstract class Interface extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i,i,d,b,b,b,b,b,b)->b] abstract method takePositional(core::int* unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i] abstract method returnUnboxedSmi(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i] abstract method returnUnboxedInt(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d] abstract method returnUnboxedDouble(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] abstract method returnBoxedNullableInt(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] abstract method returnBoxedNullableDouble(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] abstract method returnBoxedIntOrDouble(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] abstract method returnBoxedNullableIntOrDouble(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] abstract method returnBoxedNullableX(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] abstract method returnBoxedX(self::X* ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i,d,b,b,b,b,b,b)->b] abstract method takePositional(dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i] abstract method returnUnboxedSmi() → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=()->i] abstract method returnUnboxedInt() → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=()->d] abstract method returnUnboxedDouble() → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] abstract method returnBoxedNullableInt() → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] abstract method returnBoxedNullableDouble() → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] abstract method returnBoxedIntOrDouble() → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] abstract method returnBoxedNullableIntOrDouble() → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] abstract method returnBoxedNullableX() → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] abstract method returnBoxedX() → dynamic;
}
class Impl1 extends core::Object implements self::Interface {
synthetic constructor •() → self::Impl1*
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i,i,d,b,b,b,b,b,b)->b] method takePositional([@vm.inferred-type.metadata=dart.core::_Smi] core::int* unboxedSmi, [@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=!] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {}
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedSmi([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i,d,b,b,b,b,b,b)->b] method takePositional([@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=!] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {
+ self::use(unboxedInt);
+ self::use(unboxedDouble);
+ self::use(boxedNullableInt);
+ self::use(boxedNullableDouble);
+ self::use(boxedNonNullableIntOrDouble);
+ self::use(boxedNullableIntOrDouble);
+ self::use(boxedNullableX);
+ self::use(boxedX);
+ }
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i] method returnUnboxedSmi() → dynamic
return 1;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedInt([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=()->i] method returnUnboxedInt() → dynamic
return 1;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d] method returnUnboxedDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=()->d] method returnUnboxedDouble() → dynamic
return 1.1;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method returnBoxedNullableInt([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method returnBoxedNullableInt() → dynamic
return null;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method returnBoxedNullableDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method returnBoxedNullableDouble() → dynamic
return null;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method returnBoxedIntOrDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method returnBoxedIntOrDouble() → dynamic
return 1;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] method returnBoxedNullableIntOrDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] method returnBoxedNullableIntOrDouble() → dynamic
return null;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] method returnBoxedNullableX([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] method returnBoxedNullableX() → dynamic
return null;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method returnBoxedX([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method returnBoxedX() → dynamic
return new self::X::•();
}
class BaseImpl2 extends core::Object {
synthetic constructor •() → self::BaseImpl2*
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i,i,d,b,b,b,b,b,b)->b] method takePositional([@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] core::int* unboxedSmi, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic unboxedDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {}
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedSmi([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i,d,b,b,b,b,b,b)->b] method takePositional([@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic unboxedDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {
+ self::use(unboxedInt);
+ self::use(unboxedDouble);
+ self::use(boxedNullableInt);
+ self::use(boxedNullableDouble);
+ self::use(boxedNonNullableIntOrDouble);
+ self::use(boxedNullableIntOrDouble);
+ self::use(boxedNullableX);
+ self::use(boxedX);
+ }
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i] method returnUnboxedSmi() → dynamic
return 2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedInt([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=()->i] method returnUnboxedInt() → dynamic
return [@vm.inferred-type.metadata=int] self::mint;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d] method returnUnboxedDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=()->d] method returnUnboxedDouble() → dynamic
return 2.2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method returnBoxedNullableInt([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method returnBoxedNullableInt() → dynamic
return 2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method returnBoxedNullableDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method returnBoxedNullableDouble() → dynamic
return 2.2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method returnBoxedIntOrDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method returnBoxedIntOrDouble() → dynamic
return 2.2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] method returnBoxedNullableIntOrDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] method returnBoxedNullableIntOrDouble() → dynamic
return 2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] method returnBoxedNullableX([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] method returnBoxedNullableX() → dynamic
return new self::X::•();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method returnBoxedX([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method returnBoxedX() → dynamic
return new self::X::•();
}
class SubImpl3 extends self::BaseImpl2 implements self::Interface {
synthetic constructor •() → self::SubImpl3*
: super self::BaseImpl2::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i,i,d,b,b,b,b,b,b)->b] method takePositional([@vm.inferred-type.metadata=dart.core::_Smi] core::int* unboxedSmi, [@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=dart.core::_Double] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=!] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {}
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedSmi([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i,d,b,b,b,b,b,b)->b] method takePositional([@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=dart.core::_Double] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=!] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {
+ self::use(unboxedInt);
+ self::use(unboxedDouble);
+ self::use(boxedNullableInt);
+ self::use(boxedNullableDouble);
+ self::use(boxedNonNullableIntOrDouble);
+ self::use(boxedNullableIntOrDouble);
+ self::use(boxedNullableX);
+ self::use(boxedX);
+ }
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i] method returnUnboxedSmi() → dynamic
return 3;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedInt([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=()->i] method returnUnboxedInt() → dynamic
return [@vm.inferred-type.metadata=int] self::mint;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d] method returnUnboxedDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=()->d] method returnUnboxedDouble() → dynamic
return 3.3;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method returnBoxedNullableInt([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method returnBoxedNullableInt() → dynamic
return [@vm.inferred-type.metadata=int] self::mint;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method returnBoxedNullableDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method returnBoxedNullableDouble() → dynamic
return 3.3;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method returnBoxedIntOrDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method returnBoxedIntOrDouble() → dynamic
return 3.3;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] method returnBoxedNullableIntOrDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] method returnBoxedNullableIntOrDouble() → dynamic
return 3.3;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] method returnBoxedNullableX([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] method returnBoxedNullableX() → dynamic
return new self::X::•();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method returnBoxedX([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method returnBoxedX() → dynamic
return new self::X::•();
}
+static field dynamic usedObject;
[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
return -6144092014192636707;
+static method use(dynamic object) → void {
+ [@vm.inferred-type.metadata=!? (receiver not int)] self::usedObject.{core::Object::==}(null) ?{dynamic} self::usedObject = object : null;
+}
static method main() → dynamic {
final core::List<core::Object*>* values = <core::Object*>[new self::Impl1::•(), new self::BaseImpl2::•(), new self::SubImpl3::•()];
final self::Impl1* a = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int] core::int::parse("0")) as self::Impl1*;
final self::BaseImpl2* b = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int] core::int::parse("1")) as self::BaseImpl2*;
final self::SubImpl3* c = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int] core::int::parse("2")) as self::SubImpl3*;
final self::Interface* d = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int] core::int::parse("2")) as self::Interface*;
- [@vm.direct-call.metadata=#lib::Impl1.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] a.{self::Impl1::takePositional}(1, 1, 1.1, null, null, 1, null, null, new self::X::•());
- b.{self::BaseImpl2::takePositional}(2, 2, 2.2, 2, 2.2, 2.2, 2, new self::X::•(), new self::X::•());
- [@vm.direct-call.metadata=#lib::SubImpl3.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] c.{self::SubImpl3::takePositional}(3, [@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•());
- d.{self::Interface::takePositional}(3, [@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•());
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedSmi}(null));
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedInt] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedInt}(null));
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 1.1)] a.{self::Impl1::returnUnboxedDouble}(null));
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableInt] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableInt}(null));
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableDouble}(null));
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnBoxedIntOrDouble}(null));
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableIntOrDouble}(null));
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableX] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableX}(null));
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] a.{self::Impl1::returnBoxedX}(null));
- self::use([@vm.inferred-type.metadata=dart.core::_Smi] b.{self::BaseImpl2::returnUnboxedSmi}(null));
- self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnUnboxedInt}(null));
- self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnUnboxedDouble}(null));
- self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnBoxedNullableInt}(null));
- self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedNullableDouble}(null));
- self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedIntOrDouble}(null));
- self::use([@vm.inferred-type.metadata=!] b.{self::BaseImpl2::returnBoxedNullableIntOrDouble}(null));
- self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedNullableX}(null));
- self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedX}(null));
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 3)] c.{self::SubImpl3::returnUnboxedSmi}(null));
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnUnboxedInt}(null));
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnUnboxedDouble}(null));
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnBoxedNullableInt}(null));
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableDouble}(null));
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedIntOrDouble}(null));
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableIntOrDouble}(null));
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedNullableX}(null));
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedX}(null));
- self::use([@vm.inferred-type.metadata=dart.core::_Smi] d.{self::Interface::returnUnboxedSmi}(null));
- self::use([@vm.inferred-type.metadata=int] d.{self::Interface::returnUnboxedInt}(null));
- self::use([@vm.inferred-type.metadata=dart.core::_Double] d.{self::Interface::returnUnboxedDouble}(null));
- self::use([@vm.inferred-type.metadata=int?] d.{self::Interface::returnBoxedNullableInt}(null));
- self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableDouble}(null));
- self::use([@vm.inferred-type.metadata=!] d.{self::Interface::returnBoxedIntOrDouble}(null));
- self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableIntOrDouble}(null));
- self::use([@vm.inferred-type.metadata=#lib::X?] d.{self::Interface::returnBoxedNullableX}(null));
- self::use([@vm.inferred-type.metadata=#lib::X] d.{self::Interface::returnBoxedX}(null));
+ [@vm.direct-call.metadata=#lib::Impl1.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] a.{self::Impl1::takePositional}(1, 1.1, null, null, 1, null, null, new self::X::•());
+ b.{self::BaseImpl2::takePositional}(2, 2.2, 2, 2.2, 2.2, 2, new self::X::•(), new self::X::•());
+ [@vm.direct-call.metadata=#lib::SubImpl3.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] c.{self::SubImpl3::takePositional}([@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•());
+ d.{self::Interface::takePositional}([@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•());
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedSmi}());
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedInt] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedInt}());
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 1.1)] a.{self::Impl1::returnUnboxedDouble}());
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableInt] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableInt}());
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableDouble}());
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnBoxedIntOrDouble}());
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableIntOrDouble}());
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableX] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableX}());
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] a.{self::Impl1::returnBoxedX}());
+ self::use([@vm.inferred-type.metadata=dart.core::_Smi] b.{self::BaseImpl2::returnUnboxedSmi}());
+ self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnUnboxedInt}());
+ self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnUnboxedDouble}());
+ self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnBoxedNullableInt}());
+ self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedNullableDouble}());
+ self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedIntOrDouble}());
+ self::use([@vm.inferred-type.metadata=!] b.{self::BaseImpl2::returnBoxedNullableIntOrDouble}());
+ self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedNullableX}());
+ self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedX}());
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 3)] c.{self::SubImpl3::returnUnboxedSmi}());
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnUnboxedInt}());
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnUnboxedDouble}());
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnBoxedNullableInt}());
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableDouble}());
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedIntOrDouble}());
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableIntOrDouble}());
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedNullableX}());
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedX}());
+ self::use([@vm.inferred-type.metadata=dart.core::_Smi] d.{self::Interface::returnUnboxedSmi}());
+ self::use([@vm.inferred-type.metadata=int] d.{self::Interface::returnUnboxedInt}());
+ self::use([@vm.inferred-type.metadata=dart.core::_Double] d.{self::Interface::returnUnboxedDouble}());
+ self::use([@vm.inferred-type.metadata=int?] d.{self::Interface::returnBoxedNullableInt}());
+ self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableDouble}());
+ self::use([@vm.inferred-type.metadata=!] d.{self::Interface::returnBoxedIntOrDouble}());
+ self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableIntOrDouble}());
+ self::use([@vm.inferred-type.metadata=#lib::X?] d.{self::Interface::returnBoxedNullableX}());
+ self::use([@vm.inferred-type.metadata=#lib::X] d.{self::Interface::returnBoxedX}());
}
-static method use(dynamic value) → void {}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart
index fa87b74..ddbf2a0 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart
@@ -6,6 +6,11 @@
final bool kFalse = int.parse('1') == 2 ? true : false;
int get mint => 0xaabbccddaabbccdd;
int get smiOrMint => kTrue ? 1 : mint;
+dynamic usedObject;
+
+void use(dynamic object) {
+ usedObject ??= object;
+}
class X {}
@@ -42,7 +47,16 @@
dynamic boxedNonNullableIntOrDouble,
dynamic boxedNullableIntOrDouble,
dynamic boxedNullableX,
- dynamic boxedX) {}
+ dynamic boxedX) {
+ use(unboxedInt);
+ use(unboxedDouble);
+ use(boxedNullableInt);
+ use(boxedNullableDouble);
+ use(boxedNonNullableIntOrDouble);
+ use(boxedNullableIntOrDouble);
+ use(boxedNullableX);
+ use(boxedX);
+ }
dynamic returnUnboxedSmi(X ignored) => 1;
dynamic returnUnboxedInt(X ignored) => 1;
@@ -65,7 +79,16 @@
dynamic boxedNonNullableIntOrDouble,
dynamic boxedNullableIntOrDouble,
dynamic boxedNullableX,
- dynamic boxedX) {}
+ dynamic boxedX) {
+ use(unboxedInt);
+ use(unboxedDouble);
+ use(boxedNullableInt);
+ use(boxedNullableDouble);
+ use(boxedNonNullableIntOrDouble);
+ use(boxedNullableIntOrDouble);
+ use(boxedNullableX);
+ use(boxedX);
+ }
dynamic returnUnboxedSmi(X ignored) => 2;
dynamic returnUnboxedInt(X ignored) => mint;
@@ -88,7 +111,16 @@
dynamic boxedNonNullableIntOrDouble,
dynamic boxedNullableIntOrDouble,
dynamic boxedNullableX,
- dynamic boxedX) {}
+ dynamic boxedX) {
+ use(unboxedInt);
+ use(unboxedDouble);
+ use(boxedNullableInt);
+ use(boxedNullableDouble);
+ use(boxedNonNullableIntOrDouble);
+ use(boxedNullableIntOrDouble);
+ use(boxedNullableX);
+ use(boxedX);
+ }
dynamic returnUnboxedSmi(X ignored) => 3;
dynamic returnUnboxedInt(X ignored) => mint;
@@ -166,5 +198,3 @@
use(d.returnBoxedNullableX);
use(d.returnBoxedX);
}
-
-void use(dynamic value) {}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart.expect
index bed2172..0b24d0e 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart.expect
@@ -23,7 +23,16 @@
synthetic constructor •() → self::Impl1*
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method takePositional(core::int* unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {}
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method takePositional(core::int* unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {
+ self::use(unboxedInt);
+ self::use(unboxedDouble);
+ self::use(boxedNullableInt);
+ self::use(boxedNullableDouble);
+ self::use(boxedNonNullableIntOrDouble);
+ self::use(boxedNullableIntOrDouble);
+ self::use(boxedNullableX);
+ self::use(boxedX);
+ }
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedSmi(self::X* ignored) → dynamic
return 1;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedInt(self::X* ignored) → dynamic
@@ -47,7 +56,16 @@
synthetic constructor •() → self::BaseImpl2*
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method takePositional([@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] core::int* unboxedSmi, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic unboxedDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {}
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method takePositional([@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] core::int* unboxedSmi, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic unboxedDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {
+ self::use(unboxedInt);
+ self::use(unboxedDouble);
+ self::use(boxedNullableInt);
+ self::use(boxedNullableDouble);
+ self::use(boxedNonNullableIntOrDouble);
+ self::use(boxedNullableIntOrDouble);
+ self::use(boxedNullableX);
+ self::use(boxedX);
+ }
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedSmi([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
return 2;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedInt([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
@@ -71,7 +89,16 @@
synthetic constructor •() → self::SubImpl3*
: super self::BaseImpl2::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method takePositional(core::int* unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {}
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method takePositional(core::int* unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {
+ self::use(unboxedInt);
+ self::use(unboxedDouble);
+ self::use(boxedNullableInt);
+ self::use(boxedNullableDouble);
+ self::use(boxedNonNullableIntOrDouble);
+ self::use(boxedNullableIntOrDouble);
+ self::use(boxedNullableX);
+ self::use(boxedX);
+ }
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedSmi(self::X* ignored) → dynamic
return 3;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedInt(self::X* ignored) → dynamic
@@ -91,8 +118,12 @@
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method returnBoxedX(self::X* ignored) → dynamic
return new self::X::•();
}
+static field dynamic usedObject;
[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
return -6144092014192636707;
+static method use(dynamic object) → void {
+ [@vm.inferred-type.metadata=!? (receiver not int)] self::usedObject.{core::Object::==}(null) ?{dynamic} self::usedObject = object : null;
+}
static method main() → dynamic {
final core::List<core::Object*>* values = <core::Object*>[new self::Impl1::•(), new self::BaseImpl2::•(), new self::SubImpl3::•()];
final self::Impl1* a = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int] core::int::parse("0")) as self::Impl1*;
@@ -150,4 +181,3 @@
self::use(d.{self::Interface::returnBoxedNullableX});
self::use(d.{self::Interface::returnBoxedX});
}
-static method use(dynamic value) → void {}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart
index 49c6b9f..5151f2e 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart
@@ -6,6 +6,11 @@
final bool kFalse = int.parse('1') == 2 ? true : false;
int get mint => 0xaabbccddaabbccdd;
int get smiOrMint => kTrue ? 1 : mint;
+dynamic usedObject;
+
+void use(dynamic object) {
+ usedObject ??= object;
+}
class X {}
@@ -18,7 +23,16 @@
dynamic boxedIntOrDouble,
dynamic boxedNullableIntOrDouble,
dynamic boxedNullableX,
- dynamic boxedX) {}
+ dynamic boxedX) {
+ use(unboxedInt);
+ use(unboxedDouble);
+ use(boxedNullableInt);
+ use(boxedNullableDouble);
+ use(boxedIntOrDouble);
+ use(boxedNullableIntOrDouble);
+ use(boxedNullableX);
+ use(boxedX);
+}
void takeOptional(
[int unboxedSmi,
@@ -29,7 +43,16 @@
dynamic boxedIntOrDouble,
dynamic boxedNullableIntOrDouble,
dynamic boxedNullableX,
- dynamic boxedX]) {}
+ dynamic boxedX]) {
+ use(unboxedInt);
+ use(unboxedDouble);
+ use(boxedNullableInt);
+ use(boxedNullableDouble);
+ use(boxedIntOrDouble);
+ use(boxedNullableIntOrDouble);
+ use(boxedNullableX);
+ use(boxedX);
+}
void takeNamed(
{int unboxedSmi,
@@ -40,7 +63,16 @@
dynamic boxedIntOrDouble,
dynamic boxedNullableIntOrDouble,
dynamic boxedNullableX,
- dynamic boxedX}) {}
+ dynamic boxedX}) {
+ use(unboxedInt);
+ use(unboxedDouble);
+ use(boxedNullableInt);
+ use(boxedNullableDouble);
+ use(boxedIntOrDouble);
+ use(boxedNullableIntOrDouble);
+ use(boxedNullableX);
+ use(boxedX);
+}
dynamic returnUnboxedSmi() => kTrue ? 1 : 2;
dynamic returnUnboxedInt() => kTrue ? smiOrMint : 2;
@@ -106,5 +138,3 @@
use(returnBoxedX());
use(returnBoxedSmiFromEntryPoint());
}
-
-void use(dynamic value) {}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart.expect
index 8074925..934befa 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart.expect
@@ -9,13 +9,44 @@
}
[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kTrue = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.inferred-type.metadata=int] core::int::parse("1").{core::num::==}(1) ?{core::bool*} true : false;
[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kFalse = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.inferred-type.metadata=int] core::int::parse("1").{core::num::==}(2) ?{core::bool*} true : false;
+static field dynamic usedObject;
[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
return -6144092014192636707;
[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int*
return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : [@vm.inferred-type.metadata=int] self::mint;
-[@vm.unboxing-info.metadata=(i,i,d,b,b,b,b,b,b)->b]static method takePositional([@vm.inferred-type.metadata=dart.core::_Smi] core::int* unboxedSmi, [@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=!] dynamic boxedIntOrDouble, dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {}
-static method takeOptional([@vm.inferred-type.metadata=dart.core::_Smi] core::int* unboxedSmi, [@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=!] dynamic boxedIntOrDouble, dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {}
-static method takeNamed([@vm.inferred-type.metadata=!] dynamic boxedIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Smi] core::int* unboxedSmi) → void {}
+static method use(dynamic object) → void {
+ [@vm.inferred-type.metadata=!? (receiver not int)] self::usedObject.{core::Object::==}(null) ?{dynamic} self::usedObject = object : null;
+}
+[@vm.unboxing-info.metadata=(i,d,b,b,b,b,b,b)->b]static method takePositional([@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=!] dynamic boxedIntOrDouble, dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {
+ self::use(unboxedInt);
+ self::use(unboxedDouble);
+ self::use(boxedNullableInt);
+ self::use(boxedNullableDouble);
+ self::use(boxedIntOrDouble);
+ self::use(boxedNullableIntOrDouble);
+ self::use(boxedNullableX);
+ self::use(boxedX);
+}
+[@vm.unboxing-info.metadata=(i,d,b,b,b,b,b,b)->b]static method takeOptional([@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=!] dynamic boxedIntOrDouble, dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {
+ self::use(unboxedInt);
+ self::use(unboxedDouble);
+ self::use(boxedNullableInt);
+ self::use(boxedNullableDouble);
+ self::use(boxedIntOrDouble);
+ self::use(boxedNullableIntOrDouble);
+ self::use(boxedNullableX);
+ self::use(boxedX);
+}
+[@vm.unboxing-info.metadata=(b,b,b,b,b,b,d,i)->b]static method takeNamed([@vm.inferred-type.metadata=!] dynamic boxedIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int] dynamic unboxedInt) → void {
+ self::use(unboxedInt);
+ self::use(unboxedDouble);
+ self::use(boxedNullableInt);
+ self::use(boxedNullableDouble);
+ self::use(boxedIntOrDouble);
+ self::use(boxedNullableIntOrDouble);
+ self::use(boxedNullableX);
+ self::use(boxedX);
+}
[@vm.unboxing-info.metadata=()->i]static method returnUnboxedSmi() → dynamic
return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2;
[@vm.unboxing-info.metadata=()->i]static method returnUnboxedInt() → dynamic
@@ -40,9 +71,9 @@
@#C3
static method takeBoxedSmiFromEntryPoint(core::int* value) → void {}
static method main() → dynamic {
- self::takePositional([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, new self::X::•());
- self::takeOptional([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, new self::X::•());
- let core::int* #t1 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2 in let core::int* #t2 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let core::double* #t3 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2 in let core::int* #t4 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let core::double* #t5 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null in let core::num* #t6 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let core::num* #t7 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let self::X* #t8 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null in let self::X* #t9 = new self::X::•() in self::takeNamed(#t6, #t5, #t4, #t7, #t8, #t9, #t3, #t2, #t1);
+ let final core::int* #t1 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2 in let final core::int* #t2 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let final core::double* #t3 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2 in let final core::int* #t4 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let final core::double* #t5 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null in let final core::num* #t6 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let final core::num* #t7 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let final self::X* #t8 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null in let final self::X* #t9 = new self::X::•() in self::takePositional(#t2, #t3, #t4, #t5, #t6, #t7, #t8, #t9);
+ let final core::int* #t10 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2 in let final core::int* #t11 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let final core::double* #t12 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2 in let final core::int* #t13 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let final core::double* #t14 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null in let final core::num* #t15 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let final core::num* #t16 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let final self::X* #t17 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null in let final self::X* #t18 = new self::X::•() in self::takeOptional(#t11, #t12, #t13, #t14, #t15, #t16, #t17, #t18);
+ let final core::int* #t19 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2 in let final core::int* #t20 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let final core::double* #t21 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2 in let final core::int* #t22 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let final core::double* #t23 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null in let final core::num* #t24 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let final core::num* #t25 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let final self::X* #t26 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null in let final self::X* #t27 = new self::X::•() in self::takeNamed(#t24, #t23, #t22, #t25, #t26, #t27, #t21, #t20);
self::takeBoxedSmiFromEntryPoint([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2);
self::use([@vm.inferred-type.metadata=dart.core::_Smi] self::returnUnboxedSmi());
self::use([@vm.inferred-type.metadata=int] self::returnUnboxedInt());
@@ -55,4 +86,3 @@
self::use([@vm.inferred-type.metadata=#lib::X] self::returnBoxedX());
self::use([@vm.inferred-type.metadata=dart.core::_Smi] self::returnBoxedSmiFromEntryPoint());
}
-static method use(dynamic value) → void {}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart
index 16bdbe5..f20e0ce 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart
@@ -6,6 +6,11 @@
final bool kFalse = int.parse('1') == 2 ? true : false;
int get mint => 0xaabbccddaabbccdd;
int get smiOrMint => kTrue ? 1 : mint;
+dynamic usedObject;
+
+void use(dynamic object) {
+ usedObject ??= object;
+}
class X {}
@@ -18,7 +23,16 @@
dynamic boxedIntOrDouble,
dynamic boxedNullableIntOrDouble,
dynamic boxedNullableX,
- dynamic boxedX) {}
+ dynamic boxedX) {
+ use(unboxedInt);
+ use(unboxedDouble);
+ use(boxedNullableInt);
+ use(boxedNullableDouble);
+ use(boxedIntOrDouble);
+ use(boxedNullableIntOrDouble);
+ use(boxedNullableX);
+ use(boxedX);
+}
void takeOptional(
[int unboxedSmi,
@@ -29,7 +43,16 @@
dynamic boxedIntOrDouble,
dynamic boxedNullableIntOrDouble,
dynamic boxedNullableX,
- dynamic boxedX]) {}
+ dynamic boxedX]) {
+ use(unboxedInt);
+ use(unboxedDouble);
+ use(boxedNullableInt);
+ use(boxedNullableDouble);
+ use(boxedIntOrDouble);
+ use(boxedNullableIntOrDouble);
+ use(boxedNullableX);
+ use(boxedX);
+}
void takeNamed(
{int unboxedSmi,
@@ -40,7 +63,16 @@
dynamic boxedIntOrDouble,
dynamic boxedNullableIntOrDouble,
dynamic boxedNullableX,
- dynamic boxedX}) {}
+ dynamic boxedX}) {
+ use(unboxedInt);
+ use(unboxedDouble);
+ use(boxedNullableInt);
+ use(boxedNullableDouble);
+ use(boxedIntOrDouble);
+ use(boxedNullableIntOrDouble);
+ use(boxedNullableX);
+ use(boxedX);
+}
dynamic returnUnboxedSmi() => kTrue ? 1 : 2;
dynamic returnUnboxedInt() => kTrue ? smiOrMint : 2;
@@ -99,6 +131,8 @@
// Use as tear-offs.
use(takePositional);
+ use(takeOptional);
+ use(takeNamed);
use(returnUnboxedSmi);
use(returnUnboxedInt);
use(returnUnboxedDouble);
@@ -109,5 +143,3 @@
use(returnBoxedNullableX);
use(returnBoxedX);
}
-
-void use(dynamic value) {}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart.expect
index 62e1f32..10fcb7a 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart.expect
@@ -9,13 +9,44 @@
}
[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kTrue = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.inferred-type.metadata=int] core::int::parse("1").{core::num::==}(1) ?{core::bool*} true : false;
[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kFalse = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.inferred-type.metadata=int] core::int::parse("1").{core::num::==}(2) ?{core::bool*} true : false;
+static field dynamic usedObject;
[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
return -6144092014192636707;
[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int*
return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : [@vm.inferred-type.metadata=int] self::mint;
-static method takePositional(core::int* unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {}
-static method takeOptional([@vm.inferred-type.metadata=dart.core::_Smi] core::int* unboxedSmi, [@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=!] dynamic boxedIntOrDouble, dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {}
-static method takeNamed([@vm.inferred-type.metadata=!] dynamic boxedIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Smi] core::int* unboxedSmi) → void {}
+static method use(dynamic object) → void {
+ [@vm.inferred-type.metadata=!? (receiver not int)] self::usedObject.{core::Object::==}(null) ?{dynamic} self::usedObject = object : null;
+}
+static method takePositional(core::int* unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {
+ self::use(unboxedInt);
+ self::use(unboxedDouble);
+ self::use(boxedNullableInt);
+ self::use(boxedNullableDouble);
+ self::use(boxedIntOrDouble);
+ self::use(boxedNullableIntOrDouble);
+ self::use(boxedNullableX);
+ self::use(boxedX);
+}
+static method takeOptional([core::int* unboxedSmi = #C1, dynamic unboxedInt = #C1, dynamic unboxedDouble = #C1, dynamic boxedNullableInt = #C1, dynamic boxedNullableDouble = #C1, dynamic boxedIntOrDouble = #C1, dynamic boxedNullableIntOrDouble = #C1, dynamic boxedNullableX = #C1, dynamic boxedX = #C1]) → void {
+ self::use(unboxedInt);
+ self::use(unboxedDouble);
+ self::use(boxedNullableInt);
+ self::use(boxedNullableDouble);
+ self::use(boxedIntOrDouble);
+ self::use(boxedNullableIntOrDouble);
+ self::use(boxedNullableX);
+ self::use(boxedX);
+}
+static method takeNamed({core::int* unboxedSmi = #C1, dynamic unboxedInt = #C1, dynamic unboxedDouble = #C1, dynamic boxedNullableInt = #C1, dynamic boxedNullableDouble = #C1, dynamic boxedIntOrDouble = #C1, dynamic boxedNullableIntOrDouble = #C1, dynamic boxedNullableX = #C1, dynamic boxedX = #C1}) → void {
+ self::use(unboxedInt);
+ self::use(unboxedDouble);
+ self::use(boxedNullableInt);
+ self::use(boxedNullableDouble);
+ self::use(boxedIntOrDouble);
+ self::use(boxedNullableIntOrDouble);
+ self::use(boxedNullableX);
+ self::use(boxedX);
+}
[@vm.unboxing-info.metadata=()->i]static method returnUnboxedSmi() → dynamic
return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2;
[@vm.unboxing-info.metadata=()->i]static method returnUnboxedInt() → dynamic
@@ -37,7 +68,7 @@
static method main() → dynamic {
self::takePositional([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, new self::X::•());
self::takeOptional([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, new self::X::•());
- let core::int* #t1 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2 in let core::int* #t2 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let core::double* #t3 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2 in let core::int* #t4 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let core::double* #t5 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null in let core::num* #t6 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let core::num* #t7 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let self::X* #t8 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null in let self::X* #t9 = new self::X::•() in self::takeNamed(#t6, #t5, #t4, #t7, #t8, #t9, #t3, #t2, #t1);
+ self::takeNamed(unboxedSmi: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, unboxedInt: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, unboxedDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, boxedNullableInt: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, boxedNullableDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, boxedIntOrDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, boxedNullableIntOrDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, boxedNullableX: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, boxedX: new self::X::•());
self::use([@vm.inferred-type.metadata=dart.core::_Smi] self::returnUnboxedSmi());
self::use([@vm.inferred-type.metadata=int] self::returnUnboxedInt());
self::use([@vm.inferred-type.metadata=dart.core::_Double] self::returnUnboxedDouble());
@@ -47,7 +78,6 @@
self::use(self::returnBoxedNullableIntOrDouble());
self::use([@vm.inferred-type.metadata=#lib::X?] self::returnBoxedNullableX());
self::use([@vm.inferred-type.metadata=#lib::X] self::returnBoxedX());
- self::use(#C1);
self::use(#C2);
self::use(#C3);
self::use(#C4);
@@ -57,5 +87,7 @@
self::use(#C8);
self::use(#C9);
self::use(#C10);
+ self::use(#C11);
+ self::use(#C12);
+ self::use(#C13);
}
-static method use(dynamic value) → void {}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect
index 082ed50..936781a 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect
@@ -12,7 +12,7 @@
;
}
class B extends core::Object {
- constructor •([@vm.inferred-type.metadata=dart.core::_OneByteString (value: "hi")] dynamic unused4) → self::B*
+ constructor •() → self::B*
: dynamic #t1 = [@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::foo(), super core::Object::•()
;
}
@@ -55,7 +55,7 @@
static method foo() → dynamic {}
static method main() → void {
new self::A::•();
- new self::B::•("hi");
+ new self::B::•();
self::C<core::num*>* c = new self::D::•();
exp::Expect::throws<dynamic>(() → core::Null? {
[@vm.call-site-attributes.metadata=receiverType:#lib::C<dart.core::num*>*] [@vm.direct-call.metadata=#lib::D.bar] c.{self::C::bar} = 3.14;
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 8f6992b..906eb34 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -1028,11 +1028,12 @@
# This file must be compiled in for dynamic linking.
"../include/dart_api_dl.c",
- # The two files here do not depend on each other.
- # flutter/flutter integration tests will only use `ffi_test_functions.cc` -
- # any test functionality using `dart_api.h` has to go into
- # `ffi_test_functions_vmspecific.cc`.
+ # The three files here do not depend on each other.
+ # flutter/flutter integration tests will only use
+ # `ffi_test_functions{,_generated}.cc` - any test functionality using
+ # `dart_api.h` has to go into `ffi_test_functions_vmspecific.cc`.
"ffi_test/ffi_test_functions.cc",
+ "ffi_test/ffi_test_functions_generated.cc",
"ffi_test/ffi_test_functions_vmspecific.cc",
]
if (is_win && current_cpu == "x64") {
diff --git a/runtime/bin/ffi_test/ffi_test_functions.cc b/runtime/bin/ffi_test/ffi_test_functions.cc
index c9e39e9..3304154 100644
--- a/runtime/bin/ffi_test/ffi_test_functions.cc
+++ b/runtime/bin/ffi_test/ffi_test_functions.cc
@@ -750,12 +750,48 @@
return retval;
}
+// Can't easily share this with the generated file.
+struct Struct20BytesHomogeneousInt32Copy {
+ int32_t a0;
+ int32_t a1;
+ int32_t a2;
+ int32_t a3;
+ int32_t a4;
+};
+
+DART_EXPORT Struct20BytesHomogeneousInt32Copy PassStructRecursive(
+ int64_t recursionCounter,
+ Struct20BytesHomogeneousInt32Copy a0,
+ Struct20BytesHomogeneousInt32Copy (*f)(int64_t,
+ Struct20BytesHomogeneousInt32Copy)) {
+ std::cout << "PassStruct20BytesHomogeneousInt32x10"
+ << "(" << recursionCounter << ", (" << a0.a0 << ", " << a0.a1
+ << ", " << a0.a2 << ", " << a0.a3 << ", " << a0.a4 << "), "
+ << reinterpret_cast<void*>(f) << ")\n";
+ a0.a0++;
+ const int32_t a0_a0_saved = a0.a0;
+
+ if (recursionCounter <= 0) {
+ return a0;
+ }
+
+ Struct20BytesHomogeneousInt32Copy result = f(recursionCounter - 1, a0);
+ result.a0++;
+ if (a0_a0_saved != a0.a0) {
+ result.a4 = 0;
+ }
+
+ return result;
+}
+
////////////////////////////////////////////////////////////////////////////////
// Tests for callbacks.
// Sanity test.
DART_EXPORT intptr_t TestSimpleAddition(intptr_t (*add)(int, int)) {
- CHECK_EQ(add(10, 20), 30);
+ const intptr_t result = add(10, 20);
+ std::cout << "result " << result << "\n";
+ CHECK_EQ(result, 30);
return 0;
}
@@ -764,7 +800,9 @@
DART_EXPORT intptr_t
TestIntComputation(int64_t (*fn)(int8_t, int16_t, int32_t, int64_t)) {
- CHECK_EQ(fn(125, 250, 500, 1000), 625);
+ const int64_t result = fn(125, 250, 500, 1000);
+ std::cout << "result " << result << "\n";
+ CHECK_EQ(result, 625);
CHECK_EQ(0x7FFFFFFFFFFFFFFFLL, fn(0, 0, 0, 0x7FFFFFFFFFFFFFFFLL));
CHECK_EQ(((int64_t)-0x8000000000000000LL),
fn(0, 0, 0, -0x8000000000000000LL));
diff --git a/runtime/bin/ffi_test/ffi_test_functions_generated.cc b/runtime/bin/ffi_test/ffi_test_functions_generated.cc
new file mode 100644
index 0000000..9c9789f
--- /dev/null
+++ b/runtime/bin/ffi_test/ffi_test_functions_generated.cc
@@ -0,0 +1,8375 @@
+// Copyright (c) 2020, 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.
+//
+// This file has been automatically generated. Please do not edit it manually.
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include <cmath>
+#include <iostream>
+#include <limits>
+
+#if defined(_WIN32)
+#define DART_EXPORT extern "C" __declspec(dllexport)
+#else
+#define DART_EXPORT \
+ extern "C" __attribute__((visibility("default"))) __attribute((used))
+#endif
+
+namespace dart {
+
+#define CHECK(X) \
+ if (!(X)) { \
+ fprintf(stderr, "%s\n", "Check failed: " #X); \
+ return 1; \
+ }
+
+#define CHECK_EQ(X, Y) CHECK((X) == (Y))
+
+// Works for positive, negative and zero.
+#define CHECK_APPROX(EXPECTED, ACTUAL) \
+ CHECK(((EXPECTED * 0.99) <= (ACTUAL) && (EXPECTED * 1.01) >= (ACTUAL)) || \
+ ((EXPECTED * 0.99) >= (ACTUAL) && (EXPECTED * 1.01) <= (ACTUAL)))
+
+struct Struct0Bytes {};
+
+struct Struct1ByteInt {
+ int8_t a0;
+};
+
+struct Struct3BytesInt {
+ int16_t a0;
+ int8_t a1;
+};
+
+struct Struct4BytesHomogeneousInt16 {
+ int16_t a0;
+ int16_t a1;
+};
+
+struct Struct7BytesInt {
+ int32_t a0;
+ int16_t a1;
+ int8_t a2;
+};
+
+struct Struct8BytesInt {
+ int16_t a0;
+ int16_t a1;
+ int32_t a2;
+};
+
+struct Struct8BytesHomogeneousFloat {
+ float a0;
+ float a1;
+};
+
+struct Struct8BytesMixed {
+ float a0;
+ int16_t a1;
+ int16_t a2;
+};
+
+struct Struct9BytesInt {
+ int64_t a0;
+ int8_t a1;
+};
+
+struct Struct9BytesHomogeneousUint82 {
+ uint8_t a0;
+ uint8_t a1;
+ uint8_t a2;
+ uint8_t a3;
+ uint8_t a4;
+ uint8_t a5;
+ uint8_t a6;
+ uint8_t a7;
+ uint8_t a8;
+};
+
+struct Struct12BytesHomogeneousFloat {
+ float a0;
+ float a1;
+ float a2;
+};
+
+struct Struct16BytesHomogeneousFloat {
+ float a0;
+ float a1;
+ float a2;
+ float a3;
+};
+
+struct Struct16BytesMixed {
+ double a0;
+ int64_t a1;
+};
+
+struct Struct16BytesMixed2 {
+ float a0;
+ float a1;
+ float a2;
+ int32_t a3;
+};
+
+struct Struct17BytesInt {
+ int64_t a0;
+ int64_t a1;
+ int8_t a2;
+};
+
+struct Struct19BytesHomogeneousUint8 {
+ uint8_t a0;
+ uint8_t a1;
+ uint8_t a2;
+ uint8_t a3;
+ uint8_t a4;
+ uint8_t a5;
+ uint8_t a6;
+ uint8_t a7;
+ uint8_t a8;
+ uint8_t a9;
+ uint8_t a10;
+ uint8_t a11;
+ uint8_t a12;
+ uint8_t a13;
+ uint8_t a14;
+ uint8_t a15;
+ uint8_t a16;
+ uint8_t a17;
+ uint8_t a18;
+};
+
+struct Struct20BytesHomogeneousInt32 {
+ int32_t a0;
+ int32_t a1;
+ int32_t a2;
+ int32_t a3;
+ int32_t a4;
+};
+
+struct Struct20BytesHomogeneousFloat {
+ float a0;
+ float a1;
+ float a2;
+ float a3;
+ float a4;
+};
+
+struct Struct32BytesHomogeneousDouble {
+ double a0;
+ double a1;
+ double a2;
+ double a3;
+};
+
+struct Struct40BytesHomogeneousDouble {
+ double a0;
+ double a1;
+ double a2;
+ double a3;
+ double a4;
+};
+
+struct Struct1024BytesHomogeneousUint64 {
+ uint64_t a0;
+ uint64_t a1;
+ uint64_t a2;
+ uint64_t a3;
+ uint64_t a4;
+ uint64_t a5;
+ uint64_t a6;
+ uint64_t a7;
+ uint64_t a8;
+ uint64_t a9;
+ uint64_t a10;
+ uint64_t a11;
+ uint64_t a12;
+ uint64_t a13;
+ uint64_t a14;
+ uint64_t a15;
+ uint64_t a16;
+ uint64_t a17;
+ uint64_t a18;
+ uint64_t a19;
+ uint64_t a20;
+ uint64_t a21;
+ uint64_t a22;
+ uint64_t a23;
+ uint64_t a24;
+ uint64_t a25;
+ uint64_t a26;
+ uint64_t a27;
+ uint64_t a28;
+ uint64_t a29;
+ uint64_t a30;
+ uint64_t a31;
+ uint64_t a32;
+ uint64_t a33;
+ uint64_t a34;
+ uint64_t a35;
+ uint64_t a36;
+ uint64_t a37;
+ uint64_t a38;
+ uint64_t a39;
+ uint64_t a40;
+ uint64_t a41;
+ uint64_t a42;
+ uint64_t a43;
+ uint64_t a44;
+ uint64_t a45;
+ uint64_t a46;
+ uint64_t a47;
+ uint64_t a48;
+ uint64_t a49;
+ uint64_t a50;
+ uint64_t a51;
+ uint64_t a52;
+ uint64_t a53;
+ uint64_t a54;
+ uint64_t a55;
+ uint64_t a56;
+ uint64_t a57;
+ uint64_t a58;
+ uint64_t a59;
+ uint64_t a60;
+ uint64_t a61;
+ uint64_t a62;
+ uint64_t a63;
+ uint64_t a64;
+ uint64_t a65;
+ uint64_t a66;
+ uint64_t a67;
+ uint64_t a68;
+ uint64_t a69;
+ uint64_t a70;
+ uint64_t a71;
+ uint64_t a72;
+ uint64_t a73;
+ uint64_t a74;
+ uint64_t a75;
+ uint64_t a76;
+ uint64_t a77;
+ uint64_t a78;
+ uint64_t a79;
+ uint64_t a80;
+ uint64_t a81;
+ uint64_t a82;
+ uint64_t a83;
+ uint64_t a84;
+ uint64_t a85;
+ uint64_t a86;
+ uint64_t a87;
+ uint64_t a88;
+ uint64_t a89;
+ uint64_t a90;
+ uint64_t a91;
+ uint64_t a92;
+ uint64_t a93;
+ uint64_t a94;
+ uint64_t a95;
+ uint64_t a96;
+ uint64_t a97;
+ uint64_t a98;
+ uint64_t a99;
+ uint64_t a100;
+ uint64_t a101;
+ uint64_t a102;
+ uint64_t a103;
+ uint64_t a104;
+ uint64_t a105;
+ uint64_t a106;
+ uint64_t a107;
+ uint64_t a108;
+ uint64_t a109;
+ uint64_t a110;
+ uint64_t a111;
+ uint64_t a112;
+ uint64_t a113;
+ uint64_t a114;
+ uint64_t a115;
+ uint64_t a116;
+ uint64_t a117;
+ uint64_t a118;
+ uint64_t a119;
+ uint64_t a120;
+ uint64_t a121;
+ uint64_t a122;
+ uint64_t a123;
+ uint64_t a124;
+ uint64_t a125;
+ uint64_t a126;
+ uint64_t a127;
+};
+
+struct StructAlignmentInt16 {
+ int8_t a0;
+ int16_t a1;
+ int8_t a2;
+};
+
+struct StructAlignmentInt32 {
+ int8_t a0;
+ int32_t a1;
+ int8_t a2;
+};
+
+struct StructAlignmentInt64 {
+ int8_t a0;
+ int64_t a1;
+ int8_t a2;
+};
+
+// Used for testing structs by value.
+// Smallest struct with data.
+// 10 struct arguments will exhaust available registers.
+DART_EXPORT int64_t PassStruct1ByteIntx10(Struct1ByteInt a0,
+ Struct1ByteInt a1,
+ Struct1ByteInt a2,
+ Struct1ByteInt a3,
+ Struct1ByteInt a4,
+ Struct1ByteInt a5,
+ Struct1ByteInt a6,
+ Struct1ByteInt a7,
+ Struct1ByteInt a8,
+ Struct1ByteInt a9) {
+ std::cout << "PassStruct1ByteIntx10"
+ << "((" << static_cast<int>(a0.a0) << "), ("
+ << static_cast<int>(a1.a0) << "), (" << static_cast<int>(a2.a0)
+ << "), (" << static_cast<int>(a3.a0) << "), ("
+ << static_cast<int>(a4.a0) << "), (" << static_cast<int>(a5.a0)
+ << "), (" << static_cast<int>(a6.a0) << "), ("
+ << static_cast<int>(a7.a0) << "), (" << static_cast<int>(a8.a0)
+ << "), (" << static_cast<int>(a9.a0) << "))"
+ << "\n";
+
+ int64_t result = 0;
+
+ result += a0.a0;
+ result += a1.a0;
+ result += a2.a0;
+ result += a3.a0;
+ result += a4.a0;
+ result += a5.a0;
+ result += a6.a0;
+ result += a7.a0;
+ result += a8.a0;
+ result += a9.a0;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Not a multiple of word size, not a power of two.
+// 10 struct arguments will exhaust available registers.
+DART_EXPORT int64_t PassStruct3BytesIntx10(Struct3BytesInt a0,
+ Struct3BytesInt a1,
+ Struct3BytesInt a2,
+ Struct3BytesInt a3,
+ Struct3BytesInt a4,
+ Struct3BytesInt a5,
+ Struct3BytesInt a6,
+ Struct3BytesInt a7,
+ Struct3BytesInt a8,
+ Struct3BytesInt a9) {
+ std::cout << "PassStruct3BytesIntx10"
+ << "((" << a0.a0 << ", " << static_cast<int>(a0.a1) << "), ("
+ << a1.a0 << ", " << static_cast<int>(a1.a1) << "), (" << a2.a0
+ << ", " << static_cast<int>(a2.a1) << "), (" << a3.a0 << ", "
+ << static_cast<int>(a3.a1) << "), (" << a4.a0 << ", "
+ << static_cast<int>(a4.a1) << "), (" << a5.a0 << ", "
+ << static_cast<int>(a5.a1) << "), (" << a6.a0 << ", "
+ << static_cast<int>(a6.a1) << "), (" << a7.a0 << ", "
+ << static_cast<int>(a7.a1) << "), (" << a8.a0 << ", "
+ << static_cast<int>(a8.a1) << "), (" << a9.a0 << ", "
+ << static_cast<int>(a9.a1) << "))"
+ << "\n";
+
+ int64_t result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a1.a0;
+ result += a1.a1;
+ result += a2.a0;
+ result += a2.a1;
+ result += a3.a0;
+ result += a3.a1;
+ result += a4.a0;
+ result += a4.a1;
+ result += a5.a0;
+ result += a5.a1;
+ result += a6.a0;
+ result += a6.a1;
+ result += a7.a0;
+ result += a7.a1;
+ result += a8.a0;
+ result += a8.a1;
+ result += a9.a0;
+ result += a9.a1;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Exactly word size on 32-bit architectures.
+// 10 struct arguments will exhaust available registers.
+DART_EXPORT int64_t
+PassStruct4BytesHomogeneousInt16x10(Struct4BytesHomogeneousInt16 a0,
+ Struct4BytesHomogeneousInt16 a1,
+ Struct4BytesHomogeneousInt16 a2,
+ Struct4BytesHomogeneousInt16 a3,
+ Struct4BytesHomogeneousInt16 a4,
+ Struct4BytesHomogeneousInt16 a5,
+ Struct4BytesHomogeneousInt16 a6,
+ Struct4BytesHomogeneousInt16 a7,
+ Struct4BytesHomogeneousInt16 a8,
+ Struct4BytesHomogeneousInt16 a9) {
+ std::cout << "PassStruct4BytesHomogeneousInt16x10"
+ << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << ", "
+ << a1.a1 << "), (" << a2.a0 << ", " << a2.a1 << "), (" << a3.a0
+ << ", " << a3.a1 << "), (" << a4.a0 << ", " << a4.a1 << "), ("
+ << a5.a0 << ", " << a5.a1 << "), (" << a6.a0 << ", " << a6.a1
+ << "), (" << a7.a0 << ", " << a7.a1 << "), (" << a8.a0 << ", "
+ << a8.a1 << "), (" << a9.a0 << ", " << a9.a1 << "))"
+ << "\n";
+
+ int64_t result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a1.a0;
+ result += a1.a1;
+ result += a2.a0;
+ result += a2.a1;
+ result += a3.a0;
+ result += a3.a1;
+ result += a4.a0;
+ result += a4.a1;
+ result += a5.a0;
+ result += a5.a1;
+ result += a6.a0;
+ result += a6.a1;
+ result += a7.a0;
+ result += a7.a1;
+ result += a8.a0;
+ result += a8.a1;
+ result += a9.a0;
+ result += a9.a1;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Sub word size on 64 bit architectures.
+// 10 struct arguments will exhaust available registers.
+DART_EXPORT int64_t PassStruct7BytesIntx10(Struct7BytesInt a0,
+ Struct7BytesInt a1,
+ Struct7BytesInt a2,
+ Struct7BytesInt a3,
+ Struct7BytesInt a4,
+ Struct7BytesInt a5,
+ Struct7BytesInt a6,
+ Struct7BytesInt a7,
+ Struct7BytesInt a8,
+ Struct7BytesInt a9) {
+ std::cout << "PassStruct7BytesIntx10"
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << static_cast<int>(a0.a2)
+ << "), (" << a1.a0 << ", " << a1.a1 << ", "
+ << static_cast<int>(a1.a2) << "), (" << a2.a0 << ", " << a2.a1
+ << ", " << static_cast<int>(a2.a2) << "), (" << a3.a0 << ", "
+ << a3.a1 << ", " << static_cast<int>(a3.a2) << "), (" << a4.a0
+ << ", " << a4.a1 << ", " << static_cast<int>(a4.a2) << "), ("
+ << a5.a0 << ", " << a5.a1 << ", " << static_cast<int>(a5.a2)
+ << "), (" << a6.a0 << ", " << a6.a1 << ", "
+ << static_cast<int>(a6.a2) << "), (" << a7.a0 << ", " << a7.a1
+ << ", " << static_cast<int>(a7.a2) << "), (" << a8.a0 << ", "
+ << a8.a1 << ", " << static_cast<int>(a8.a2) << "), (" << a9.a0
+ << ", " << a9.a1 << ", " << static_cast<int>(a9.a2) << "))"
+ << "\n";
+
+ int64_t result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a0.a2;
+ result += a1.a0;
+ result += a1.a1;
+ result += a1.a2;
+ result += a2.a0;
+ result += a2.a1;
+ result += a2.a2;
+ result += a3.a0;
+ result += a3.a1;
+ result += a3.a2;
+ result += a4.a0;
+ result += a4.a1;
+ result += a4.a2;
+ result += a5.a0;
+ result += a5.a1;
+ result += a5.a2;
+ result += a6.a0;
+ result += a6.a1;
+ result += a6.a2;
+ result += a7.a0;
+ result += a7.a1;
+ result += a7.a2;
+ result += a8.a0;
+ result += a8.a1;
+ result += a8.a2;
+ result += a9.a0;
+ result += a9.a1;
+ result += a9.a2;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Exactly word size struct on 64bit architectures.
+// 10 struct arguments will exhaust available registers.
+DART_EXPORT int64_t PassStruct8BytesIntx10(Struct8BytesInt a0,
+ Struct8BytesInt a1,
+ Struct8BytesInt a2,
+ Struct8BytesInt a3,
+ Struct8BytesInt a4,
+ Struct8BytesInt a5,
+ Struct8BytesInt a6,
+ Struct8BytesInt a7,
+ Struct8BytesInt a8,
+ Struct8BytesInt a9) {
+ std::cout << "PassStruct8BytesIntx10"
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << "), ("
+ << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << "), (" << a2.a0
+ << ", " << a2.a1 << ", " << a2.a2 << "), (" << a3.a0 << ", "
+ << a3.a1 << ", " << a3.a2 << "), (" << a4.a0 << ", " << a4.a1
+ << ", " << a4.a2 << "), (" << a5.a0 << ", " << a5.a1 << ", "
+ << a5.a2 << "), (" << a6.a0 << ", " << a6.a1 << ", " << a6.a2
+ << "), (" << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << "), ("
+ << a8.a0 << ", " << a8.a1 << ", " << a8.a2 << "), (" << a9.a0
+ << ", " << a9.a1 << ", " << a9.a2 << "))"
+ << "\n";
+
+ int64_t result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a0.a2;
+ result += a1.a0;
+ result += a1.a1;
+ result += a1.a2;
+ result += a2.a0;
+ result += a2.a1;
+ result += a2.a2;
+ result += a3.a0;
+ result += a3.a1;
+ result += a3.a2;
+ result += a4.a0;
+ result += a4.a1;
+ result += a4.a2;
+ result += a5.a0;
+ result += a5.a1;
+ result += a5.a2;
+ result += a6.a0;
+ result += a6.a1;
+ result += a6.a2;
+ result += a7.a0;
+ result += a7.a1;
+ result += a7.a2;
+ result += a8.a0;
+ result += a8.a1;
+ result += a8.a2;
+ result += a9.a0;
+ result += a9.a1;
+ result += a9.a2;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Arguments passed in FP registers as long as they fit.
+// 10 struct arguments will exhaust available registers.
+DART_EXPORT float PassStruct8BytesHomogeneousFloatx10(
+ Struct8BytesHomogeneousFloat a0,
+ Struct8BytesHomogeneousFloat a1,
+ Struct8BytesHomogeneousFloat a2,
+ Struct8BytesHomogeneousFloat a3,
+ Struct8BytesHomogeneousFloat a4,
+ Struct8BytesHomogeneousFloat a5,
+ Struct8BytesHomogeneousFloat a6,
+ Struct8BytesHomogeneousFloat a7,
+ Struct8BytesHomogeneousFloat a8,
+ Struct8BytesHomogeneousFloat a9) {
+ std::cout << "PassStruct8BytesHomogeneousFloatx10"
+ << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << ", "
+ << a1.a1 << "), (" << a2.a0 << ", " << a2.a1 << "), (" << a3.a0
+ << ", " << a3.a1 << "), (" << a4.a0 << ", " << a4.a1 << "), ("
+ << a5.a0 << ", " << a5.a1 << "), (" << a6.a0 << ", " << a6.a1
+ << "), (" << a7.a0 << ", " << a7.a1 << "), (" << a8.a0 << ", "
+ << a8.a1 << "), (" << a9.a0 << ", " << a9.a1 << "))"
+ << "\n";
+
+ float result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a1.a0;
+ result += a1.a1;
+ result += a2.a0;
+ result += a2.a1;
+ result += a3.a0;
+ result += a3.a1;
+ result += a4.a0;
+ result += a4.a1;
+ result += a5.a0;
+ result += a5.a1;
+ result += a6.a0;
+ result += a6.a1;
+ result += a7.a0;
+ result += a7.a1;
+ result += a8.a0;
+ result += a8.a1;
+ result += a9.a0;
+ result += a9.a1;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// On x64, arguments go in int registers because it is not only float.
+// 10 struct arguments will exhaust available registers.
+DART_EXPORT float PassStruct8BytesMixedx10(Struct8BytesMixed a0,
+ Struct8BytesMixed a1,
+ Struct8BytesMixed a2,
+ Struct8BytesMixed a3,
+ Struct8BytesMixed a4,
+ Struct8BytesMixed a5,
+ Struct8BytesMixed a6,
+ Struct8BytesMixed a7,
+ Struct8BytesMixed a8,
+ Struct8BytesMixed a9) {
+ std::cout << "PassStruct8BytesMixedx10"
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << "), ("
+ << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << "), (" << a2.a0
+ << ", " << a2.a1 << ", " << a2.a2 << "), (" << a3.a0 << ", "
+ << a3.a1 << ", " << a3.a2 << "), (" << a4.a0 << ", " << a4.a1
+ << ", " << a4.a2 << "), (" << a5.a0 << ", " << a5.a1 << ", "
+ << a5.a2 << "), (" << a6.a0 << ", " << a6.a1 << ", " << a6.a2
+ << "), (" << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << "), ("
+ << a8.a0 << ", " << a8.a1 << ", " << a8.a2 << "), (" << a9.a0
+ << ", " << a9.a1 << ", " << a9.a2 << "))"
+ << "\n";
+
+ float result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a0.a2;
+ result += a1.a0;
+ result += a1.a1;
+ result += a1.a2;
+ result += a2.a0;
+ result += a2.a1;
+ result += a2.a2;
+ result += a3.a0;
+ result += a3.a1;
+ result += a3.a2;
+ result += a4.a0;
+ result += a4.a1;
+ result += a4.a2;
+ result += a5.a0;
+ result += a5.a1;
+ result += a5.a2;
+ result += a6.a0;
+ result += a6.a1;
+ result += a6.a2;
+ result += a7.a0;
+ result += a7.a1;
+ result += a7.a2;
+ result += a8.a0;
+ result += a8.a1;
+ result += a8.a2;
+ result += a9.a0;
+ result += a9.a1;
+ result += a9.a2;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Argument is a single byte over a multiple of word size.
+// 10 struct arguments will exhaust available registers.
+// Tests upper bytes in the integer registers that are partly filled.
+// Tests stack alignment of non word size stack arguments.
+DART_EXPORT int64_t PassStruct9BytesIntx10(Struct9BytesInt a0,
+ Struct9BytesInt a1,
+ Struct9BytesInt a2,
+ Struct9BytesInt a3,
+ Struct9BytesInt a4,
+ Struct9BytesInt a5,
+ Struct9BytesInt a6,
+ Struct9BytesInt a7,
+ Struct9BytesInt a8,
+ Struct9BytesInt a9) {
+ std::cout << "PassStruct9BytesIntx10"
+ << "((" << a0.a0 << ", " << static_cast<int>(a0.a1) << "), ("
+ << a1.a0 << ", " << static_cast<int>(a1.a1) << "), (" << a2.a0
+ << ", " << static_cast<int>(a2.a1) << "), (" << a3.a0 << ", "
+ << static_cast<int>(a3.a1) << "), (" << a4.a0 << ", "
+ << static_cast<int>(a4.a1) << "), (" << a5.a0 << ", "
+ << static_cast<int>(a5.a1) << "), (" << a6.a0 << ", "
+ << static_cast<int>(a6.a1) << "), (" << a7.a0 << ", "
+ << static_cast<int>(a7.a1) << "), (" << a8.a0 << ", "
+ << static_cast<int>(a8.a1) << "), (" << a9.a0 << ", "
+ << static_cast<int>(a9.a1) << "))"
+ << "\n";
+
+ int64_t result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a1.a0;
+ result += a1.a1;
+ result += a2.a0;
+ result += a2.a1;
+ result += a3.a0;
+ result += a3.a1;
+ result += a4.a0;
+ result += a4.a1;
+ result += a5.a0;
+ result += a5.a1;
+ result += a6.a0;
+ result += a6.a1;
+ result += a7.a0;
+ result += a7.a1;
+ result += a8.a0;
+ result += a8.a1;
+ result += a9.a0;
+ result += a9.a1;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Argument is a single byte over a multiple of word size.
+// 10 struct arguments will exhaust available registers.
+// Struct only has 1-byte aligned fields to test struct alignment itself.
+//
+DART_EXPORT int64_t
+PassStruct9BytesHomogeneousUint82x10(Struct9BytesHomogeneousUint82 a0,
+ Struct9BytesHomogeneousUint82 a1,
+ Struct9BytesHomogeneousUint82 a2,
+ Struct9BytesHomogeneousUint82 a3,
+ Struct9BytesHomogeneousUint82 a4,
+ Struct9BytesHomogeneousUint82 a5,
+ Struct9BytesHomogeneousUint82 a6,
+ Struct9BytesHomogeneousUint82 a7,
+ Struct9BytesHomogeneousUint82 a8,
+ Struct9BytesHomogeneousUint82 a9) {
+ std::cout
+ << "PassStruct9BytesHomogeneousUint82x10"
+ << "((" << static_cast<int>(a0.a0) << ", " << static_cast<int>(a0.a1)
+ << ", " << static_cast<int>(a0.a2) << ", " << static_cast<int>(a0.a3)
+ << ", " << static_cast<int>(a0.a4) << ", " << static_cast<int>(a0.a5)
+ << ", " << static_cast<int>(a0.a6) << ", " << static_cast<int>(a0.a7)
+ << ", " << static_cast<int>(a0.a8) << "), (" << static_cast<int>(a1.a0)
+ << ", " << static_cast<int>(a1.a1) << ", " << static_cast<int>(a1.a2)
+ << ", " << static_cast<int>(a1.a3) << ", " << static_cast<int>(a1.a4)
+ << ", " << static_cast<int>(a1.a5) << ", " << static_cast<int>(a1.a6)
+ << ", " << static_cast<int>(a1.a7) << ", " << static_cast<int>(a1.a8)
+ << "), (" << static_cast<int>(a2.a0) << ", " << static_cast<int>(a2.a1)
+ << ", " << static_cast<int>(a2.a2) << ", " << static_cast<int>(a2.a3)
+ << ", " << static_cast<int>(a2.a4) << ", " << static_cast<int>(a2.a5)
+ << ", " << static_cast<int>(a2.a6) << ", " << static_cast<int>(a2.a7)
+ << ", " << static_cast<int>(a2.a8) << "), (" << static_cast<int>(a3.a0)
+ << ", " << static_cast<int>(a3.a1) << ", " << static_cast<int>(a3.a2)
+ << ", " << static_cast<int>(a3.a3) << ", " << static_cast<int>(a3.a4)
+ << ", " << static_cast<int>(a3.a5) << ", " << static_cast<int>(a3.a6)
+ << ", " << static_cast<int>(a3.a7) << ", " << static_cast<int>(a3.a8)
+ << "), (" << static_cast<int>(a4.a0) << ", " << static_cast<int>(a4.a1)
+ << ", " << static_cast<int>(a4.a2) << ", " << static_cast<int>(a4.a3)
+ << ", " << static_cast<int>(a4.a4) << ", " << static_cast<int>(a4.a5)
+ << ", " << static_cast<int>(a4.a6) << ", " << static_cast<int>(a4.a7)
+ << ", " << static_cast<int>(a4.a8) << "), (" << static_cast<int>(a5.a0)
+ << ", " << static_cast<int>(a5.a1) << ", " << static_cast<int>(a5.a2)
+ << ", " << static_cast<int>(a5.a3) << ", " << static_cast<int>(a5.a4)
+ << ", " << static_cast<int>(a5.a5) << ", " << static_cast<int>(a5.a6)
+ << ", " << static_cast<int>(a5.a7) << ", " << static_cast<int>(a5.a8)
+ << "), (" << static_cast<int>(a6.a0) << ", " << static_cast<int>(a6.a1)
+ << ", " << static_cast<int>(a6.a2) << ", " << static_cast<int>(a6.a3)
+ << ", " << static_cast<int>(a6.a4) << ", " << static_cast<int>(a6.a5)
+ << ", " << static_cast<int>(a6.a6) << ", " << static_cast<int>(a6.a7)
+ << ", " << static_cast<int>(a6.a8) << "), (" << static_cast<int>(a7.a0)
+ << ", " << static_cast<int>(a7.a1) << ", " << static_cast<int>(a7.a2)
+ << ", " << static_cast<int>(a7.a3) << ", " << static_cast<int>(a7.a4)
+ << ", " << static_cast<int>(a7.a5) << ", " << static_cast<int>(a7.a6)
+ << ", " << static_cast<int>(a7.a7) << ", " << static_cast<int>(a7.a8)
+ << "), (" << static_cast<int>(a8.a0) << ", " << static_cast<int>(a8.a1)
+ << ", " << static_cast<int>(a8.a2) << ", " << static_cast<int>(a8.a3)
+ << ", " << static_cast<int>(a8.a4) << ", " << static_cast<int>(a8.a5)
+ << ", " << static_cast<int>(a8.a6) << ", " << static_cast<int>(a8.a7)
+ << ", " << static_cast<int>(a8.a8) << "), (" << static_cast<int>(a9.a0)
+ << ", " << static_cast<int>(a9.a1) << ", " << static_cast<int>(a9.a2)
+ << ", " << static_cast<int>(a9.a3) << ", " << static_cast<int>(a9.a4)
+ << ", " << static_cast<int>(a9.a5) << ", " << static_cast<int>(a9.a6)
+ << ", " << static_cast<int>(a9.a7) << ", " << static_cast<int>(a9.a8)
+ << "))"
+ << "\n";
+
+ int64_t result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a0.a2;
+ result += a0.a3;
+ result += a0.a4;
+ result += a0.a5;
+ result += a0.a6;
+ result += a0.a7;
+ result += a0.a8;
+ result += a1.a0;
+ result += a1.a1;
+ result += a1.a2;
+ result += a1.a3;
+ result += a1.a4;
+ result += a1.a5;
+ result += a1.a6;
+ result += a1.a7;
+ result += a1.a8;
+ result += a2.a0;
+ result += a2.a1;
+ result += a2.a2;
+ result += a2.a3;
+ result += a2.a4;
+ result += a2.a5;
+ result += a2.a6;
+ result += a2.a7;
+ result += a2.a8;
+ result += a3.a0;
+ result += a3.a1;
+ result += a3.a2;
+ result += a3.a3;
+ result += a3.a4;
+ result += a3.a5;
+ result += a3.a6;
+ result += a3.a7;
+ result += a3.a8;
+ result += a4.a0;
+ result += a4.a1;
+ result += a4.a2;
+ result += a4.a3;
+ result += a4.a4;
+ result += a4.a5;
+ result += a4.a6;
+ result += a4.a7;
+ result += a4.a8;
+ result += a5.a0;
+ result += a5.a1;
+ result += a5.a2;
+ result += a5.a3;
+ result += a5.a4;
+ result += a5.a5;
+ result += a5.a6;
+ result += a5.a7;
+ result += a5.a8;
+ result += a6.a0;
+ result += a6.a1;
+ result += a6.a2;
+ result += a6.a3;
+ result += a6.a4;
+ result += a6.a5;
+ result += a6.a6;
+ result += a6.a7;
+ result += a6.a8;
+ result += a7.a0;
+ result += a7.a1;
+ result += a7.a2;
+ result += a7.a3;
+ result += a7.a4;
+ result += a7.a5;
+ result += a7.a6;
+ result += a7.a7;
+ result += a7.a8;
+ result += a8.a0;
+ result += a8.a1;
+ result += a8.a2;
+ result += a8.a3;
+ result += a8.a4;
+ result += a8.a5;
+ result += a8.a6;
+ result += a8.a7;
+ result += a8.a8;
+ result += a9.a0;
+ result += a9.a1;
+ result += a9.a2;
+ result += a9.a3;
+ result += a9.a4;
+ result += a9.a5;
+ result += a9.a6;
+ result += a9.a7;
+ result += a9.a8;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Arguments in FPU registers on arm hardfp and arm64.
+// Struct arguments will exhaust available registers, and leave some empty.
+// The last argument is to test whether arguments are backfilled.
+DART_EXPORT float PassStruct12BytesHomogeneousFloatx6(
+ Struct12BytesHomogeneousFloat a0,
+ Struct12BytesHomogeneousFloat a1,
+ Struct12BytesHomogeneousFloat a2,
+ Struct12BytesHomogeneousFloat a3,
+ Struct12BytesHomogeneousFloat a4,
+ Struct12BytesHomogeneousFloat a5) {
+ std::cout << "PassStruct12BytesHomogeneousFloatx6"
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << "), ("
+ << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << "), (" << a2.a0
+ << ", " << a2.a1 << ", " << a2.a2 << "), (" << a3.a0 << ", "
+ << a3.a1 << ", " << a3.a2 << "), (" << a4.a0 << ", " << a4.a1
+ << ", " << a4.a2 << "), (" << a5.a0 << ", " << a5.a1 << ", "
+ << a5.a2 << "))"
+ << "\n";
+
+ float result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a0.a2;
+ result += a1.a0;
+ result += a1.a1;
+ result += a1.a2;
+ result += a2.a0;
+ result += a2.a1;
+ result += a2.a2;
+ result += a3.a0;
+ result += a3.a1;
+ result += a3.a2;
+ result += a4.a0;
+ result += a4.a1;
+ result += a4.a2;
+ result += a5.a0;
+ result += a5.a1;
+ result += a5.a2;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// On Linux x64 argument is transferred on stack because it is over 16 bytes.
+// Arguments in FPU registers on arm hardfp and arm64.
+// 5 struct arguments will exhaust available registers.
+DART_EXPORT float PassStruct16BytesHomogeneousFloatx5(
+ Struct16BytesHomogeneousFloat a0,
+ Struct16BytesHomogeneousFloat a1,
+ Struct16BytesHomogeneousFloat a2,
+ Struct16BytesHomogeneousFloat a3,
+ Struct16BytesHomogeneousFloat a4) {
+ std::cout << "PassStruct16BytesHomogeneousFloatx5"
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3
+ << "), (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << ", "
+ << a1.a3 << "), (" << a2.a0 << ", " << a2.a1 << ", " << a2.a2
+ << ", " << a2.a3 << "), (" << a3.a0 << ", " << a3.a1 << ", "
+ << a3.a2 << ", " << a3.a3 << "), (" << a4.a0 << ", " << a4.a1
+ << ", " << a4.a2 << ", " << a4.a3 << "))"
+ << "\n";
+
+ float result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a0.a2;
+ result += a0.a3;
+ result += a1.a0;
+ result += a1.a1;
+ result += a1.a2;
+ result += a1.a3;
+ result += a2.a0;
+ result += a2.a1;
+ result += a2.a2;
+ result += a2.a3;
+ result += a3.a0;
+ result += a3.a1;
+ result += a3.a2;
+ result += a3.a3;
+ result += a4.a0;
+ result += a4.a1;
+ result += a4.a2;
+ result += a4.a3;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// On x64, arguments are split over FP and int registers.
+// On x64, it will exhaust the integer registers with the 6th argument.
+// The rest goes on the stack.
+// On arm, arguments are 8 byte aligned.
+DART_EXPORT double PassStruct16BytesMixedx10(Struct16BytesMixed a0,
+ Struct16BytesMixed a1,
+ Struct16BytesMixed a2,
+ Struct16BytesMixed a3,
+ Struct16BytesMixed a4,
+ Struct16BytesMixed a5,
+ Struct16BytesMixed a6,
+ Struct16BytesMixed a7,
+ Struct16BytesMixed a8,
+ Struct16BytesMixed a9) {
+ std::cout << "PassStruct16BytesMixedx10"
+ << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << ", "
+ << a1.a1 << "), (" << a2.a0 << ", " << a2.a1 << "), (" << a3.a0
+ << ", " << a3.a1 << "), (" << a4.a0 << ", " << a4.a1 << "), ("
+ << a5.a0 << ", " << a5.a1 << "), (" << a6.a0 << ", " << a6.a1
+ << "), (" << a7.a0 << ", " << a7.a1 << "), (" << a8.a0 << ", "
+ << a8.a1 << "), (" << a9.a0 << ", " << a9.a1 << "))"
+ << "\n";
+
+ double result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a1.a0;
+ result += a1.a1;
+ result += a2.a0;
+ result += a2.a1;
+ result += a3.a0;
+ result += a3.a1;
+ result += a4.a0;
+ result += a4.a1;
+ result += a5.a0;
+ result += a5.a1;
+ result += a6.a0;
+ result += a6.a1;
+ result += a7.a0;
+ result += a7.a1;
+ result += a8.a0;
+ result += a8.a1;
+ result += a9.a0;
+ result += a9.a1;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// On x64, arguments are split over FP and int registers.
+// On x64, it will exhaust the integer registers with the 6th argument.
+// The rest goes on the stack.
+// On arm, arguments are 4 byte aligned.
+DART_EXPORT float PassStruct16BytesMixed2x10(Struct16BytesMixed2 a0,
+ Struct16BytesMixed2 a1,
+ Struct16BytesMixed2 a2,
+ Struct16BytesMixed2 a3,
+ Struct16BytesMixed2 a4,
+ Struct16BytesMixed2 a5,
+ Struct16BytesMixed2 a6,
+ Struct16BytesMixed2 a7,
+ Struct16BytesMixed2 a8,
+ Struct16BytesMixed2 a9) {
+ std::cout << "PassStruct16BytesMixed2x10"
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3
+ << "), (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << ", "
+ << a1.a3 << "), (" << a2.a0 << ", " << a2.a1 << ", " << a2.a2
+ << ", " << a2.a3 << "), (" << a3.a0 << ", " << a3.a1 << ", "
+ << a3.a2 << ", " << a3.a3 << "), (" << a4.a0 << ", " << a4.a1
+ << ", " << a4.a2 << ", " << a4.a3 << "), (" << a5.a0 << ", "
+ << a5.a1 << ", " << a5.a2 << ", " << a5.a3 << "), (" << a6.a0
+ << ", " << a6.a1 << ", " << a6.a2 << ", " << a6.a3 << "), ("
+ << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << ", " << a7.a3
+ << "), (" << a8.a0 << ", " << a8.a1 << ", " << a8.a2 << ", "
+ << a8.a3 << "), (" << a9.a0 << ", " << a9.a1 << ", " << a9.a2
+ << ", " << a9.a3 << "))"
+ << "\n";
+
+ float result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a0.a2;
+ result += a0.a3;
+ result += a1.a0;
+ result += a1.a1;
+ result += a1.a2;
+ result += a1.a3;
+ result += a2.a0;
+ result += a2.a1;
+ result += a2.a2;
+ result += a2.a3;
+ result += a3.a0;
+ result += a3.a1;
+ result += a3.a2;
+ result += a3.a3;
+ result += a4.a0;
+ result += a4.a1;
+ result += a4.a2;
+ result += a4.a3;
+ result += a5.a0;
+ result += a5.a1;
+ result += a5.a2;
+ result += a5.a3;
+ result += a6.a0;
+ result += a6.a1;
+ result += a6.a2;
+ result += a6.a3;
+ result += a7.a0;
+ result += a7.a1;
+ result += a7.a2;
+ result += a7.a3;
+ result += a8.a0;
+ result += a8.a1;
+ result += a8.a2;
+ result += a8.a3;
+ result += a9.a0;
+ result += a9.a1;
+ result += a9.a2;
+ result += a9.a3;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Arguments are passed as pointer to copy on arm64.
+// Tests that the memory allocated for copies are rounded up to word size.
+DART_EXPORT int64_t PassStruct17BytesIntx10(Struct17BytesInt a0,
+ Struct17BytesInt a1,
+ Struct17BytesInt a2,
+ Struct17BytesInt a3,
+ Struct17BytesInt a4,
+ Struct17BytesInt a5,
+ Struct17BytesInt a6,
+ Struct17BytesInt a7,
+ Struct17BytesInt a8,
+ Struct17BytesInt a9) {
+ std::cout << "PassStruct17BytesIntx10"
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << static_cast<int>(a0.a2)
+ << "), (" << a1.a0 << ", " << a1.a1 << ", "
+ << static_cast<int>(a1.a2) << "), (" << a2.a0 << ", " << a2.a1
+ << ", " << static_cast<int>(a2.a2) << "), (" << a3.a0 << ", "
+ << a3.a1 << ", " << static_cast<int>(a3.a2) << "), (" << a4.a0
+ << ", " << a4.a1 << ", " << static_cast<int>(a4.a2) << "), ("
+ << a5.a0 << ", " << a5.a1 << ", " << static_cast<int>(a5.a2)
+ << "), (" << a6.a0 << ", " << a6.a1 << ", "
+ << static_cast<int>(a6.a2) << "), (" << a7.a0 << ", " << a7.a1
+ << ", " << static_cast<int>(a7.a2) << "), (" << a8.a0 << ", "
+ << a8.a1 << ", " << static_cast<int>(a8.a2) << "), (" << a9.a0
+ << ", " << a9.a1 << ", " << static_cast<int>(a9.a2) << "))"
+ << "\n";
+
+ int64_t result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a0.a2;
+ result += a1.a0;
+ result += a1.a1;
+ result += a1.a2;
+ result += a2.a0;
+ result += a2.a1;
+ result += a2.a2;
+ result += a3.a0;
+ result += a3.a1;
+ result += a3.a2;
+ result += a4.a0;
+ result += a4.a1;
+ result += a4.a2;
+ result += a5.a0;
+ result += a5.a1;
+ result += a5.a2;
+ result += a6.a0;
+ result += a6.a1;
+ result += a6.a2;
+ result += a7.a0;
+ result += a7.a1;
+ result += a7.a2;
+ result += a8.a0;
+ result += a8.a1;
+ result += a8.a2;
+ result += a9.a0;
+ result += a9.a1;
+ result += a9.a2;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// The minimum alignment of this struct is only 1 byte based on its fields.
+// Test that the memory backing these structs is extended to the right size.
+//
+DART_EXPORT int64_t
+PassStruct19BytesHomogeneousUint8x10(Struct19BytesHomogeneousUint8 a0,
+ Struct19BytesHomogeneousUint8 a1,
+ Struct19BytesHomogeneousUint8 a2,
+ Struct19BytesHomogeneousUint8 a3,
+ Struct19BytesHomogeneousUint8 a4,
+ Struct19BytesHomogeneousUint8 a5,
+ Struct19BytesHomogeneousUint8 a6,
+ Struct19BytesHomogeneousUint8 a7,
+ Struct19BytesHomogeneousUint8 a8,
+ Struct19BytesHomogeneousUint8 a9) {
+ std::cout
+ << "PassStruct19BytesHomogeneousUint8x10"
+ << "((" << static_cast<int>(a0.a0) << ", " << static_cast<int>(a0.a1)
+ << ", " << static_cast<int>(a0.a2) << ", " << static_cast<int>(a0.a3)
+ << ", " << static_cast<int>(a0.a4) << ", " << static_cast<int>(a0.a5)
+ << ", " << static_cast<int>(a0.a6) << ", " << static_cast<int>(a0.a7)
+ << ", " << static_cast<int>(a0.a8) << ", " << static_cast<int>(a0.a9)
+ << ", " << static_cast<int>(a0.a10) << ", " << static_cast<int>(a0.a11)
+ << ", " << static_cast<int>(a0.a12) << ", " << static_cast<int>(a0.a13)
+ << ", " << static_cast<int>(a0.a14) << ", " << static_cast<int>(a0.a15)
+ << ", " << static_cast<int>(a0.a16) << ", " << static_cast<int>(a0.a17)
+ << ", " << static_cast<int>(a0.a18) << "), (" << static_cast<int>(a1.a0)
+ << ", " << static_cast<int>(a1.a1) << ", " << static_cast<int>(a1.a2)
+ << ", " << static_cast<int>(a1.a3) << ", " << static_cast<int>(a1.a4)
+ << ", " << static_cast<int>(a1.a5) << ", " << static_cast<int>(a1.a6)
+ << ", " << static_cast<int>(a1.a7) << ", " << static_cast<int>(a1.a8)
+ << ", " << static_cast<int>(a1.a9) << ", " << static_cast<int>(a1.a10)
+ << ", " << static_cast<int>(a1.a11) << ", " << static_cast<int>(a1.a12)
+ << ", " << static_cast<int>(a1.a13) << ", " << static_cast<int>(a1.a14)
+ << ", " << static_cast<int>(a1.a15) << ", " << static_cast<int>(a1.a16)
+ << ", " << static_cast<int>(a1.a17) << ", " << static_cast<int>(a1.a18)
+ << "), (" << static_cast<int>(a2.a0) << ", " << static_cast<int>(a2.a1)
+ << ", " << static_cast<int>(a2.a2) << ", " << static_cast<int>(a2.a3)
+ << ", " << static_cast<int>(a2.a4) << ", " << static_cast<int>(a2.a5)
+ << ", " << static_cast<int>(a2.a6) << ", " << static_cast<int>(a2.a7)
+ << ", " << static_cast<int>(a2.a8) << ", " << static_cast<int>(a2.a9)
+ << ", " << static_cast<int>(a2.a10) << ", " << static_cast<int>(a2.a11)
+ << ", " << static_cast<int>(a2.a12) << ", " << static_cast<int>(a2.a13)
+ << ", " << static_cast<int>(a2.a14) << ", " << static_cast<int>(a2.a15)
+ << ", " << static_cast<int>(a2.a16) << ", " << static_cast<int>(a2.a17)
+ << ", " << static_cast<int>(a2.a18) << "), (" << static_cast<int>(a3.a0)
+ << ", " << static_cast<int>(a3.a1) << ", " << static_cast<int>(a3.a2)
+ << ", " << static_cast<int>(a3.a3) << ", " << static_cast<int>(a3.a4)
+ << ", " << static_cast<int>(a3.a5) << ", " << static_cast<int>(a3.a6)
+ << ", " << static_cast<int>(a3.a7) << ", " << static_cast<int>(a3.a8)
+ << ", " << static_cast<int>(a3.a9) << ", " << static_cast<int>(a3.a10)
+ << ", " << static_cast<int>(a3.a11) << ", " << static_cast<int>(a3.a12)
+ << ", " << static_cast<int>(a3.a13) << ", " << static_cast<int>(a3.a14)
+ << ", " << static_cast<int>(a3.a15) << ", " << static_cast<int>(a3.a16)
+ << ", " << static_cast<int>(a3.a17) << ", " << static_cast<int>(a3.a18)
+ << "), (" << static_cast<int>(a4.a0) << ", " << static_cast<int>(a4.a1)
+ << ", " << static_cast<int>(a4.a2) << ", " << static_cast<int>(a4.a3)
+ << ", " << static_cast<int>(a4.a4) << ", " << static_cast<int>(a4.a5)
+ << ", " << static_cast<int>(a4.a6) << ", " << static_cast<int>(a4.a7)
+ << ", " << static_cast<int>(a4.a8) << ", " << static_cast<int>(a4.a9)
+ << ", " << static_cast<int>(a4.a10) << ", " << static_cast<int>(a4.a11)
+ << ", " << static_cast<int>(a4.a12) << ", " << static_cast<int>(a4.a13)
+ << ", " << static_cast<int>(a4.a14) << ", " << static_cast<int>(a4.a15)
+ << ", " << static_cast<int>(a4.a16) << ", " << static_cast<int>(a4.a17)
+ << ", " << static_cast<int>(a4.a18) << "), (" << static_cast<int>(a5.a0)
+ << ", " << static_cast<int>(a5.a1) << ", " << static_cast<int>(a5.a2)
+ << ", " << static_cast<int>(a5.a3) << ", " << static_cast<int>(a5.a4)
+ << ", " << static_cast<int>(a5.a5) << ", " << static_cast<int>(a5.a6)
+ << ", " << static_cast<int>(a5.a7) << ", " << static_cast<int>(a5.a8)
+ << ", " << static_cast<int>(a5.a9) << ", " << static_cast<int>(a5.a10)
+ << ", " << static_cast<int>(a5.a11) << ", " << static_cast<int>(a5.a12)
+ << ", " << static_cast<int>(a5.a13) << ", " << static_cast<int>(a5.a14)
+ << ", " << static_cast<int>(a5.a15) << ", " << static_cast<int>(a5.a16)
+ << ", " << static_cast<int>(a5.a17) << ", " << static_cast<int>(a5.a18)
+ << "), (" << static_cast<int>(a6.a0) << ", " << static_cast<int>(a6.a1)
+ << ", " << static_cast<int>(a6.a2) << ", " << static_cast<int>(a6.a3)
+ << ", " << static_cast<int>(a6.a4) << ", " << static_cast<int>(a6.a5)
+ << ", " << static_cast<int>(a6.a6) << ", " << static_cast<int>(a6.a7)
+ << ", " << static_cast<int>(a6.a8) << ", " << static_cast<int>(a6.a9)
+ << ", " << static_cast<int>(a6.a10) << ", " << static_cast<int>(a6.a11)
+ << ", " << static_cast<int>(a6.a12) << ", " << static_cast<int>(a6.a13)
+ << ", " << static_cast<int>(a6.a14) << ", " << static_cast<int>(a6.a15)
+ << ", " << static_cast<int>(a6.a16) << ", " << static_cast<int>(a6.a17)
+ << ", " << static_cast<int>(a6.a18) << "), (" << static_cast<int>(a7.a0)
+ << ", " << static_cast<int>(a7.a1) << ", " << static_cast<int>(a7.a2)
+ << ", " << static_cast<int>(a7.a3) << ", " << static_cast<int>(a7.a4)
+ << ", " << static_cast<int>(a7.a5) << ", " << static_cast<int>(a7.a6)
+ << ", " << static_cast<int>(a7.a7) << ", " << static_cast<int>(a7.a8)
+ << ", " << static_cast<int>(a7.a9) << ", " << static_cast<int>(a7.a10)
+ << ", " << static_cast<int>(a7.a11) << ", " << static_cast<int>(a7.a12)
+ << ", " << static_cast<int>(a7.a13) << ", " << static_cast<int>(a7.a14)
+ << ", " << static_cast<int>(a7.a15) << ", " << static_cast<int>(a7.a16)
+ << ", " << static_cast<int>(a7.a17) << ", " << static_cast<int>(a7.a18)
+ << "), (" << static_cast<int>(a8.a0) << ", " << static_cast<int>(a8.a1)
+ << ", " << static_cast<int>(a8.a2) << ", " << static_cast<int>(a8.a3)
+ << ", " << static_cast<int>(a8.a4) << ", " << static_cast<int>(a8.a5)
+ << ", " << static_cast<int>(a8.a6) << ", " << static_cast<int>(a8.a7)
+ << ", " << static_cast<int>(a8.a8) << ", " << static_cast<int>(a8.a9)
+ << ", " << static_cast<int>(a8.a10) << ", " << static_cast<int>(a8.a11)
+ << ", " << static_cast<int>(a8.a12) << ", " << static_cast<int>(a8.a13)
+ << ", " << static_cast<int>(a8.a14) << ", " << static_cast<int>(a8.a15)
+ << ", " << static_cast<int>(a8.a16) << ", " << static_cast<int>(a8.a17)
+ << ", " << static_cast<int>(a8.a18) << "), (" << static_cast<int>(a9.a0)
+ << ", " << static_cast<int>(a9.a1) << ", " << static_cast<int>(a9.a2)
+ << ", " << static_cast<int>(a9.a3) << ", " << static_cast<int>(a9.a4)
+ << ", " << static_cast<int>(a9.a5) << ", " << static_cast<int>(a9.a6)
+ << ", " << static_cast<int>(a9.a7) << ", " << static_cast<int>(a9.a8)
+ << ", " << static_cast<int>(a9.a9) << ", " << static_cast<int>(a9.a10)
+ << ", " << static_cast<int>(a9.a11) << ", " << static_cast<int>(a9.a12)
+ << ", " << static_cast<int>(a9.a13) << ", " << static_cast<int>(a9.a14)
+ << ", " << static_cast<int>(a9.a15) << ", " << static_cast<int>(a9.a16)
+ << ", " << static_cast<int>(a9.a17) << ", " << static_cast<int>(a9.a18)
+ << "))"
+ << "\n";
+
+ int64_t result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a0.a2;
+ result += a0.a3;
+ result += a0.a4;
+ result += a0.a5;
+ result += a0.a6;
+ result += a0.a7;
+ result += a0.a8;
+ result += a0.a9;
+ result += a0.a10;
+ result += a0.a11;
+ result += a0.a12;
+ result += a0.a13;
+ result += a0.a14;
+ result += a0.a15;
+ result += a0.a16;
+ result += a0.a17;
+ result += a0.a18;
+ result += a1.a0;
+ result += a1.a1;
+ result += a1.a2;
+ result += a1.a3;
+ result += a1.a4;
+ result += a1.a5;
+ result += a1.a6;
+ result += a1.a7;
+ result += a1.a8;
+ result += a1.a9;
+ result += a1.a10;
+ result += a1.a11;
+ result += a1.a12;
+ result += a1.a13;
+ result += a1.a14;
+ result += a1.a15;
+ result += a1.a16;
+ result += a1.a17;
+ result += a1.a18;
+ result += a2.a0;
+ result += a2.a1;
+ result += a2.a2;
+ result += a2.a3;
+ result += a2.a4;
+ result += a2.a5;
+ result += a2.a6;
+ result += a2.a7;
+ result += a2.a8;
+ result += a2.a9;
+ result += a2.a10;
+ result += a2.a11;
+ result += a2.a12;
+ result += a2.a13;
+ result += a2.a14;
+ result += a2.a15;
+ result += a2.a16;
+ result += a2.a17;
+ result += a2.a18;
+ result += a3.a0;
+ result += a3.a1;
+ result += a3.a2;
+ result += a3.a3;
+ result += a3.a4;
+ result += a3.a5;
+ result += a3.a6;
+ result += a3.a7;
+ result += a3.a8;
+ result += a3.a9;
+ result += a3.a10;
+ result += a3.a11;
+ result += a3.a12;
+ result += a3.a13;
+ result += a3.a14;
+ result += a3.a15;
+ result += a3.a16;
+ result += a3.a17;
+ result += a3.a18;
+ result += a4.a0;
+ result += a4.a1;
+ result += a4.a2;
+ result += a4.a3;
+ result += a4.a4;
+ result += a4.a5;
+ result += a4.a6;
+ result += a4.a7;
+ result += a4.a8;
+ result += a4.a9;
+ result += a4.a10;
+ result += a4.a11;
+ result += a4.a12;
+ result += a4.a13;
+ result += a4.a14;
+ result += a4.a15;
+ result += a4.a16;
+ result += a4.a17;
+ result += a4.a18;
+ result += a5.a0;
+ result += a5.a1;
+ result += a5.a2;
+ result += a5.a3;
+ result += a5.a4;
+ result += a5.a5;
+ result += a5.a6;
+ result += a5.a7;
+ result += a5.a8;
+ result += a5.a9;
+ result += a5.a10;
+ result += a5.a11;
+ result += a5.a12;
+ result += a5.a13;
+ result += a5.a14;
+ result += a5.a15;
+ result += a5.a16;
+ result += a5.a17;
+ result += a5.a18;
+ result += a6.a0;
+ result += a6.a1;
+ result += a6.a2;
+ result += a6.a3;
+ result += a6.a4;
+ result += a6.a5;
+ result += a6.a6;
+ result += a6.a7;
+ result += a6.a8;
+ result += a6.a9;
+ result += a6.a10;
+ result += a6.a11;
+ result += a6.a12;
+ result += a6.a13;
+ result += a6.a14;
+ result += a6.a15;
+ result += a6.a16;
+ result += a6.a17;
+ result += a6.a18;
+ result += a7.a0;
+ result += a7.a1;
+ result += a7.a2;
+ result += a7.a3;
+ result += a7.a4;
+ result += a7.a5;
+ result += a7.a6;
+ result += a7.a7;
+ result += a7.a8;
+ result += a7.a9;
+ result += a7.a10;
+ result += a7.a11;
+ result += a7.a12;
+ result += a7.a13;
+ result += a7.a14;
+ result += a7.a15;
+ result += a7.a16;
+ result += a7.a17;
+ result += a7.a18;
+ result += a8.a0;
+ result += a8.a1;
+ result += a8.a2;
+ result += a8.a3;
+ result += a8.a4;
+ result += a8.a5;
+ result += a8.a6;
+ result += a8.a7;
+ result += a8.a8;
+ result += a8.a9;
+ result += a8.a10;
+ result += a8.a11;
+ result += a8.a12;
+ result += a8.a13;
+ result += a8.a14;
+ result += a8.a15;
+ result += a8.a16;
+ result += a8.a17;
+ result += a8.a18;
+ result += a9.a0;
+ result += a9.a1;
+ result += a9.a2;
+ result += a9.a3;
+ result += a9.a4;
+ result += a9.a5;
+ result += a9.a6;
+ result += a9.a7;
+ result += a9.a8;
+ result += a9.a9;
+ result += a9.a10;
+ result += a9.a11;
+ result += a9.a12;
+ result += a9.a13;
+ result += a9.a14;
+ result += a9.a15;
+ result += a9.a16;
+ result += a9.a17;
+ result += a9.a18;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Argument too big to go into integer registers on arm64.
+// The arguments are passed as pointers to copies.
+// The amount of arguments exhausts the number of integer registers, such that
+// pointers to copies are also passed on the stack.
+DART_EXPORT int32_t
+PassStruct20BytesHomogeneousInt32x10(Struct20BytesHomogeneousInt32 a0,
+ Struct20BytesHomogeneousInt32 a1,
+ Struct20BytesHomogeneousInt32 a2,
+ Struct20BytesHomogeneousInt32 a3,
+ Struct20BytesHomogeneousInt32 a4,
+ Struct20BytesHomogeneousInt32 a5,
+ Struct20BytesHomogeneousInt32 a6,
+ Struct20BytesHomogeneousInt32 a7,
+ Struct20BytesHomogeneousInt32 a8,
+ Struct20BytesHomogeneousInt32 a9) {
+ std::cout << "PassStruct20BytesHomogeneousInt32x10"
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3
+ << ", " << a0.a4 << "), (" << a1.a0 << ", " << a1.a1 << ", "
+ << a1.a2 << ", " << a1.a3 << ", " << a1.a4 << "), (" << a2.a0
+ << ", " << a2.a1 << ", " << a2.a2 << ", " << a2.a3 << ", " << a2.a4
+ << "), (" << a3.a0 << ", " << a3.a1 << ", " << a3.a2 << ", "
+ << a3.a3 << ", " << a3.a4 << "), (" << a4.a0 << ", " << a4.a1
+ << ", " << a4.a2 << ", " << a4.a3 << ", " << a4.a4 << "), ("
+ << a5.a0 << ", " << a5.a1 << ", " << a5.a2 << ", " << a5.a3 << ", "
+ << a5.a4 << "), (" << a6.a0 << ", " << a6.a1 << ", " << a6.a2
+ << ", " << a6.a3 << ", " << a6.a4 << "), (" << a7.a0 << ", "
+ << a7.a1 << ", " << a7.a2 << ", " << a7.a3 << ", " << a7.a4
+ << "), (" << a8.a0 << ", " << a8.a1 << ", " << a8.a2 << ", "
+ << a8.a3 << ", " << a8.a4 << "), (" << a9.a0 << ", " << a9.a1
+ << ", " << a9.a2 << ", " << a9.a3 << ", " << a9.a4 << "))"
+ << "\n";
+
+ int32_t result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a0.a2;
+ result += a0.a3;
+ result += a0.a4;
+ result += a1.a0;
+ result += a1.a1;
+ result += a1.a2;
+ result += a1.a3;
+ result += a1.a4;
+ result += a2.a0;
+ result += a2.a1;
+ result += a2.a2;
+ result += a2.a3;
+ result += a2.a4;
+ result += a3.a0;
+ result += a3.a1;
+ result += a3.a2;
+ result += a3.a3;
+ result += a3.a4;
+ result += a4.a0;
+ result += a4.a1;
+ result += a4.a2;
+ result += a4.a3;
+ result += a4.a4;
+ result += a5.a0;
+ result += a5.a1;
+ result += a5.a2;
+ result += a5.a3;
+ result += a5.a4;
+ result += a6.a0;
+ result += a6.a1;
+ result += a6.a2;
+ result += a6.a3;
+ result += a6.a4;
+ result += a7.a0;
+ result += a7.a1;
+ result += a7.a2;
+ result += a7.a3;
+ result += a7.a4;
+ result += a8.a0;
+ result += a8.a1;
+ result += a8.a2;
+ result += a8.a3;
+ result += a8.a4;
+ result += a9.a0;
+ result += a9.a1;
+ result += a9.a2;
+ result += a9.a3;
+ result += a9.a4;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Argument too big to go into FPU registers in hardfp and arm64.
+DART_EXPORT float PassStruct20BytesHomogeneousFloat(
+ Struct20BytesHomogeneousFloat a0) {
+ std::cout << "PassStruct20BytesHomogeneousFloat"
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3
+ << ", " << a0.a4 << "))"
+ << "\n";
+
+ float result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a0.a2;
+ result += a0.a3;
+ result += a0.a4;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Arguments in FPU registers on arm64.
+// 5 struct arguments will exhaust available registers.
+DART_EXPORT double PassStruct32BytesHomogeneousDoublex5(
+ Struct32BytesHomogeneousDouble a0,
+ Struct32BytesHomogeneousDouble a1,
+ Struct32BytesHomogeneousDouble a2,
+ Struct32BytesHomogeneousDouble a3,
+ Struct32BytesHomogeneousDouble a4) {
+ std::cout << "PassStruct32BytesHomogeneousDoublex5"
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3
+ << "), (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << ", "
+ << a1.a3 << "), (" << a2.a0 << ", " << a2.a1 << ", " << a2.a2
+ << ", " << a2.a3 << "), (" << a3.a0 << ", " << a3.a1 << ", "
+ << a3.a2 << ", " << a3.a3 << "), (" << a4.a0 << ", " << a4.a1
+ << ", " << a4.a2 << ", " << a4.a3 << "))"
+ << "\n";
+
+ double result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a0.a2;
+ result += a0.a3;
+ result += a1.a0;
+ result += a1.a1;
+ result += a1.a2;
+ result += a1.a3;
+ result += a2.a0;
+ result += a2.a1;
+ result += a2.a2;
+ result += a2.a3;
+ result += a3.a0;
+ result += a3.a1;
+ result += a3.a2;
+ result += a3.a3;
+ result += a4.a0;
+ result += a4.a1;
+ result += a4.a2;
+ result += a4.a3;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Argument too big to go into FPU registers in arm64.
+DART_EXPORT double PassStruct40BytesHomogeneousDouble(
+ Struct40BytesHomogeneousDouble a0) {
+ std::cout << "PassStruct40BytesHomogeneousDouble"
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3
+ << ", " << a0.a4 << "))"
+ << "\n";
+
+ double result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a0.a2;
+ result += a0.a3;
+ result += a0.a4;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Test 1kb struct.
+DART_EXPORT uint64_t
+PassStruct1024BytesHomogeneousUint64(Struct1024BytesHomogeneousUint64 a0) {
+ std::cout << "PassStruct1024BytesHomogeneousUint64"
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3
+ << ", " << a0.a4 << ", " << a0.a5 << ", " << a0.a6 << ", " << a0.a7
+ << ", " << a0.a8 << ", " << a0.a9 << ", " << a0.a10 << ", "
+ << a0.a11 << ", " << a0.a12 << ", " << a0.a13 << ", " << a0.a14
+ << ", " << a0.a15 << ", " << a0.a16 << ", " << a0.a17 << ", "
+ << a0.a18 << ", " << a0.a19 << ", " << a0.a20 << ", " << a0.a21
+ << ", " << a0.a22 << ", " << a0.a23 << ", " << a0.a24 << ", "
+ << a0.a25 << ", " << a0.a26 << ", " << a0.a27 << ", " << a0.a28
+ << ", " << a0.a29 << ", " << a0.a30 << ", " << a0.a31 << ", "
+ << a0.a32 << ", " << a0.a33 << ", " << a0.a34 << ", " << a0.a35
+ << ", " << a0.a36 << ", " << a0.a37 << ", " << a0.a38 << ", "
+ << a0.a39 << ", " << a0.a40 << ", " << a0.a41 << ", " << a0.a42
+ << ", " << a0.a43 << ", " << a0.a44 << ", " << a0.a45 << ", "
+ << a0.a46 << ", " << a0.a47 << ", " << a0.a48 << ", " << a0.a49
+ << ", " << a0.a50 << ", " << a0.a51 << ", " << a0.a52 << ", "
+ << a0.a53 << ", " << a0.a54 << ", " << a0.a55 << ", " << a0.a56
+ << ", " << a0.a57 << ", " << a0.a58 << ", " << a0.a59 << ", "
+ << a0.a60 << ", " << a0.a61 << ", " << a0.a62 << ", " << a0.a63
+ << ", " << a0.a64 << ", " << a0.a65 << ", " << a0.a66 << ", "
+ << a0.a67 << ", " << a0.a68 << ", " << a0.a69 << ", " << a0.a70
+ << ", " << a0.a71 << ", " << a0.a72 << ", " << a0.a73 << ", "
+ << a0.a74 << ", " << a0.a75 << ", " << a0.a76 << ", " << a0.a77
+ << ", " << a0.a78 << ", " << a0.a79 << ", " << a0.a80 << ", "
+ << a0.a81 << ", " << a0.a82 << ", " << a0.a83 << ", " << a0.a84
+ << ", " << a0.a85 << ", " << a0.a86 << ", " << a0.a87 << ", "
+ << a0.a88 << ", " << a0.a89 << ", " << a0.a90 << ", " << a0.a91
+ << ", " << a0.a92 << ", " << a0.a93 << ", " << a0.a94 << ", "
+ << a0.a95 << ", " << a0.a96 << ", " << a0.a97 << ", " << a0.a98
+ << ", " << a0.a99 << ", " << a0.a100 << ", " << a0.a101 << ", "
+ << a0.a102 << ", " << a0.a103 << ", " << a0.a104 << ", " << a0.a105
+ << ", " << a0.a106 << ", " << a0.a107 << ", " << a0.a108 << ", "
+ << a0.a109 << ", " << a0.a110 << ", " << a0.a111 << ", " << a0.a112
+ << ", " << a0.a113 << ", " << a0.a114 << ", " << a0.a115 << ", "
+ << a0.a116 << ", " << a0.a117 << ", " << a0.a118 << ", " << a0.a119
+ << ", " << a0.a120 << ", " << a0.a121 << ", " << a0.a122 << ", "
+ << a0.a123 << ", " << a0.a124 << ", " << a0.a125 << ", " << a0.a126
+ << ", " << a0.a127 << "))"
+ << "\n";
+
+ uint64_t result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a0.a2;
+ result += a0.a3;
+ result += a0.a4;
+ result += a0.a5;
+ result += a0.a6;
+ result += a0.a7;
+ result += a0.a8;
+ result += a0.a9;
+ result += a0.a10;
+ result += a0.a11;
+ result += a0.a12;
+ result += a0.a13;
+ result += a0.a14;
+ result += a0.a15;
+ result += a0.a16;
+ result += a0.a17;
+ result += a0.a18;
+ result += a0.a19;
+ result += a0.a20;
+ result += a0.a21;
+ result += a0.a22;
+ result += a0.a23;
+ result += a0.a24;
+ result += a0.a25;
+ result += a0.a26;
+ result += a0.a27;
+ result += a0.a28;
+ result += a0.a29;
+ result += a0.a30;
+ result += a0.a31;
+ result += a0.a32;
+ result += a0.a33;
+ result += a0.a34;
+ result += a0.a35;
+ result += a0.a36;
+ result += a0.a37;
+ result += a0.a38;
+ result += a0.a39;
+ result += a0.a40;
+ result += a0.a41;
+ result += a0.a42;
+ result += a0.a43;
+ result += a0.a44;
+ result += a0.a45;
+ result += a0.a46;
+ result += a0.a47;
+ result += a0.a48;
+ result += a0.a49;
+ result += a0.a50;
+ result += a0.a51;
+ result += a0.a52;
+ result += a0.a53;
+ result += a0.a54;
+ result += a0.a55;
+ result += a0.a56;
+ result += a0.a57;
+ result += a0.a58;
+ result += a0.a59;
+ result += a0.a60;
+ result += a0.a61;
+ result += a0.a62;
+ result += a0.a63;
+ result += a0.a64;
+ result += a0.a65;
+ result += a0.a66;
+ result += a0.a67;
+ result += a0.a68;
+ result += a0.a69;
+ result += a0.a70;
+ result += a0.a71;
+ result += a0.a72;
+ result += a0.a73;
+ result += a0.a74;
+ result += a0.a75;
+ result += a0.a76;
+ result += a0.a77;
+ result += a0.a78;
+ result += a0.a79;
+ result += a0.a80;
+ result += a0.a81;
+ result += a0.a82;
+ result += a0.a83;
+ result += a0.a84;
+ result += a0.a85;
+ result += a0.a86;
+ result += a0.a87;
+ result += a0.a88;
+ result += a0.a89;
+ result += a0.a90;
+ result += a0.a91;
+ result += a0.a92;
+ result += a0.a93;
+ result += a0.a94;
+ result += a0.a95;
+ result += a0.a96;
+ result += a0.a97;
+ result += a0.a98;
+ result += a0.a99;
+ result += a0.a100;
+ result += a0.a101;
+ result += a0.a102;
+ result += a0.a103;
+ result += a0.a104;
+ result += a0.a105;
+ result += a0.a106;
+ result += a0.a107;
+ result += a0.a108;
+ result += a0.a109;
+ result += a0.a110;
+ result += a0.a111;
+ result += a0.a112;
+ result += a0.a113;
+ result += a0.a114;
+ result += a0.a115;
+ result += a0.a116;
+ result += a0.a117;
+ result += a0.a118;
+ result += a0.a119;
+ result += a0.a120;
+ result += a0.a121;
+ result += a0.a122;
+ result += a0.a123;
+ result += a0.a124;
+ result += a0.a125;
+ result += a0.a126;
+ result += a0.a127;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Tests the alignment of structs in FPU registers and backfilling.
+DART_EXPORT float PassFloatStruct16BytesHomogeneousFloatFloatStruct1(
+ float a0,
+ Struct16BytesHomogeneousFloat a1,
+ float a2,
+ Struct16BytesHomogeneousFloat a3,
+ float a4,
+ Struct16BytesHomogeneousFloat a5,
+ float a6,
+ Struct16BytesHomogeneousFloat a7,
+ float a8) {
+ std::cout << "PassFloatStruct16BytesHomogeneousFloatFloatStruct1"
+ << "(" << a0 << ", (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2
+ << ", " << a1.a3 << "), " << a2 << ", (" << a3.a0 << ", " << a3.a1
+ << ", " << a3.a2 << ", " << a3.a3 << "), " << a4 << ", (" << a5.a0
+ << ", " << a5.a1 << ", " << a5.a2 << ", " << a5.a3 << "), " << a6
+ << ", (" << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << ", " << a7.a3
+ << "), " << a8 << ")"
+ << "\n";
+
+ float result = 0;
+
+ result += a0;
+ result += a1.a0;
+ result += a1.a1;
+ result += a1.a2;
+ result += a1.a3;
+ result += a2;
+ result += a3.a0;
+ result += a3.a1;
+ result += a3.a2;
+ result += a3.a3;
+ result += a4;
+ result += a5.a0;
+ result += a5.a1;
+ result += a5.a2;
+ result += a5.a3;
+ result += a6;
+ result += a7.a0;
+ result += a7.a1;
+ result += a7.a2;
+ result += a7.a3;
+ result += a8;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Tests the alignment of structs in FPU registers and backfilling.
+DART_EXPORT double PassFloatStruct32BytesHomogeneousDoubleFloatStruct(
+ float a0,
+ Struct32BytesHomogeneousDouble a1,
+ float a2,
+ Struct32BytesHomogeneousDouble a3,
+ float a4,
+ Struct32BytesHomogeneousDouble a5,
+ float a6,
+ Struct32BytesHomogeneousDouble a7,
+ float a8) {
+ std::cout << "PassFloatStruct32BytesHomogeneousDoubleFloatStruct"
+ << "(" << a0 << ", (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2
+ << ", " << a1.a3 << "), " << a2 << ", (" << a3.a0 << ", " << a3.a1
+ << ", " << a3.a2 << ", " << a3.a3 << "), " << a4 << ", (" << a5.a0
+ << ", " << a5.a1 << ", " << a5.a2 << ", " << a5.a3 << "), " << a6
+ << ", (" << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << ", " << a7.a3
+ << "), " << a8 << ")"
+ << "\n";
+
+ double result = 0;
+
+ result += a0;
+ result += a1.a0;
+ result += a1.a1;
+ result += a1.a2;
+ result += a1.a3;
+ result += a2;
+ result += a3.a0;
+ result += a3.a1;
+ result += a3.a2;
+ result += a3.a3;
+ result += a4;
+ result += a5.a0;
+ result += a5.a1;
+ result += a5.a2;
+ result += a5.a3;
+ result += a6;
+ result += a7.a0;
+ result += a7.a1;
+ result += a7.a2;
+ result += a7.a3;
+ result += a8;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Tests the alignment of structs in integers registers and on the stack.
+// Arm32 aligns this struct at 8.
+// Also, arm32 allocates the second struct partially in registers, partially
+// on stack.
+// Test backfilling of integer registers.
+DART_EXPORT double PassInt8Struct16BytesMixedInt8Struct16BytesMixedIn(
+ int8_t a0,
+ Struct16BytesMixed a1,
+ int8_t a2,
+ Struct16BytesMixed a3,
+ int8_t a4,
+ Struct16BytesMixed a5,
+ int8_t a6,
+ Struct16BytesMixed a7,
+ int8_t a8) {
+ std::cout << "PassInt8Struct16BytesMixedInt8Struct16BytesMixedIn"
+ << "(" << static_cast<int>(a0) << ", (" << a1.a0 << ", " << a1.a1
+ << "), " << static_cast<int>(a2) << ", (" << a3.a0 << ", " << a3.a1
+ << "), " << static_cast<int>(a4) << ", (" << a5.a0 << ", " << a5.a1
+ << "), " << static_cast<int>(a6) << ", (" << a7.a0 << ", " << a7.a1
+ << "), " << static_cast<int>(a8) << ")"
+ << "\n";
+
+ double result = 0;
+
+ result += a0;
+ result += a1.a0;
+ result += a1.a1;
+ result += a2;
+ result += a3.a0;
+ result += a3.a1;
+ result += a4;
+ result += a5.a0;
+ result += a5.a1;
+ result += a6;
+ result += a7.a0;
+ result += a7.a1;
+ result += a8;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// On Linux x64, it will exhaust xmm registers first, after 6 doubles and 2
+// structs. The rest of the structs will go on the stack.
+// The int will be backfilled into the int register.
+DART_EXPORT double PassDoublex6Struct16BytesMixedx4Int32(double a0,
+ double a1,
+ double a2,
+ double a3,
+ double a4,
+ double a5,
+ Struct16BytesMixed a6,
+ Struct16BytesMixed a7,
+ Struct16BytesMixed a8,
+ Struct16BytesMixed a9,
+ int32_t a10) {
+ std::cout << "PassDoublex6Struct16BytesMixedx4Int32"
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4
+ << ", " << a5 << ", (" << a6.a0 << ", " << a6.a1 << "), (" << a7.a0
+ << ", " << a7.a1 << "), (" << a8.a0 << ", " << a8.a1 << "), ("
+ << a9.a0 << ", " << a9.a1 << "), " << a10 << ")"
+ << "\n";
+
+ double result = 0;
+
+ result += a0;
+ result += a1;
+ result += a2;
+ result += a3;
+ result += a4;
+ result += a5;
+ result += a6.a0;
+ result += a6.a1;
+ result += a7.a0;
+ result += a7.a1;
+ result += a8.a0;
+ result += a8.a1;
+ result += a9.a0;
+ result += a9.a1;
+ result += a10;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// On Linux x64, it will exhaust int registers first.
+// The rest of the structs will go on the stack.
+// The double will be backfilled into the xmm register.
+DART_EXPORT double PassInt32x4Struct16BytesMixedx4Double(int32_t a0,
+ int32_t a1,
+ int32_t a2,
+ int32_t a3,
+ Struct16BytesMixed a4,
+ Struct16BytesMixed a5,
+ Struct16BytesMixed a6,
+ Struct16BytesMixed a7,
+ double a8) {
+ std::cout << "PassInt32x4Struct16BytesMixedx4Double"
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", ("
+ << a4.a0 << ", " << a4.a1 << "), (" << a5.a0 << ", " << a5.a1
+ << "), (" << a6.a0 << ", " << a6.a1 << "), (" << a7.a0 << ", "
+ << a7.a1 << "), " << a8 << ")"
+ << "\n";
+
+ double result = 0;
+
+ result += a0;
+ result += a1;
+ result += a2;
+ result += a3;
+ result += a4.a0;
+ result += a4.a1;
+ result += a5.a0;
+ result += a5.a1;
+ result += a6.a0;
+ result += a6.a1;
+ result += a7.a0;
+ result += a7.a1;
+ result += a8;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// On various architectures, first struct is allocated on stack.
+// Check that the other two arguments are allocated on registers.
+DART_EXPORT double PassStruct40BytesHomogeneousDoubleStruct4BytesHomo(
+ Struct40BytesHomogeneousDouble a0,
+ Struct4BytesHomogeneousInt16 a1,
+ Struct8BytesHomogeneousFloat a2) {
+ std::cout << "PassStruct40BytesHomogeneousDoubleStruct4BytesHomo"
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3
+ << ", " << a0.a4 << "), (" << a1.a0 << ", " << a1.a1 << "), ("
+ << a2.a0 << ", " << a2.a1 << "))"
+ << "\n";
+
+ double result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a0.a2;
+ result += a0.a3;
+ result += a0.a4;
+ result += a1.a0;
+ result += a1.a1;
+ result += a2.a0;
+ result += a2.a1;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of 16 byte int within struct.
+DART_EXPORT int64_t PassStructAlignmentInt16(StructAlignmentInt16 a0) {
+ std::cout << "PassStructAlignmentInt16"
+ << "((" << static_cast<int>(a0.a0) << ", " << a0.a1 << ", "
+ << static_cast<int>(a0.a2) << "))"
+ << "\n";
+
+ int64_t result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a0.a2;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of 32 byte int within struct.
+DART_EXPORT int64_t PassStructAlignmentInt32(StructAlignmentInt32 a0) {
+ std::cout << "PassStructAlignmentInt32"
+ << "((" << static_cast<int>(a0.a0) << ", " << a0.a1 << ", "
+ << static_cast<int>(a0.a2) << "))"
+ << "\n";
+
+ int64_t result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a0.a2;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of 64 byte int within struct.
+DART_EXPORT int64_t PassStructAlignmentInt64(StructAlignmentInt64 a0) {
+ std::cout << "PassStructAlignmentInt64"
+ << "((" << static_cast<int>(a0.a0) << ", " << a0.a1 << ", "
+ << static_cast<int>(a0.a2) << "))"
+ << "\n";
+
+ int64_t result = 0;
+
+ result += a0.a0;
+ result += a0.a1;
+ result += a0.a2;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Smallest struct with data.
+DART_EXPORT Struct1ByteInt ReturnStruct1ByteInt(int8_t a0) {
+ std::cout << "ReturnStruct1ByteInt"
+ << "(" << static_cast<int>(a0) << ")"
+ << "\n";
+
+ Struct1ByteInt result;
+
+ result.a0 = a0;
+
+ std::cout << "result = "
+ << "(" << static_cast<int>(result.a0) << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Smaller than word size return value on all architectures.
+DART_EXPORT Struct3BytesInt ReturnStruct3BytesInt(int16_t a0, int8_t a1) {
+ std::cout << "ReturnStruct3BytesInt"
+ << "(" << a0 << ", " << static_cast<int>(a1) << ")"
+ << "\n";
+
+ Struct3BytesInt result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << static_cast<int>(result.a1) << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Word size return value on 32 bit architectures..
+DART_EXPORT Struct4BytesHomogeneousInt16
+ReturnStruct4BytesHomogeneousInt16(int16_t a0, int16_t a1) {
+ std::cout << "ReturnStruct4BytesHomogeneousInt16"
+ << "(" << a0 << ", " << a1 << ")"
+ << "\n";
+
+ Struct4BytesHomogeneousInt16 result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Non-wordsize return value.
+DART_EXPORT Struct7BytesInt ReturnStruct7BytesInt(int32_t a0,
+ int16_t a1,
+ int8_t a2) {
+ std::cout << "ReturnStruct7BytesInt"
+ << "(" << a0 << ", " << a1 << ", " << static_cast<int>(a2) << ")"
+ << "\n";
+
+ Struct7BytesInt result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+ result.a2 = a2;
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", "
+ << static_cast<int>(result.a2) << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Return value in integer registers on many architectures.
+DART_EXPORT Struct8BytesInt ReturnStruct8BytesInt(int16_t a0,
+ int16_t a1,
+ int32_t a2) {
+ std::cout << "ReturnStruct8BytesInt"
+ << "(" << a0 << ", " << a1 << ", " << a2 << ")"
+ << "\n";
+
+ Struct8BytesInt result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+ result.a2 = a2;
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Return value in FP registers on many architectures.
+DART_EXPORT Struct8BytesHomogeneousFloat
+ReturnStruct8BytesHomogeneousFloat(float a0, float a1) {
+ std::cout << "ReturnStruct8BytesHomogeneousFloat"
+ << "(" << a0 << ", " << a1 << ")"
+ << "\n";
+
+ Struct8BytesHomogeneousFloat result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Return value split over FP and integer register in x64.
+DART_EXPORT Struct8BytesMixed ReturnStruct8BytesMixed(float a0,
+ int16_t a1,
+ int16_t a2) {
+ std::cout << "ReturnStruct8BytesMixed"
+ << "(" << a0 << ", " << a1 << ", " << a2 << ")"
+ << "\n";
+
+ Struct8BytesMixed result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+ result.a2 = a2;
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Return value in two integer registers on x64.
+// The second register only contains a single byte.
+DART_EXPORT Struct9BytesInt ReturnStruct9BytesInt(int64_t a0, int8_t a1) {
+ std::cout << "ReturnStruct9BytesInt"
+ << "(" << a0 << ", " << static_cast<int>(a1) << ")"
+ << "\n";
+
+ Struct9BytesInt result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << static_cast<int>(result.a1) << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// The minimum alignment of this struct is only 1 byte based on its fields.
+// Test that the memory backing these structs is the right size and that
+// dart:ffi trampolines do not write outside this size.
+DART_EXPORT Struct9BytesHomogeneousUint82
+ReturnStruct9BytesHomogeneousUint82(uint8_t a0,
+ uint8_t a1,
+ uint8_t a2,
+ uint8_t a3,
+ uint8_t a4,
+ uint8_t a5,
+ uint8_t a6,
+ uint8_t a7,
+ uint8_t a8) {
+ std::cout << "ReturnStruct9BytesHomogeneousUint82"
+ << "(" << static_cast<int>(a0) << ", " << static_cast<int>(a1)
+ << ", " << static_cast<int>(a2) << ", " << static_cast<int>(a3)
+ << ", " << static_cast<int>(a4) << ", " << static_cast<int>(a5)
+ << ", " << static_cast<int>(a6) << ", " << static_cast<int>(a7)
+ << ", " << static_cast<int>(a8) << ")"
+ << "\n";
+
+ Struct9BytesHomogeneousUint82 result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+ result.a2 = a2;
+ result.a3 = a3;
+ result.a4 = a4;
+ result.a5 = a5;
+ result.a6 = a6;
+ result.a7 = a7;
+ result.a8 = a8;
+
+ std::cout << "result = "
+ << "(" << static_cast<int>(result.a0) << ", "
+ << static_cast<int>(result.a1) << ", "
+ << static_cast<int>(result.a2) << ", "
+ << static_cast<int>(result.a3) << ", "
+ << static_cast<int>(result.a4) << ", "
+ << static_cast<int>(result.a5) << ", "
+ << static_cast<int>(result.a6) << ", "
+ << static_cast<int>(result.a7) << ", "
+ << static_cast<int>(result.a8) << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Return value in FPU registers, but does not use all registers on arm hardfp
+// and arm64.
+DART_EXPORT Struct12BytesHomogeneousFloat
+ReturnStruct12BytesHomogeneousFloat(float a0, float a1, float a2) {
+ std::cout << "ReturnStruct12BytesHomogeneousFloat"
+ << "(" << a0 << ", " << a1 << ", " << a2 << ")"
+ << "\n";
+
+ Struct12BytesHomogeneousFloat result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+ result.a2 = a2;
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Return value in FPU registers on arm hardfp and arm64.
+DART_EXPORT Struct16BytesHomogeneousFloat
+ReturnStruct16BytesHomogeneousFloat(float a0, float a1, float a2, float a3) {
+ std::cout << "ReturnStruct16BytesHomogeneousFloat"
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ")"
+ << "\n";
+
+ Struct16BytesHomogeneousFloat result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+ result.a2 = a2;
+ result.a3 = a3;
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2
+ << ", " << result.a3 << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Return value split over FP and integer register in x64.
+DART_EXPORT Struct16BytesMixed ReturnStruct16BytesMixed(double a0, int64_t a1) {
+ std::cout << "ReturnStruct16BytesMixed"
+ << "(" << a0 << ", " << a1 << ")"
+ << "\n";
+
+ Struct16BytesMixed result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Return value split over FP and integer register in x64.
+// The integer register contains half float half int.
+DART_EXPORT Struct16BytesMixed2 ReturnStruct16BytesMixed2(float a0,
+ float a1,
+ float a2,
+ int32_t a3) {
+ std::cout << "ReturnStruct16BytesMixed2"
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ")"
+ << "\n";
+
+ Struct16BytesMixed2 result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+ result.a2 = a2;
+ result.a3 = a3;
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2
+ << ", " << result.a3 << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Rerturn value returned in preallocated space passed by pointer on most ABIs.
+// Is non word size on purpose, to test that structs are rounded up to word size
+// on all ABIs.
+DART_EXPORT Struct17BytesInt ReturnStruct17BytesInt(int64_t a0,
+ int64_t a1,
+ int8_t a2) {
+ std::cout << "ReturnStruct17BytesInt"
+ << "(" << a0 << ", " << a1 << ", " << static_cast<int>(a2) << ")"
+ << "\n";
+
+ Struct17BytesInt result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+ result.a2 = a2;
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", "
+ << static_cast<int>(result.a2) << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// The minimum alignment of this struct is only 1 byte based on its fields.
+// Test that the memory backing these structs is the right size and that
+// dart:ffi trampolines do not write outside this size.
+DART_EXPORT Struct19BytesHomogeneousUint8
+ReturnStruct19BytesHomogeneousUint8(uint8_t a0,
+ uint8_t a1,
+ uint8_t a2,
+ uint8_t a3,
+ uint8_t a4,
+ uint8_t a5,
+ uint8_t a6,
+ uint8_t a7,
+ uint8_t a8,
+ uint8_t a9,
+ uint8_t a10,
+ uint8_t a11,
+ uint8_t a12,
+ uint8_t a13,
+ uint8_t a14,
+ uint8_t a15,
+ uint8_t a16,
+ uint8_t a17,
+ uint8_t a18) {
+ std::cout << "ReturnStruct19BytesHomogeneousUint8"
+ << "(" << static_cast<int>(a0) << ", " << static_cast<int>(a1)
+ << ", " << static_cast<int>(a2) << ", " << static_cast<int>(a3)
+ << ", " << static_cast<int>(a4) << ", " << static_cast<int>(a5)
+ << ", " << static_cast<int>(a6) << ", " << static_cast<int>(a7)
+ << ", " << static_cast<int>(a8) << ", " << static_cast<int>(a9)
+ << ", " << static_cast<int>(a10) << ", " << static_cast<int>(a11)
+ << ", " << static_cast<int>(a12) << ", " << static_cast<int>(a13)
+ << ", " << static_cast<int>(a14) << ", " << static_cast<int>(a15)
+ << ", " << static_cast<int>(a16) << ", " << static_cast<int>(a17)
+ << ", " << static_cast<int>(a18) << ")"
+ << "\n";
+
+ Struct19BytesHomogeneousUint8 result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+ result.a2 = a2;
+ result.a3 = a3;
+ result.a4 = a4;
+ result.a5 = a5;
+ result.a6 = a6;
+ result.a7 = a7;
+ result.a8 = a8;
+ result.a9 = a9;
+ result.a10 = a10;
+ result.a11 = a11;
+ result.a12 = a12;
+ result.a13 = a13;
+ result.a14 = a14;
+ result.a15 = a15;
+ result.a16 = a16;
+ result.a17 = a17;
+ result.a18 = a18;
+
+ std::cout << "result = "
+ << "(" << static_cast<int>(result.a0) << ", "
+ << static_cast<int>(result.a1) << ", "
+ << static_cast<int>(result.a2) << ", "
+ << static_cast<int>(result.a3) << ", "
+ << static_cast<int>(result.a4) << ", "
+ << static_cast<int>(result.a5) << ", "
+ << static_cast<int>(result.a6) << ", "
+ << static_cast<int>(result.a7) << ", "
+ << static_cast<int>(result.a8) << ", "
+ << static_cast<int>(result.a9) << ", "
+ << static_cast<int>(result.a10) << ", "
+ << static_cast<int>(result.a11) << ", "
+ << static_cast<int>(result.a12) << ", "
+ << static_cast<int>(result.a13) << ", "
+ << static_cast<int>(result.a14) << ", "
+ << static_cast<int>(result.a15) << ", "
+ << static_cast<int>(result.a16) << ", "
+ << static_cast<int>(result.a17) << ", "
+ << static_cast<int>(result.a18) << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Return value too big to go in cpu registers on arm64.
+DART_EXPORT Struct20BytesHomogeneousInt32
+ReturnStruct20BytesHomogeneousInt32(int32_t a0,
+ int32_t a1,
+ int32_t a2,
+ int32_t a3,
+ int32_t a4) {
+ std::cout << "ReturnStruct20BytesHomogeneousInt32"
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4
+ << ")"
+ << "\n";
+
+ Struct20BytesHomogeneousInt32 result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+ result.a2 = a2;
+ result.a3 = a3;
+ result.a4 = a4;
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2
+ << ", " << result.a3 << ", " << result.a4 << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Return value too big to go in FPU registers on x64, arm hardfp and arm64.
+DART_EXPORT Struct20BytesHomogeneousFloat
+ReturnStruct20BytesHomogeneousFloat(float a0,
+ float a1,
+ float a2,
+ float a3,
+ float a4) {
+ std::cout << "ReturnStruct20BytesHomogeneousFloat"
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4
+ << ")"
+ << "\n";
+
+ Struct20BytesHomogeneousFloat result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+ result.a2 = a2;
+ result.a3 = a3;
+ result.a4 = a4;
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2
+ << ", " << result.a3 << ", " << result.a4 << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Return value in FPU registers on arm64.
+DART_EXPORT Struct32BytesHomogeneousDouble
+ReturnStruct32BytesHomogeneousDouble(double a0,
+ double a1,
+ double a2,
+ double a3) {
+ std::cout << "ReturnStruct32BytesHomogeneousDouble"
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ")"
+ << "\n";
+
+ Struct32BytesHomogeneousDouble result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+ result.a2 = a2;
+ result.a3 = a3;
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2
+ << ", " << result.a3 << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Return value too big to go in FPU registers on arm64.
+DART_EXPORT Struct40BytesHomogeneousDouble
+ReturnStruct40BytesHomogeneousDouble(double a0,
+ double a1,
+ double a2,
+ double a3,
+ double a4) {
+ std::cout << "ReturnStruct40BytesHomogeneousDouble"
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4
+ << ")"
+ << "\n";
+
+ Struct40BytesHomogeneousDouble result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+ result.a2 = a2;
+ result.a3 = a3;
+ result.a4 = a4;
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2
+ << ", " << result.a3 << ", " << result.a4 << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Test 1kb struct.
+DART_EXPORT Struct1024BytesHomogeneousUint64
+ReturnStruct1024BytesHomogeneousUint64(uint64_t a0,
+ uint64_t a1,
+ uint64_t a2,
+ uint64_t a3,
+ uint64_t a4,
+ uint64_t a5,
+ uint64_t a6,
+ uint64_t a7,
+ uint64_t a8,
+ uint64_t a9,
+ uint64_t a10,
+ uint64_t a11,
+ uint64_t a12,
+ uint64_t a13,
+ uint64_t a14,
+ uint64_t a15,
+ uint64_t a16,
+ uint64_t a17,
+ uint64_t a18,
+ uint64_t a19,
+ uint64_t a20,
+ uint64_t a21,
+ uint64_t a22,
+ uint64_t a23,
+ uint64_t a24,
+ uint64_t a25,
+ uint64_t a26,
+ uint64_t a27,
+ uint64_t a28,
+ uint64_t a29,
+ uint64_t a30,
+ uint64_t a31,
+ uint64_t a32,
+ uint64_t a33,
+ uint64_t a34,
+ uint64_t a35,
+ uint64_t a36,
+ uint64_t a37,
+ uint64_t a38,
+ uint64_t a39,
+ uint64_t a40,
+ uint64_t a41,
+ uint64_t a42,
+ uint64_t a43,
+ uint64_t a44,
+ uint64_t a45,
+ uint64_t a46,
+ uint64_t a47,
+ uint64_t a48,
+ uint64_t a49,
+ uint64_t a50,
+ uint64_t a51,
+ uint64_t a52,
+ uint64_t a53,
+ uint64_t a54,
+ uint64_t a55,
+ uint64_t a56,
+ uint64_t a57,
+ uint64_t a58,
+ uint64_t a59,
+ uint64_t a60,
+ uint64_t a61,
+ uint64_t a62,
+ uint64_t a63,
+ uint64_t a64,
+ uint64_t a65,
+ uint64_t a66,
+ uint64_t a67,
+ uint64_t a68,
+ uint64_t a69,
+ uint64_t a70,
+ uint64_t a71,
+ uint64_t a72,
+ uint64_t a73,
+ uint64_t a74,
+ uint64_t a75,
+ uint64_t a76,
+ uint64_t a77,
+ uint64_t a78,
+ uint64_t a79,
+ uint64_t a80,
+ uint64_t a81,
+ uint64_t a82,
+ uint64_t a83,
+ uint64_t a84,
+ uint64_t a85,
+ uint64_t a86,
+ uint64_t a87,
+ uint64_t a88,
+ uint64_t a89,
+ uint64_t a90,
+ uint64_t a91,
+ uint64_t a92,
+ uint64_t a93,
+ uint64_t a94,
+ uint64_t a95,
+ uint64_t a96,
+ uint64_t a97,
+ uint64_t a98,
+ uint64_t a99,
+ uint64_t a100,
+ uint64_t a101,
+ uint64_t a102,
+ uint64_t a103,
+ uint64_t a104,
+ uint64_t a105,
+ uint64_t a106,
+ uint64_t a107,
+ uint64_t a108,
+ uint64_t a109,
+ uint64_t a110,
+ uint64_t a111,
+ uint64_t a112,
+ uint64_t a113,
+ uint64_t a114,
+ uint64_t a115,
+ uint64_t a116,
+ uint64_t a117,
+ uint64_t a118,
+ uint64_t a119,
+ uint64_t a120,
+ uint64_t a121,
+ uint64_t a122,
+ uint64_t a123,
+ uint64_t a124,
+ uint64_t a125,
+ uint64_t a126,
+ uint64_t a127) {
+ std::cout << "ReturnStruct1024BytesHomogeneousUint64"
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4
+ << ", " << a5 << ", " << a6 << ", " << a7 << ", " << a8 << ", "
+ << a9 << ", " << a10 << ", " << a11 << ", " << a12 << ", " << a13
+ << ", " << a14 << ", " << a15 << ", " << a16 << ", " << a17 << ", "
+ << a18 << ", " << a19 << ", " << a20 << ", " << a21 << ", " << a22
+ << ", " << a23 << ", " << a24 << ", " << a25 << ", " << a26 << ", "
+ << a27 << ", " << a28 << ", " << a29 << ", " << a30 << ", " << a31
+ << ", " << a32 << ", " << a33 << ", " << a34 << ", " << a35 << ", "
+ << a36 << ", " << a37 << ", " << a38 << ", " << a39 << ", " << a40
+ << ", " << a41 << ", " << a42 << ", " << a43 << ", " << a44 << ", "
+ << a45 << ", " << a46 << ", " << a47 << ", " << a48 << ", " << a49
+ << ", " << a50 << ", " << a51 << ", " << a52 << ", " << a53 << ", "
+ << a54 << ", " << a55 << ", " << a56 << ", " << a57 << ", " << a58
+ << ", " << a59 << ", " << a60 << ", " << a61 << ", " << a62 << ", "
+ << a63 << ", " << a64 << ", " << a65 << ", " << a66 << ", " << a67
+ << ", " << a68 << ", " << a69 << ", " << a70 << ", " << a71 << ", "
+ << a72 << ", " << a73 << ", " << a74 << ", " << a75 << ", " << a76
+ << ", " << a77 << ", " << a78 << ", " << a79 << ", " << a80 << ", "
+ << a81 << ", " << a82 << ", " << a83 << ", " << a84 << ", " << a85
+ << ", " << a86 << ", " << a87 << ", " << a88 << ", " << a89 << ", "
+ << a90 << ", " << a91 << ", " << a92 << ", " << a93 << ", " << a94
+ << ", " << a95 << ", " << a96 << ", " << a97 << ", " << a98 << ", "
+ << a99 << ", " << a100 << ", " << a101 << ", " << a102 << ", "
+ << a103 << ", " << a104 << ", " << a105 << ", " << a106 << ", "
+ << a107 << ", " << a108 << ", " << a109 << ", " << a110 << ", "
+ << a111 << ", " << a112 << ", " << a113 << ", " << a114 << ", "
+ << a115 << ", " << a116 << ", " << a117 << ", " << a118 << ", "
+ << a119 << ", " << a120 << ", " << a121 << ", " << a122 << ", "
+ << a123 << ", " << a124 << ", " << a125 << ", " << a126 << ", "
+ << a127 << ")"
+ << "\n";
+
+ Struct1024BytesHomogeneousUint64 result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+ result.a2 = a2;
+ result.a3 = a3;
+ result.a4 = a4;
+ result.a5 = a5;
+ result.a6 = a6;
+ result.a7 = a7;
+ result.a8 = a8;
+ result.a9 = a9;
+ result.a10 = a10;
+ result.a11 = a11;
+ result.a12 = a12;
+ result.a13 = a13;
+ result.a14 = a14;
+ result.a15 = a15;
+ result.a16 = a16;
+ result.a17 = a17;
+ result.a18 = a18;
+ result.a19 = a19;
+ result.a20 = a20;
+ result.a21 = a21;
+ result.a22 = a22;
+ result.a23 = a23;
+ result.a24 = a24;
+ result.a25 = a25;
+ result.a26 = a26;
+ result.a27 = a27;
+ result.a28 = a28;
+ result.a29 = a29;
+ result.a30 = a30;
+ result.a31 = a31;
+ result.a32 = a32;
+ result.a33 = a33;
+ result.a34 = a34;
+ result.a35 = a35;
+ result.a36 = a36;
+ result.a37 = a37;
+ result.a38 = a38;
+ result.a39 = a39;
+ result.a40 = a40;
+ result.a41 = a41;
+ result.a42 = a42;
+ result.a43 = a43;
+ result.a44 = a44;
+ result.a45 = a45;
+ result.a46 = a46;
+ result.a47 = a47;
+ result.a48 = a48;
+ result.a49 = a49;
+ result.a50 = a50;
+ result.a51 = a51;
+ result.a52 = a52;
+ result.a53 = a53;
+ result.a54 = a54;
+ result.a55 = a55;
+ result.a56 = a56;
+ result.a57 = a57;
+ result.a58 = a58;
+ result.a59 = a59;
+ result.a60 = a60;
+ result.a61 = a61;
+ result.a62 = a62;
+ result.a63 = a63;
+ result.a64 = a64;
+ result.a65 = a65;
+ result.a66 = a66;
+ result.a67 = a67;
+ result.a68 = a68;
+ result.a69 = a69;
+ result.a70 = a70;
+ result.a71 = a71;
+ result.a72 = a72;
+ result.a73 = a73;
+ result.a74 = a74;
+ result.a75 = a75;
+ result.a76 = a76;
+ result.a77 = a77;
+ result.a78 = a78;
+ result.a79 = a79;
+ result.a80 = a80;
+ result.a81 = a81;
+ result.a82 = a82;
+ result.a83 = a83;
+ result.a84 = a84;
+ result.a85 = a85;
+ result.a86 = a86;
+ result.a87 = a87;
+ result.a88 = a88;
+ result.a89 = a89;
+ result.a90 = a90;
+ result.a91 = a91;
+ result.a92 = a92;
+ result.a93 = a93;
+ result.a94 = a94;
+ result.a95 = a95;
+ result.a96 = a96;
+ result.a97 = a97;
+ result.a98 = a98;
+ result.a99 = a99;
+ result.a100 = a100;
+ result.a101 = a101;
+ result.a102 = a102;
+ result.a103 = a103;
+ result.a104 = a104;
+ result.a105 = a105;
+ result.a106 = a106;
+ result.a107 = a107;
+ result.a108 = a108;
+ result.a109 = a109;
+ result.a110 = a110;
+ result.a111 = a111;
+ result.a112 = a112;
+ result.a113 = a113;
+ result.a114 = a114;
+ result.a115 = a115;
+ result.a116 = a116;
+ result.a117 = a117;
+ result.a118 = a118;
+ result.a119 = a119;
+ result.a120 = a120;
+ result.a121 = a121;
+ result.a122 = a122;
+ result.a123 = a123;
+ result.a124 = a124;
+ result.a125 = a125;
+ result.a126 = a126;
+ result.a127 = a127;
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2
+ << ", " << result.a3 << ", " << result.a4 << ", " << result.a5
+ << ", " << result.a6 << ", " << result.a7 << ", " << result.a8
+ << ", " << result.a9 << ", " << result.a10 << ", " << result.a11
+ << ", " << result.a12 << ", " << result.a13 << ", " << result.a14
+ << ", " << result.a15 << ", " << result.a16 << ", " << result.a17
+ << ", " << result.a18 << ", " << result.a19 << ", " << result.a20
+ << ", " << result.a21 << ", " << result.a22 << ", " << result.a23
+ << ", " << result.a24 << ", " << result.a25 << ", " << result.a26
+ << ", " << result.a27 << ", " << result.a28 << ", " << result.a29
+ << ", " << result.a30 << ", " << result.a31 << ", " << result.a32
+ << ", " << result.a33 << ", " << result.a34 << ", " << result.a35
+ << ", " << result.a36 << ", " << result.a37 << ", " << result.a38
+ << ", " << result.a39 << ", " << result.a40 << ", " << result.a41
+ << ", " << result.a42 << ", " << result.a43 << ", " << result.a44
+ << ", " << result.a45 << ", " << result.a46 << ", " << result.a47
+ << ", " << result.a48 << ", " << result.a49 << ", " << result.a50
+ << ", " << result.a51 << ", " << result.a52 << ", " << result.a53
+ << ", " << result.a54 << ", " << result.a55 << ", " << result.a56
+ << ", " << result.a57 << ", " << result.a58 << ", " << result.a59
+ << ", " << result.a60 << ", " << result.a61 << ", " << result.a62
+ << ", " << result.a63 << ", " << result.a64 << ", " << result.a65
+ << ", " << result.a66 << ", " << result.a67 << ", " << result.a68
+ << ", " << result.a69 << ", " << result.a70 << ", " << result.a71
+ << ", " << result.a72 << ", " << result.a73 << ", " << result.a74
+ << ", " << result.a75 << ", " << result.a76 << ", " << result.a77
+ << ", " << result.a78 << ", " << result.a79 << ", " << result.a80
+ << ", " << result.a81 << ", " << result.a82 << ", " << result.a83
+ << ", " << result.a84 << ", " << result.a85 << ", " << result.a86
+ << ", " << result.a87 << ", " << result.a88 << ", " << result.a89
+ << ", " << result.a90 << ", " << result.a91 << ", " << result.a92
+ << ", " << result.a93 << ", " << result.a94 << ", " << result.a95
+ << ", " << result.a96 << ", " << result.a97 << ", " << result.a98
+ << ", " << result.a99 << ", " << result.a100 << ", " << result.a101
+ << ", " << result.a102 << ", " << result.a103 << ", " << result.a104
+ << ", " << result.a105 << ", " << result.a106 << ", " << result.a107
+ << ", " << result.a108 << ", " << result.a109 << ", " << result.a110
+ << ", " << result.a111 << ", " << result.a112 << ", " << result.a113
+ << ", " << result.a114 << ", " << result.a115 << ", " << result.a116
+ << ", " << result.a117 << ", " << result.a118 << ", " << result.a119
+ << ", " << result.a120 << ", " << result.a121 << ", " << result.a122
+ << ", " << result.a123 << ", " << result.a124 << ", " << result.a125
+ << ", " << result.a126 << ", " << result.a127 << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Test that a struct passed in as argument can be returned.
+// Especially for ffi callbacks.
+// Struct is passed in int registers in most ABIs.
+DART_EXPORT Struct1ByteInt
+ReturnStructArgumentStruct1ByteInt(Struct1ByteInt a0) {
+ std::cout << "ReturnStructArgumentStruct1ByteInt"
+ << "((" << static_cast<int>(a0.a0) << "))"
+ << "\n";
+
+ Struct1ByteInt result = a0;
+
+ std::cout << "result = "
+ << "(" << static_cast<int>(result.a0) << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Test that a struct passed in as argument can be returned.
+// Especially for ffi callbacks.
+// Struct is passed on stack on all ABIs.
+DART_EXPORT Struct1ByteInt
+ReturnStructArgumentInt32x8Struct1ByteInt(int32_t a0,
+ int32_t a1,
+ int32_t a2,
+ int32_t a3,
+ int32_t a4,
+ int32_t a5,
+ int32_t a6,
+ int32_t a7,
+ Struct1ByteInt a8) {
+ std::cout << "ReturnStructArgumentInt32x8Struct1ByteInt"
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4
+ << ", " << a5 << ", " << a6 << ", " << a7 << ", ("
+ << static_cast<int>(a8.a0) << "))"
+ << "\n";
+
+ Struct1ByteInt result = a8;
+
+ std::cout << "result = "
+ << "(" << static_cast<int>(result.a0) << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Test that a struct passed in as argument can be returned.
+// Especially for ffi callbacks.
+// Struct is passed in float registers in most ABIs.
+DART_EXPORT Struct8BytesHomogeneousFloat
+ReturnStructArgumentStruct8BytesHomogeneousFloat(
+ Struct8BytesHomogeneousFloat a0) {
+ std::cout << "ReturnStructArgumentStruct8BytesHomogeneousFloat"
+ << "((" << a0.a0 << ", " << a0.a1 << "))"
+ << "\n";
+
+ Struct8BytesHomogeneousFloat result = a0;
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// On arm64, both argument and return value are passed in by pointer.
+DART_EXPORT Struct20BytesHomogeneousInt32
+ReturnStructArgumentStruct20BytesHomogeneousInt32(
+ Struct20BytesHomogeneousInt32 a0) {
+ std::cout << "ReturnStructArgumentStruct20BytesHomogeneousInt32"
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3
+ << ", " << a0.a4 << "))"
+ << "\n";
+
+ Struct20BytesHomogeneousInt32 result = a0;
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2
+ << ", " << result.a3 << ", " << result.a4 << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// On arm64, both argument and return value are passed in by pointer.
+// Ints exhaust registers, so that pointer is passed on stack.
+DART_EXPORT Struct20BytesHomogeneousInt32
+ReturnStructArgumentInt32x8Struct20BytesHomogeneou(
+ int32_t a0,
+ int32_t a1,
+ int32_t a2,
+ int32_t a3,
+ int32_t a4,
+ int32_t a5,
+ int32_t a6,
+ int32_t a7,
+ Struct20BytesHomogeneousInt32 a8) {
+ std::cout << "ReturnStructArgumentInt32x8Struct20BytesHomogeneou"
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4
+ << ", " << a5 << ", " << a6 << ", " << a7 << ", (" << a8.a0 << ", "
+ << a8.a1 << ", " << a8.a2 << ", " << a8.a3 << ", " << a8.a4 << "))"
+ << "\n";
+
+ Struct20BytesHomogeneousInt32 result = a8;
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2
+ << ", " << result.a3 << ", " << result.a4 << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of 16 byte int within struct.
+DART_EXPORT StructAlignmentInt16 ReturnStructAlignmentInt16(int8_t a0,
+ int16_t a1,
+ int8_t a2) {
+ std::cout << "ReturnStructAlignmentInt16"
+ << "(" << static_cast<int>(a0) << ", " << a1 << ", "
+ << static_cast<int>(a2) << ")"
+ << "\n";
+
+ StructAlignmentInt16 result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+ result.a2 = a2;
+
+ std::cout << "result = "
+ << "(" << static_cast<int>(result.a0) << ", " << result.a1 << ", "
+ << static_cast<int>(result.a2) << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of 32 byte int within struct.
+DART_EXPORT StructAlignmentInt32 ReturnStructAlignmentInt32(int8_t a0,
+ int32_t a1,
+ int8_t a2) {
+ std::cout << "ReturnStructAlignmentInt32"
+ << "(" << static_cast<int>(a0) << ", " << a1 << ", "
+ << static_cast<int>(a2) << ")"
+ << "\n";
+
+ StructAlignmentInt32 result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+ result.a2 = a2;
+
+ std::cout << "result = "
+ << "(" << static_cast<int>(result.a0) << ", " << result.a1 << ", "
+ << static_cast<int>(result.a2) << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of 64 byte int within struct.
+DART_EXPORT StructAlignmentInt64 ReturnStructAlignmentInt64(int8_t a0,
+ int64_t a1,
+ int8_t a2) {
+ std::cout << "ReturnStructAlignmentInt64"
+ << "(" << static_cast<int>(a0) << ", " << a1 << ", "
+ << static_cast<int>(a2) << ")"
+ << "\n";
+
+ StructAlignmentInt64 result;
+
+ result.a0 = a0;
+ result.a1 = a1;
+ result.a2 = a2;
+
+ std::cout << "result = "
+ << "(" << static_cast<int>(result.a0) << ", " << result.a1 << ", "
+ << static_cast<int>(result.a2) << ")"
+ << "\n";
+
+ return result;
+}
+
+// Used for testing structs by value.
+// Smallest struct with data.
+// 10 struct arguments will exhaust available registers.
+DART_EXPORT intptr_t TestPassStruct1ByteIntx10(
+ // NOLINTNEXTLINE(whitespace/parens)
+ int64_t (*f)(Struct1ByteInt a0,
+ Struct1ByteInt a1,
+ Struct1ByteInt a2,
+ Struct1ByteInt a3,
+ Struct1ByteInt a4,
+ Struct1ByteInt a5,
+ Struct1ByteInt a6,
+ Struct1ByteInt a7,
+ Struct1ByteInt a8,
+ Struct1ByteInt a9)) {
+ Struct1ByteInt a0;
+ Struct1ByteInt a1;
+ Struct1ByteInt a2;
+ Struct1ByteInt a3;
+ Struct1ByteInt a4;
+ Struct1ByteInt a5;
+ Struct1ByteInt a6;
+ Struct1ByteInt a7;
+ Struct1ByteInt a8;
+ Struct1ByteInt a9;
+
+ a0.a0 = -1;
+ a1.a0 = 2;
+ a2.a0 = -3;
+ a3.a0 = 4;
+ a4.a0 = -5;
+ a5.a0 = 6;
+ a6.a0 = -7;
+ a7.a0 = 8;
+ a8.a0 = -9;
+ a9.a0 = 10;
+
+ std::cout << "Calling TestPassStruct1ByteIntx10("
+ << "((" << static_cast<int>(a0.a0) << "), ("
+ << static_cast<int>(a1.a0) << "), (" << static_cast<int>(a2.a0)
+ << "), (" << static_cast<int>(a3.a0) << "), ("
+ << static_cast<int>(a4.a0) << "), (" << static_cast<int>(a5.a0)
+ << "), (" << static_cast<int>(a6.a0) << "), ("
+ << static_cast<int>(a7.a0) << "), (" << static_cast<int>(a8.a0)
+ << "), (" << static_cast<int>(a9.a0) << "))"
+ << ")\n";
+
+ int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_EQ(5, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_EQ(0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_EQ(0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Not a multiple of word size, not a power of two.
+// 10 struct arguments will exhaust available registers.
+DART_EXPORT intptr_t TestPassStruct3BytesIntx10(
+ // NOLINTNEXTLINE(whitespace/parens)
+ int64_t (*f)(Struct3BytesInt a0,
+ Struct3BytesInt a1,
+ Struct3BytesInt a2,
+ Struct3BytesInt a3,
+ Struct3BytesInt a4,
+ Struct3BytesInt a5,
+ Struct3BytesInt a6,
+ Struct3BytesInt a7,
+ Struct3BytesInt a8,
+ Struct3BytesInt a9)) {
+ Struct3BytesInt a0;
+ Struct3BytesInt a1;
+ Struct3BytesInt a2;
+ Struct3BytesInt a3;
+ Struct3BytesInt a4;
+ Struct3BytesInt a5;
+ Struct3BytesInt a6;
+ Struct3BytesInt a7;
+ Struct3BytesInt a8;
+ Struct3BytesInt a9;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a1.a0 = -3;
+ a1.a1 = 4;
+ a2.a0 = -5;
+ a2.a1 = 6;
+ a3.a0 = -7;
+ a3.a1 = 8;
+ a4.a0 = -9;
+ a4.a1 = 10;
+ a5.a0 = -11;
+ a5.a1 = 12;
+ a6.a0 = -13;
+ a6.a1 = 14;
+ a7.a0 = -15;
+ a7.a1 = 16;
+ a8.a0 = -17;
+ a8.a1 = 18;
+ a9.a0 = -19;
+ a9.a1 = 20;
+
+ std::cout << "Calling TestPassStruct3BytesIntx10("
+ << "((" << a0.a0 << ", " << static_cast<int>(a0.a1) << "), ("
+ << a1.a0 << ", " << static_cast<int>(a1.a1) << "), (" << a2.a0
+ << ", " << static_cast<int>(a2.a1) << "), (" << a3.a0 << ", "
+ << static_cast<int>(a3.a1) << "), (" << a4.a0 << ", "
+ << static_cast<int>(a4.a1) << "), (" << a5.a0 << ", "
+ << static_cast<int>(a5.a1) << "), (" << a6.a0 << ", "
+ << static_cast<int>(a6.a1) << "), (" << a7.a0 << ", "
+ << static_cast<int>(a7.a1) << "), (" << a8.a0 << ", "
+ << static_cast<int>(a8.a1) << "), (" << a9.a0 << ", "
+ << static_cast<int>(a9.a1) << "))"
+ << ")\n";
+
+ int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_EQ(10, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_EQ(0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_EQ(0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Exactly word size on 32-bit architectures.
+// 10 struct arguments will exhaust available registers.
+DART_EXPORT intptr_t TestPassStruct4BytesHomogeneousInt16x10(
+ // NOLINTNEXTLINE(whitespace/parens)
+ int64_t (*f)(Struct4BytesHomogeneousInt16 a0,
+ Struct4BytesHomogeneousInt16 a1,
+ Struct4BytesHomogeneousInt16 a2,
+ Struct4BytesHomogeneousInt16 a3,
+ Struct4BytesHomogeneousInt16 a4,
+ Struct4BytesHomogeneousInt16 a5,
+ Struct4BytesHomogeneousInt16 a6,
+ Struct4BytesHomogeneousInt16 a7,
+ Struct4BytesHomogeneousInt16 a8,
+ Struct4BytesHomogeneousInt16 a9)) {
+ Struct4BytesHomogeneousInt16 a0;
+ Struct4BytesHomogeneousInt16 a1;
+ Struct4BytesHomogeneousInt16 a2;
+ Struct4BytesHomogeneousInt16 a3;
+ Struct4BytesHomogeneousInt16 a4;
+ Struct4BytesHomogeneousInt16 a5;
+ Struct4BytesHomogeneousInt16 a6;
+ Struct4BytesHomogeneousInt16 a7;
+ Struct4BytesHomogeneousInt16 a8;
+ Struct4BytesHomogeneousInt16 a9;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a1.a0 = -3;
+ a1.a1 = 4;
+ a2.a0 = -5;
+ a2.a1 = 6;
+ a3.a0 = -7;
+ a3.a1 = 8;
+ a4.a0 = -9;
+ a4.a1 = 10;
+ a5.a0 = -11;
+ a5.a1 = 12;
+ a6.a0 = -13;
+ a6.a1 = 14;
+ a7.a0 = -15;
+ a7.a1 = 16;
+ a8.a0 = -17;
+ a8.a1 = 18;
+ a9.a0 = -19;
+ a9.a1 = 20;
+
+ std::cout << "Calling TestPassStruct4BytesHomogeneousInt16x10("
+ << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << ", "
+ << a1.a1 << "), (" << a2.a0 << ", " << a2.a1 << "), (" << a3.a0
+ << ", " << a3.a1 << "), (" << a4.a0 << ", " << a4.a1 << "), ("
+ << a5.a0 << ", " << a5.a1 << "), (" << a6.a0 << ", " << a6.a1
+ << "), (" << a7.a0 << ", " << a7.a1 << "), (" << a8.a0 << ", "
+ << a8.a1 << "), (" << a9.a0 << ", " << a9.a1 << "))"
+ << ")\n";
+
+ int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_EQ(10, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_EQ(0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_EQ(0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Sub word size on 64 bit architectures.
+// 10 struct arguments will exhaust available registers.
+DART_EXPORT intptr_t TestPassStruct7BytesIntx10(
+ // NOLINTNEXTLINE(whitespace/parens)
+ int64_t (*f)(Struct7BytesInt a0,
+ Struct7BytesInt a1,
+ Struct7BytesInt a2,
+ Struct7BytesInt a3,
+ Struct7BytesInt a4,
+ Struct7BytesInt a5,
+ Struct7BytesInt a6,
+ Struct7BytesInt a7,
+ Struct7BytesInt a8,
+ Struct7BytesInt a9)) {
+ Struct7BytesInt a0;
+ Struct7BytesInt a1;
+ Struct7BytesInt a2;
+ Struct7BytesInt a3;
+ Struct7BytesInt a4;
+ Struct7BytesInt a5;
+ Struct7BytesInt a6;
+ Struct7BytesInt a7;
+ Struct7BytesInt a8;
+ Struct7BytesInt a9;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+ a1.a0 = 4;
+ a1.a1 = -5;
+ a1.a2 = 6;
+ a2.a0 = -7;
+ a2.a1 = 8;
+ a2.a2 = -9;
+ a3.a0 = 10;
+ a3.a1 = -11;
+ a3.a2 = 12;
+ a4.a0 = -13;
+ a4.a1 = 14;
+ a4.a2 = -15;
+ a5.a0 = 16;
+ a5.a1 = -17;
+ a5.a2 = 18;
+ a6.a0 = -19;
+ a6.a1 = 20;
+ a6.a2 = -21;
+ a7.a0 = 22;
+ a7.a1 = -23;
+ a7.a2 = 24;
+ a8.a0 = -25;
+ a8.a1 = 26;
+ a8.a2 = -27;
+ a9.a0 = 28;
+ a9.a1 = -29;
+ a9.a2 = 30;
+
+ std::cout << "Calling TestPassStruct7BytesIntx10("
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << static_cast<int>(a0.a2)
+ << "), (" << a1.a0 << ", " << a1.a1 << ", "
+ << static_cast<int>(a1.a2) << "), (" << a2.a0 << ", " << a2.a1
+ << ", " << static_cast<int>(a2.a2) << "), (" << a3.a0 << ", "
+ << a3.a1 << ", " << static_cast<int>(a3.a2) << "), (" << a4.a0
+ << ", " << a4.a1 << ", " << static_cast<int>(a4.a2) << "), ("
+ << a5.a0 << ", " << a5.a1 << ", " << static_cast<int>(a5.a2)
+ << "), (" << a6.a0 << ", " << a6.a1 << ", "
+ << static_cast<int>(a6.a2) << "), (" << a7.a0 << ", " << a7.a1
+ << ", " << static_cast<int>(a7.a2) << "), (" << a8.a0 << ", "
+ << a8.a1 << ", " << static_cast<int>(a8.a2) << "), (" << a9.a0
+ << ", " << a9.a1 << ", " << static_cast<int>(a9.a2) << "))"
+ << ")\n";
+
+ int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_EQ(15, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_EQ(0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_EQ(0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Exactly word size struct on 64bit architectures.
+// 10 struct arguments will exhaust available registers.
+DART_EXPORT intptr_t TestPassStruct8BytesIntx10(
+ // NOLINTNEXTLINE(whitespace/parens)
+ int64_t (*f)(Struct8BytesInt a0,
+ Struct8BytesInt a1,
+ Struct8BytesInt a2,
+ Struct8BytesInt a3,
+ Struct8BytesInt a4,
+ Struct8BytesInt a5,
+ Struct8BytesInt a6,
+ Struct8BytesInt a7,
+ Struct8BytesInt a8,
+ Struct8BytesInt a9)) {
+ Struct8BytesInt a0;
+ Struct8BytesInt a1;
+ Struct8BytesInt a2;
+ Struct8BytesInt a3;
+ Struct8BytesInt a4;
+ Struct8BytesInt a5;
+ Struct8BytesInt a6;
+ Struct8BytesInt a7;
+ Struct8BytesInt a8;
+ Struct8BytesInt a9;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+ a1.a0 = 4;
+ a1.a1 = -5;
+ a1.a2 = 6;
+ a2.a0 = -7;
+ a2.a1 = 8;
+ a2.a2 = -9;
+ a3.a0 = 10;
+ a3.a1 = -11;
+ a3.a2 = 12;
+ a4.a0 = -13;
+ a4.a1 = 14;
+ a4.a2 = -15;
+ a5.a0 = 16;
+ a5.a1 = -17;
+ a5.a2 = 18;
+ a6.a0 = -19;
+ a6.a1 = 20;
+ a6.a2 = -21;
+ a7.a0 = 22;
+ a7.a1 = -23;
+ a7.a2 = 24;
+ a8.a0 = -25;
+ a8.a1 = 26;
+ a8.a2 = -27;
+ a9.a0 = 28;
+ a9.a1 = -29;
+ a9.a2 = 30;
+
+ std::cout << "Calling TestPassStruct8BytesIntx10("
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << "), ("
+ << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << "), (" << a2.a0
+ << ", " << a2.a1 << ", " << a2.a2 << "), (" << a3.a0 << ", "
+ << a3.a1 << ", " << a3.a2 << "), (" << a4.a0 << ", " << a4.a1
+ << ", " << a4.a2 << "), (" << a5.a0 << ", " << a5.a1 << ", "
+ << a5.a2 << "), (" << a6.a0 << ", " << a6.a1 << ", " << a6.a2
+ << "), (" << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << "), ("
+ << a8.a0 << ", " << a8.a1 << ", " << a8.a2 << "), (" << a9.a0
+ << ", " << a9.a1 << ", " << a9.a2 << "))"
+ << ")\n";
+
+ int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_EQ(15, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_EQ(0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_EQ(0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Arguments passed in FP registers as long as they fit.
+// 10 struct arguments will exhaust available registers.
+DART_EXPORT intptr_t TestPassStruct8BytesHomogeneousFloatx10(
+ // NOLINTNEXTLINE(whitespace/parens)
+ float (*f)(Struct8BytesHomogeneousFloat a0,
+ Struct8BytesHomogeneousFloat a1,
+ Struct8BytesHomogeneousFloat a2,
+ Struct8BytesHomogeneousFloat a3,
+ Struct8BytesHomogeneousFloat a4,
+ Struct8BytesHomogeneousFloat a5,
+ Struct8BytesHomogeneousFloat a6,
+ Struct8BytesHomogeneousFloat a7,
+ Struct8BytesHomogeneousFloat a8,
+ Struct8BytesHomogeneousFloat a9)) {
+ Struct8BytesHomogeneousFloat a0;
+ Struct8BytesHomogeneousFloat a1;
+ Struct8BytesHomogeneousFloat a2;
+ Struct8BytesHomogeneousFloat a3;
+ Struct8BytesHomogeneousFloat a4;
+ Struct8BytesHomogeneousFloat a5;
+ Struct8BytesHomogeneousFloat a6;
+ Struct8BytesHomogeneousFloat a7;
+ Struct8BytesHomogeneousFloat a8;
+ Struct8BytesHomogeneousFloat a9;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a1.a0 = -3.0;
+ a1.a1 = 4.0;
+ a2.a0 = -5.0;
+ a2.a1 = 6.0;
+ a3.a0 = -7.0;
+ a3.a1 = 8.0;
+ a4.a0 = -9.0;
+ a4.a1 = 10.0;
+ a5.a0 = -11.0;
+ a5.a1 = 12.0;
+ a6.a0 = -13.0;
+ a6.a1 = 14.0;
+ a7.a0 = -15.0;
+ a7.a1 = 16.0;
+ a8.a0 = -17.0;
+ a8.a1 = 18.0;
+ a9.a0 = -19.0;
+ a9.a1 = 20.0;
+
+ std::cout << "Calling TestPassStruct8BytesHomogeneousFloatx10("
+ << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << ", "
+ << a1.a1 << "), (" << a2.a0 << ", " << a2.a1 << "), (" << a3.a0
+ << ", " << a3.a1 << "), (" << a4.a0 << ", " << a4.a1 << "), ("
+ << a5.a0 << ", " << a5.a1 << "), (" << a6.a0 << ", " << a6.a1
+ << "), (" << a7.a0 << ", " << a7.a1 << "), (" << a8.a0 << ", "
+ << a8.a1 << "), (" << a9.a0 << ", " << a9.a1 << "))"
+ << ")\n";
+
+ float result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_APPROX(10.0, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_APPROX(0.0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_APPROX(0.0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// On x64, arguments go in int registers because it is not only float.
+// 10 struct arguments will exhaust available registers.
+DART_EXPORT intptr_t TestPassStruct8BytesMixedx10(
+ // NOLINTNEXTLINE(whitespace/parens)
+ float (*f)(Struct8BytesMixed a0,
+ Struct8BytesMixed a1,
+ Struct8BytesMixed a2,
+ Struct8BytesMixed a3,
+ Struct8BytesMixed a4,
+ Struct8BytesMixed a5,
+ Struct8BytesMixed a6,
+ Struct8BytesMixed a7,
+ Struct8BytesMixed a8,
+ Struct8BytesMixed a9)) {
+ Struct8BytesMixed a0;
+ Struct8BytesMixed a1;
+ Struct8BytesMixed a2;
+ Struct8BytesMixed a3;
+ Struct8BytesMixed a4;
+ Struct8BytesMixed a5;
+ Struct8BytesMixed a6;
+ Struct8BytesMixed a7;
+ Struct8BytesMixed a8;
+ Struct8BytesMixed a9;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2;
+ a0.a2 = -3;
+ a1.a0 = 4.0;
+ a1.a1 = -5;
+ a1.a2 = 6;
+ a2.a0 = -7.0;
+ a2.a1 = 8;
+ a2.a2 = -9;
+ a3.a0 = 10.0;
+ a3.a1 = -11;
+ a3.a2 = 12;
+ a4.a0 = -13.0;
+ a4.a1 = 14;
+ a4.a2 = -15;
+ a5.a0 = 16.0;
+ a5.a1 = -17;
+ a5.a2 = 18;
+ a6.a0 = -19.0;
+ a6.a1 = 20;
+ a6.a2 = -21;
+ a7.a0 = 22.0;
+ a7.a1 = -23;
+ a7.a2 = 24;
+ a8.a0 = -25.0;
+ a8.a1 = 26;
+ a8.a2 = -27;
+ a9.a0 = 28.0;
+ a9.a1 = -29;
+ a9.a2 = 30;
+
+ std::cout << "Calling TestPassStruct8BytesMixedx10("
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << "), ("
+ << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << "), (" << a2.a0
+ << ", " << a2.a1 << ", " << a2.a2 << "), (" << a3.a0 << ", "
+ << a3.a1 << ", " << a3.a2 << "), (" << a4.a0 << ", " << a4.a1
+ << ", " << a4.a2 << "), (" << a5.a0 << ", " << a5.a1 << ", "
+ << a5.a2 << "), (" << a6.a0 << ", " << a6.a1 << ", " << a6.a2
+ << "), (" << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << "), ("
+ << a8.a0 << ", " << a8.a1 << ", " << a8.a2 << "), (" << a9.a0
+ << ", " << a9.a1 << ", " << a9.a2 << "))"
+ << ")\n";
+
+ float result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_APPROX(15.0, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_APPROX(0.0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_APPROX(0.0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Argument is a single byte over a multiple of word size.
+// 10 struct arguments will exhaust available registers.
+// Tests upper bytes in the integer registers that are partly filled.
+// Tests stack alignment of non word size stack arguments.
+DART_EXPORT intptr_t TestPassStruct9BytesIntx10(
+ // NOLINTNEXTLINE(whitespace/parens)
+ int64_t (*f)(Struct9BytesInt a0,
+ Struct9BytesInt a1,
+ Struct9BytesInt a2,
+ Struct9BytesInt a3,
+ Struct9BytesInt a4,
+ Struct9BytesInt a5,
+ Struct9BytesInt a6,
+ Struct9BytesInt a7,
+ Struct9BytesInt a8,
+ Struct9BytesInt a9)) {
+ Struct9BytesInt a0;
+ Struct9BytesInt a1;
+ Struct9BytesInt a2;
+ Struct9BytesInt a3;
+ Struct9BytesInt a4;
+ Struct9BytesInt a5;
+ Struct9BytesInt a6;
+ Struct9BytesInt a7;
+ Struct9BytesInt a8;
+ Struct9BytesInt a9;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a1.a0 = -3;
+ a1.a1 = 4;
+ a2.a0 = -5;
+ a2.a1 = 6;
+ a3.a0 = -7;
+ a3.a1 = 8;
+ a4.a0 = -9;
+ a4.a1 = 10;
+ a5.a0 = -11;
+ a5.a1 = 12;
+ a6.a0 = -13;
+ a6.a1 = 14;
+ a7.a0 = -15;
+ a7.a1 = 16;
+ a8.a0 = -17;
+ a8.a1 = 18;
+ a9.a0 = -19;
+ a9.a1 = 20;
+
+ std::cout << "Calling TestPassStruct9BytesIntx10("
+ << "((" << a0.a0 << ", " << static_cast<int>(a0.a1) << "), ("
+ << a1.a0 << ", " << static_cast<int>(a1.a1) << "), (" << a2.a0
+ << ", " << static_cast<int>(a2.a1) << "), (" << a3.a0 << ", "
+ << static_cast<int>(a3.a1) << "), (" << a4.a0 << ", "
+ << static_cast<int>(a4.a1) << "), (" << a5.a0 << ", "
+ << static_cast<int>(a5.a1) << "), (" << a6.a0 << ", "
+ << static_cast<int>(a6.a1) << "), (" << a7.a0 << ", "
+ << static_cast<int>(a7.a1) << "), (" << a8.a0 << ", "
+ << static_cast<int>(a8.a1) << "), (" << a9.a0 << ", "
+ << static_cast<int>(a9.a1) << "))"
+ << ")\n";
+
+ int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_EQ(10, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_EQ(0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_EQ(0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Argument is a single byte over a multiple of word size.
+// 10 struct arguments will exhaust available registers.
+// Struct only has 1-byte aligned fields to test struct alignment itself.
+//
+DART_EXPORT intptr_t TestPassStruct9BytesHomogeneousUint82x10(
+ // NOLINTNEXTLINE(whitespace/parens)
+ int64_t (*f)(Struct9BytesHomogeneousUint82 a0,
+ Struct9BytesHomogeneousUint82 a1,
+ Struct9BytesHomogeneousUint82 a2,
+ Struct9BytesHomogeneousUint82 a3,
+ Struct9BytesHomogeneousUint82 a4,
+ Struct9BytesHomogeneousUint82 a5,
+ Struct9BytesHomogeneousUint82 a6,
+ Struct9BytesHomogeneousUint82 a7,
+ Struct9BytesHomogeneousUint82 a8,
+ Struct9BytesHomogeneousUint82 a9)) {
+ Struct9BytesHomogeneousUint82 a0;
+ Struct9BytesHomogeneousUint82 a1;
+ Struct9BytesHomogeneousUint82 a2;
+ Struct9BytesHomogeneousUint82 a3;
+ Struct9BytesHomogeneousUint82 a4;
+ Struct9BytesHomogeneousUint82 a5;
+ Struct9BytesHomogeneousUint82 a6;
+ Struct9BytesHomogeneousUint82 a7;
+ Struct9BytesHomogeneousUint82 a8;
+ Struct9BytesHomogeneousUint82 a9;
+
+ a0.a0 = 1;
+ a0.a1 = 2;
+ a0.a2 = 3;
+ a0.a3 = 4;
+ a0.a4 = 5;
+ a0.a5 = 6;
+ a0.a6 = 7;
+ a0.a7 = 8;
+ a0.a8 = 9;
+ a1.a0 = 10;
+ a1.a1 = 11;
+ a1.a2 = 12;
+ a1.a3 = 13;
+ a1.a4 = 14;
+ a1.a5 = 15;
+ a1.a6 = 16;
+ a1.a7 = 17;
+ a1.a8 = 18;
+ a2.a0 = 19;
+ a2.a1 = 20;
+ a2.a2 = 21;
+ a2.a3 = 22;
+ a2.a4 = 23;
+ a2.a5 = 24;
+ a2.a6 = 25;
+ a2.a7 = 26;
+ a2.a8 = 27;
+ a3.a0 = 28;
+ a3.a1 = 29;
+ a3.a2 = 30;
+ a3.a3 = 31;
+ a3.a4 = 32;
+ a3.a5 = 33;
+ a3.a6 = 34;
+ a3.a7 = 35;
+ a3.a8 = 36;
+ a4.a0 = 37;
+ a4.a1 = 38;
+ a4.a2 = 39;
+ a4.a3 = 40;
+ a4.a4 = 41;
+ a4.a5 = 42;
+ a4.a6 = 43;
+ a4.a7 = 44;
+ a4.a8 = 45;
+ a5.a0 = 46;
+ a5.a1 = 47;
+ a5.a2 = 48;
+ a5.a3 = 49;
+ a5.a4 = 50;
+ a5.a5 = 51;
+ a5.a6 = 52;
+ a5.a7 = 53;
+ a5.a8 = 54;
+ a6.a0 = 55;
+ a6.a1 = 56;
+ a6.a2 = 57;
+ a6.a3 = 58;
+ a6.a4 = 59;
+ a6.a5 = 60;
+ a6.a6 = 61;
+ a6.a7 = 62;
+ a6.a8 = 63;
+ a7.a0 = 64;
+ a7.a1 = 65;
+ a7.a2 = 66;
+ a7.a3 = 67;
+ a7.a4 = 68;
+ a7.a5 = 69;
+ a7.a6 = 70;
+ a7.a7 = 71;
+ a7.a8 = 72;
+ a8.a0 = 73;
+ a8.a1 = 74;
+ a8.a2 = 75;
+ a8.a3 = 76;
+ a8.a4 = 77;
+ a8.a5 = 78;
+ a8.a6 = 79;
+ a8.a7 = 80;
+ a8.a8 = 81;
+ a9.a0 = 82;
+ a9.a1 = 83;
+ a9.a2 = 84;
+ a9.a3 = 85;
+ a9.a4 = 86;
+ a9.a5 = 87;
+ a9.a6 = 88;
+ a9.a7 = 89;
+ a9.a8 = 90;
+
+ std::cout
+ << "Calling TestPassStruct9BytesHomogeneousUint82x10("
+ << "((" << static_cast<int>(a0.a0) << ", " << static_cast<int>(a0.a1)
+ << ", " << static_cast<int>(a0.a2) << ", " << static_cast<int>(a0.a3)
+ << ", " << static_cast<int>(a0.a4) << ", " << static_cast<int>(a0.a5)
+ << ", " << static_cast<int>(a0.a6) << ", " << static_cast<int>(a0.a7)
+ << ", " << static_cast<int>(a0.a8) << "), (" << static_cast<int>(a1.a0)
+ << ", " << static_cast<int>(a1.a1) << ", " << static_cast<int>(a1.a2)
+ << ", " << static_cast<int>(a1.a3) << ", " << static_cast<int>(a1.a4)
+ << ", " << static_cast<int>(a1.a5) << ", " << static_cast<int>(a1.a6)
+ << ", " << static_cast<int>(a1.a7) << ", " << static_cast<int>(a1.a8)
+ << "), (" << static_cast<int>(a2.a0) << ", " << static_cast<int>(a2.a1)
+ << ", " << static_cast<int>(a2.a2) << ", " << static_cast<int>(a2.a3)
+ << ", " << static_cast<int>(a2.a4) << ", " << static_cast<int>(a2.a5)
+ << ", " << static_cast<int>(a2.a6) << ", " << static_cast<int>(a2.a7)
+ << ", " << static_cast<int>(a2.a8) << "), (" << static_cast<int>(a3.a0)
+ << ", " << static_cast<int>(a3.a1) << ", " << static_cast<int>(a3.a2)
+ << ", " << static_cast<int>(a3.a3) << ", " << static_cast<int>(a3.a4)
+ << ", " << static_cast<int>(a3.a5) << ", " << static_cast<int>(a3.a6)
+ << ", " << static_cast<int>(a3.a7) << ", " << static_cast<int>(a3.a8)
+ << "), (" << static_cast<int>(a4.a0) << ", " << static_cast<int>(a4.a1)
+ << ", " << static_cast<int>(a4.a2) << ", " << static_cast<int>(a4.a3)
+ << ", " << static_cast<int>(a4.a4) << ", " << static_cast<int>(a4.a5)
+ << ", " << static_cast<int>(a4.a6) << ", " << static_cast<int>(a4.a7)
+ << ", " << static_cast<int>(a4.a8) << "), (" << static_cast<int>(a5.a0)
+ << ", " << static_cast<int>(a5.a1) << ", " << static_cast<int>(a5.a2)
+ << ", " << static_cast<int>(a5.a3) << ", " << static_cast<int>(a5.a4)
+ << ", " << static_cast<int>(a5.a5) << ", " << static_cast<int>(a5.a6)
+ << ", " << static_cast<int>(a5.a7) << ", " << static_cast<int>(a5.a8)
+ << "), (" << static_cast<int>(a6.a0) << ", " << static_cast<int>(a6.a1)
+ << ", " << static_cast<int>(a6.a2) << ", " << static_cast<int>(a6.a3)
+ << ", " << static_cast<int>(a6.a4) << ", " << static_cast<int>(a6.a5)
+ << ", " << static_cast<int>(a6.a6) << ", " << static_cast<int>(a6.a7)
+ << ", " << static_cast<int>(a6.a8) << "), (" << static_cast<int>(a7.a0)
+ << ", " << static_cast<int>(a7.a1) << ", " << static_cast<int>(a7.a2)
+ << ", " << static_cast<int>(a7.a3) << ", " << static_cast<int>(a7.a4)
+ << ", " << static_cast<int>(a7.a5) << ", " << static_cast<int>(a7.a6)
+ << ", " << static_cast<int>(a7.a7) << ", " << static_cast<int>(a7.a8)
+ << "), (" << static_cast<int>(a8.a0) << ", " << static_cast<int>(a8.a1)
+ << ", " << static_cast<int>(a8.a2) << ", " << static_cast<int>(a8.a3)
+ << ", " << static_cast<int>(a8.a4) << ", " << static_cast<int>(a8.a5)
+ << ", " << static_cast<int>(a8.a6) << ", " << static_cast<int>(a8.a7)
+ << ", " << static_cast<int>(a8.a8) << "), (" << static_cast<int>(a9.a0)
+ << ", " << static_cast<int>(a9.a1) << ", " << static_cast<int>(a9.a2)
+ << ", " << static_cast<int>(a9.a3) << ", " << static_cast<int>(a9.a4)
+ << ", " << static_cast<int>(a9.a5) << ", " << static_cast<int>(a9.a6)
+ << ", " << static_cast<int>(a9.a7) << ", " << static_cast<int>(a9.a8)
+ << "))"
+ << ")\n";
+
+ int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_EQ(4095, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_EQ(0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_EQ(0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Arguments in FPU registers on arm hardfp and arm64.
+// Struct arguments will exhaust available registers, and leave some empty.
+// The last argument is to test whether arguments are backfilled.
+DART_EXPORT intptr_t TestPassStruct12BytesHomogeneousFloatx6(
+ // NOLINTNEXTLINE(whitespace/parens)
+ float (*f)(Struct12BytesHomogeneousFloat a0,
+ Struct12BytesHomogeneousFloat a1,
+ Struct12BytesHomogeneousFloat a2,
+ Struct12BytesHomogeneousFloat a3,
+ Struct12BytesHomogeneousFloat a4,
+ Struct12BytesHomogeneousFloat a5)) {
+ Struct12BytesHomogeneousFloat a0;
+ Struct12BytesHomogeneousFloat a1;
+ Struct12BytesHomogeneousFloat a2;
+ Struct12BytesHomogeneousFloat a3;
+ Struct12BytesHomogeneousFloat a4;
+ Struct12BytesHomogeneousFloat a5;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a0.a2 = -3.0;
+ a1.a0 = 4.0;
+ a1.a1 = -5.0;
+ a1.a2 = 6.0;
+ a2.a0 = -7.0;
+ a2.a1 = 8.0;
+ a2.a2 = -9.0;
+ a3.a0 = 10.0;
+ a3.a1 = -11.0;
+ a3.a2 = 12.0;
+ a4.a0 = -13.0;
+ a4.a1 = 14.0;
+ a4.a2 = -15.0;
+ a5.a0 = 16.0;
+ a5.a1 = -17.0;
+ a5.a2 = 18.0;
+
+ std::cout << "Calling TestPassStruct12BytesHomogeneousFloatx6("
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << "), ("
+ << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << "), (" << a2.a0
+ << ", " << a2.a1 << ", " << a2.a2 << "), (" << a3.a0 << ", "
+ << a3.a1 << ", " << a3.a2 << "), (" << a4.a0 << ", " << a4.a1
+ << ", " << a4.a2 << "), (" << a5.a0 << ", " << a5.a1 << ", "
+ << a5.a2 << "))"
+ << ")\n";
+
+ float result = f(a0, a1, a2, a3, a4, a5);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_APPROX(9.0, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5);
+
+ CHECK_APPROX(0.0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5);
+
+ CHECK_APPROX(0.0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// On Linux x64 argument is transferred on stack because it is over 16 bytes.
+// Arguments in FPU registers on arm hardfp and arm64.
+// 5 struct arguments will exhaust available registers.
+DART_EXPORT intptr_t TestPassStruct16BytesHomogeneousFloatx5(
+ // NOLINTNEXTLINE(whitespace/parens)
+ float (*f)(Struct16BytesHomogeneousFloat a0,
+ Struct16BytesHomogeneousFloat a1,
+ Struct16BytesHomogeneousFloat a2,
+ Struct16BytesHomogeneousFloat a3,
+ Struct16BytesHomogeneousFloat a4)) {
+ Struct16BytesHomogeneousFloat a0;
+ Struct16BytesHomogeneousFloat a1;
+ Struct16BytesHomogeneousFloat a2;
+ Struct16BytesHomogeneousFloat a3;
+ Struct16BytesHomogeneousFloat a4;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a0.a2 = -3.0;
+ a0.a3 = 4.0;
+ a1.a0 = -5.0;
+ a1.a1 = 6.0;
+ a1.a2 = -7.0;
+ a1.a3 = 8.0;
+ a2.a0 = -9.0;
+ a2.a1 = 10.0;
+ a2.a2 = -11.0;
+ a2.a3 = 12.0;
+ a3.a0 = -13.0;
+ a3.a1 = 14.0;
+ a3.a2 = -15.0;
+ a3.a3 = 16.0;
+ a4.a0 = -17.0;
+ a4.a1 = 18.0;
+ a4.a2 = -19.0;
+ a4.a3 = 20.0;
+
+ std::cout << "Calling TestPassStruct16BytesHomogeneousFloatx5("
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3
+ << "), (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << ", "
+ << a1.a3 << "), (" << a2.a0 << ", " << a2.a1 << ", " << a2.a2
+ << ", " << a2.a3 << "), (" << a3.a0 << ", " << a3.a1 << ", "
+ << a3.a2 << ", " << a3.a3 << "), (" << a4.a0 << ", " << a4.a1
+ << ", " << a4.a2 << ", " << a4.a3 << "))"
+ << ")\n";
+
+ float result = f(a0, a1, a2, a3, a4);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_APPROX(10.0, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4);
+
+ CHECK_APPROX(0.0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4);
+
+ CHECK_APPROX(0.0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// On x64, arguments are split over FP and int registers.
+// On x64, it will exhaust the integer registers with the 6th argument.
+// The rest goes on the stack.
+// On arm, arguments are 8 byte aligned.
+DART_EXPORT intptr_t TestPassStruct16BytesMixedx10(
+ // NOLINTNEXTLINE(whitespace/parens)
+ double (*f)(Struct16BytesMixed a0,
+ Struct16BytesMixed a1,
+ Struct16BytesMixed a2,
+ Struct16BytesMixed a3,
+ Struct16BytesMixed a4,
+ Struct16BytesMixed a5,
+ Struct16BytesMixed a6,
+ Struct16BytesMixed a7,
+ Struct16BytesMixed a8,
+ Struct16BytesMixed a9)) {
+ Struct16BytesMixed a0;
+ Struct16BytesMixed a1;
+ Struct16BytesMixed a2;
+ Struct16BytesMixed a3;
+ Struct16BytesMixed a4;
+ Struct16BytesMixed a5;
+ Struct16BytesMixed a6;
+ Struct16BytesMixed a7;
+ Struct16BytesMixed a8;
+ Struct16BytesMixed a9;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2;
+ a1.a0 = -3.0;
+ a1.a1 = 4;
+ a2.a0 = -5.0;
+ a2.a1 = 6;
+ a3.a0 = -7.0;
+ a3.a1 = 8;
+ a4.a0 = -9.0;
+ a4.a1 = 10;
+ a5.a0 = -11.0;
+ a5.a1 = 12;
+ a6.a0 = -13.0;
+ a6.a1 = 14;
+ a7.a0 = -15.0;
+ a7.a1 = 16;
+ a8.a0 = -17.0;
+ a8.a1 = 18;
+ a9.a0 = -19.0;
+ a9.a1 = 20;
+
+ std::cout << "Calling TestPassStruct16BytesMixedx10("
+ << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << ", "
+ << a1.a1 << "), (" << a2.a0 << ", " << a2.a1 << "), (" << a3.a0
+ << ", " << a3.a1 << "), (" << a4.a0 << ", " << a4.a1 << "), ("
+ << a5.a0 << ", " << a5.a1 << "), (" << a6.a0 << ", " << a6.a1
+ << "), (" << a7.a0 << ", " << a7.a1 << "), (" << a8.a0 << ", "
+ << a8.a1 << "), (" << a9.a0 << ", " << a9.a1 << "))"
+ << ")\n";
+
+ double result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_APPROX(10.0, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_APPROX(0.0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_APPROX(0.0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// On x64, arguments are split over FP and int registers.
+// On x64, it will exhaust the integer registers with the 6th argument.
+// The rest goes on the stack.
+// On arm, arguments are 4 byte aligned.
+DART_EXPORT intptr_t TestPassStruct16BytesMixed2x10(
+ // NOLINTNEXTLINE(whitespace/parens)
+ float (*f)(Struct16BytesMixed2 a0,
+ Struct16BytesMixed2 a1,
+ Struct16BytesMixed2 a2,
+ Struct16BytesMixed2 a3,
+ Struct16BytesMixed2 a4,
+ Struct16BytesMixed2 a5,
+ Struct16BytesMixed2 a6,
+ Struct16BytesMixed2 a7,
+ Struct16BytesMixed2 a8,
+ Struct16BytesMixed2 a9)) {
+ Struct16BytesMixed2 a0;
+ Struct16BytesMixed2 a1;
+ Struct16BytesMixed2 a2;
+ Struct16BytesMixed2 a3;
+ Struct16BytesMixed2 a4;
+ Struct16BytesMixed2 a5;
+ Struct16BytesMixed2 a6;
+ Struct16BytesMixed2 a7;
+ Struct16BytesMixed2 a8;
+ Struct16BytesMixed2 a9;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a0.a2 = -3.0;
+ a0.a3 = 4;
+ a1.a0 = -5.0;
+ a1.a1 = 6.0;
+ a1.a2 = -7.0;
+ a1.a3 = 8;
+ a2.a0 = -9.0;
+ a2.a1 = 10.0;
+ a2.a2 = -11.0;
+ a2.a3 = 12;
+ a3.a0 = -13.0;
+ a3.a1 = 14.0;
+ a3.a2 = -15.0;
+ a3.a3 = 16;
+ a4.a0 = -17.0;
+ a4.a1 = 18.0;
+ a4.a2 = -19.0;
+ a4.a3 = 20;
+ a5.a0 = -21.0;
+ a5.a1 = 22.0;
+ a5.a2 = -23.0;
+ a5.a3 = 24;
+ a6.a0 = -25.0;
+ a6.a1 = 26.0;
+ a6.a2 = -27.0;
+ a6.a3 = 28;
+ a7.a0 = -29.0;
+ a7.a1 = 30.0;
+ a7.a2 = -31.0;
+ a7.a3 = 32;
+ a8.a0 = -33.0;
+ a8.a1 = 34.0;
+ a8.a2 = -35.0;
+ a8.a3 = 36;
+ a9.a0 = -37.0;
+ a9.a1 = 38.0;
+ a9.a2 = -39.0;
+ a9.a3 = 40;
+
+ std::cout << "Calling TestPassStruct16BytesMixed2x10("
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3
+ << "), (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << ", "
+ << a1.a3 << "), (" << a2.a0 << ", " << a2.a1 << ", " << a2.a2
+ << ", " << a2.a3 << "), (" << a3.a0 << ", " << a3.a1 << ", "
+ << a3.a2 << ", " << a3.a3 << "), (" << a4.a0 << ", " << a4.a1
+ << ", " << a4.a2 << ", " << a4.a3 << "), (" << a5.a0 << ", "
+ << a5.a1 << ", " << a5.a2 << ", " << a5.a3 << "), (" << a6.a0
+ << ", " << a6.a1 << ", " << a6.a2 << ", " << a6.a3 << "), ("
+ << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << ", " << a7.a3
+ << "), (" << a8.a0 << ", " << a8.a1 << ", " << a8.a2 << ", "
+ << a8.a3 << "), (" << a9.a0 << ", " << a9.a1 << ", " << a9.a2
+ << ", " << a9.a3 << "))"
+ << ")\n";
+
+ float result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_APPROX(20.0, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_APPROX(0.0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_APPROX(0.0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Arguments are passed as pointer to copy on arm64.
+// Tests that the memory allocated for copies are rounded up to word size.
+DART_EXPORT intptr_t TestPassStruct17BytesIntx10(
+ // NOLINTNEXTLINE(whitespace/parens)
+ int64_t (*f)(Struct17BytesInt a0,
+ Struct17BytesInt a1,
+ Struct17BytesInt a2,
+ Struct17BytesInt a3,
+ Struct17BytesInt a4,
+ Struct17BytesInt a5,
+ Struct17BytesInt a6,
+ Struct17BytesInt a7,
+ Struct17BytesInt a8,
+ Struct17BytesInt a9)) {
+ Struct17BytesInt a0;
+ Struct17BytesInt a1;
+ Struct17BytesInt a2;
+ Struct17BytesInt a3;
+ Struct17BytesInt a4;
+ Struct17BytesInt a5;
+ Struct17BytesInt a6;
+ Struct17BytesInt a7;
+ Struct17BytesInt a8;
+ Struct17BytesInt a9;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+ a1.a0 = 4;
+ a1.a1 = -5;
+ a1.a2 = 6;
+ a2.a0 = -7;
+ a2.a1 = 8;
+ a2.a2 = -9;
+ a3.a0 = 10;
+ a3.a1 = -11;
+ a3.a2 = 12;
+ a4.a0 = -13;
+ a4.a1 = 14;
+ a4.a2 = -15;
+ a5.a0 = 16;
+ a5.a1 = -17;
+ a5.a2 = 18;
+ a6.a0 = -19;
+ a6.a1 = 20;
+ a6.a2 = -21;
+ a7.a0 = 22;
+ a7.a1 = -23;
+ a7.a2 = 24;
+ a8.a0 = -25;
+ a8.a1 = 26;
+ a8.a2 = -27;
+ a9.a0 = 28;
+ a9.a1 = -29;
+ a9.a2 = 30;
+
+ std::cout << "Calling TestPassStruct17BytesIntx10("
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << static_cast<int>(a0.a2)
+ << "), (" << a1.a0 << ", " << a1.a1 << ", "
+ << static_cast<int>(a1.a2) << "), (" << a2.a0 << ", " << a2.a1
+ << ", " << static_cast<int>(a2.a2) << "), (" << a3.a0 << ", "
+ << a3.a1 << ", " << static_cast<int>(a3.a2) << "), (" << a4.a0
+ << ", " << a4.a1 << ", " << static_cast<int>(a4.a2) << "), ("
+ << a5.a0 << ", " << a5.a1 << ", " << static_cast<int>(a5.a2)
+ << "), (" << a6.a0 << ", " << a6.a1 << ", "
+ << static_cast<int>(a6.a2) << "), (" << a7.a0 << ", " << a7.a1
+ << ", " << static_cast<int>(a7.a2) << "), (" << a8.a0 << ", "
+ << a8.a1 << ", " << static_cast<int>(a8.a2) << "), (" << a9.a0
+ << ", " << a9.a1 << ", " << static_cast<int>(a9.a2) << "))"
+ << ")\n";
+
+ int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_EQ(15, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_EQ(0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_EQ(0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// The minimum alignment of this struct is only 1 byte based on its fields.
+// Test that the memory backing these structs is extended to the right size.
+//
+DART_EXPORT intptr_t TestPassStruct19BytesHomogeneousUint8x10(
+ // NOLINTNEXTLINE(whitespace/parens)
+ int64_t (*f)(Struct19BytesHomogeneousUint8 a0,
+ Struct19BytesHomogeneousUint8 a1,
+ Struct19BytesHomogeneousUint8 a2,
+ Struct19BytesHomogeneousUint8 a3,
+ Struct19BytesHomogeneousUint8 a4,
+ Struct19BytesHomogeneousUint8 a5,
+ Struct19BytesHomogeneousUint8 a6,
+ Struct19BytesHomogeneousUint8 a7,
+ Struct19BytesHomogeneousUint8 a8,
+ Struct19BytesHomogeneousUint8 a9)) {
+ Struct19BytesHomogeneousUint8 a0;
+ Struct19BytesHomogeneousUint8 a1;
+ Struct19BytesHomogeneousUint8 a2;
+ Struct19BytesHomogeneousUint8 a3;
+ Struct19BytesHomogeneousUint8 a4;
+ Struct19BytesHomogeneousUint8 a5;
+ Struct19BytesHomogeneousUint8 a6;
+ Struct19BytesHomogeneousUint8 a7;
+ Struct19BytesHomogeneousUint8 a8;
+ Struct19BytesHomogeneousUint8 a9;
+
+ a0.a0 = 1;
+ a0.a1 = 2;
+ a0.a2 = 3;
+ a0.a3 = 4;
+ a0.a4 = 5;
+ a0.a5 = 6;
+ a0.a6 = 7;
+ a0.a7 = 8;
+ a0.a8 = 9;
+ a0.a9 = 10;
+ a0.a10 = 11;
+ a0.a11 = 12;
+ a0.a12 = 13;
+ a0.a13 = 14;
+ a0.a14 = 15;
+ a0.a15 = 16;
+ a0.a16 = 17;
+ a0.a17 = 18;
+ a0.a18 = 19;
+ a1.a0 = 20;
+ a1.a1 = 21;
+ a1.a2 = 22;
+ a1.a3 = 23;
+ a1.a4 = 24;
+ a1.a5 = 25;
+ a1.a6 = 26;
+ a1.a7 = 27;
+ a1.a8 = 28;
+ a1.a9 = 29;
+ a1.a10 = 30;
+ a1.a11 = 31;
+ a1.a12 = 32;
+ a1.a13 = 33;
+ a1.a14 = 34;
+ a1.a15 = 35;
+ a1.a16 = 36;
+ a1.a17 = 37;
+ a1.a18 = 38;
+ a2.a0 = 39;
+ a2.a1 = 40;
+ a2.a2 = 41;
+ a2.a3 = 42;
+ a2.a4 = 43;
+ a2.a5 = 44;
+ a2.a6 = 45;
+ a2.a7 = 46;
+ a2.a8 = 47;
+ a2.a9 = 48;
+ a2.a10 = 49;
+ a2.a11 = 50;
+ a2.a12 = 51;
+ a2.a13 = 52;
+ a2.a14 = 53;
+ a2.a15 = 54;
+ a2.a16 = 55;
+ a2.a17 = 56;
+ a2.a18 = 57;
+ a3.a0 = 58;
+ a3.a1 = 59;
+ a3.a2 = 60;
+ a3.a3 = 61;
+ a3.a4 = 62;
+ a3.a5 = 63;
+ a3.a6 = 64;
+ a3.a7 = 65;
+ a3.a8 = 66;
+ a3.a9 = 67;
+ a3.a10 = 68;
+ a3.a11 = 69;
+ a3.a12 = 70;
+ a3.a13 = 71;
+ a3.a14 = 72;
+ a3.a15 = 73;
+ a3.a16 = 74;
+ a3.a17 = 75;
+ a3.a18 = 76;
+ a4.a0 = 77;
+ a4.a1 = 78;
+ a4.a2 = 79;
+ a4.a3 = 80;
+ a4.a4 = 81;
+ a4.a5 = 82;
+ a4.a6 = 83;
+ a4.a7 = 84;
+ a4.a8 = 85;
+ a4.a9 = 86;
+ a4.a10 = 87;
+ a4.a11 = 88;
+ a4.a12 = 89;
+ a4.a13 = 90;
+ a4.a14 = 91;
+ a4.a15 = 92;
+ a4.a16 = 93;
+ a4.a17 = 94;
+ a4.a18 = 95;
+ a5.a0 = 96;
+ a5.a1 = 97;
+ a5.a2 = 98;
+ a5.a3 = 99;
+ a5.a4 = 100;
+ a5.a5 = 101;
+ a5.a6 = 102;
+ a5.a7 = 103;
+ a5.a8 = 104;
+ a5.a9 = 105;
+ a5.a10 = 106;
+ a5.a11 = 107;
+ a5.a12 = 108;
+ a5.a13 = 109;
+ a5.a14 = 110;
+ a5.a15 = 111;
+ a5.a16 = 112;
+ a5.a17 = 113;
+ a5.a18 = 114;
+ a6.a0 = 115;
+ a6.a1 = 116;
+ a6.a2 = 117;
+ a6.a3 = 118;
+ a6.a4 = 119;
+ a6.a5 = 120;
+ a6.a6 = 121;
+ a6.a7 = 122;
+ a6.a8 = 123;
+ a6.a9 = 124;
+ a6.a10 = 125;
+ a6.a11 = 126;
+ a6.a12 = 127;
+ a6.a13 = 128;
+ a6.a14 = 129;
+ a6.a15 = 130;
+ a6.a16 = 131;
+ a6.a17 = 132;
+ a6.a18 = 133;
+ a7.a0 = 134;
+ a7.a1 = 135;
+ a7.a2 = 136;
+ a7.a3 = 137;
+ a7.a4 = 138;
+ a7.a5 = 139;
+ a7.a6 = 140;
+ a7.a7 = 141;
+ a7.a8 = 142;
+ a7.a9 = 143;
+ a7.a10 = 144;
+ a7.a11 = 145;
+ a7.a12 = 146;
+ a7.a13 = 147;
+ a7.a14 = 148;
+ a7.a15 = 149;
+ a7.a16 = 150;
+ a7.a17 = 151;
+ a7.a18 = 152;
+ a8.a0 = 153;
+ a8.a1 = 154;
+ a8.a2 = 155;
+ a8.a3 = 156;
+ a8.a4 = 157;
+ a8.a5 = 158;
+ a8.a6 = 159;
+ a8.a7 = 160;
+ a8.a8 = 161;
+ a8.a9 = 162;
+ a8.a10 = 163;
+ a8.a11 = 164;
+ a8.a12 = 165;
+ a8.a13 = 166;
+ a8.a14 = 167;
+ a8.a15 = 168;
+ a8.a16 = 169;
+ a8.a17 = 170;
+ a8.a18 = 171;
+ a9.a0 = 172;
+ a9.a1 = 173;
+ a9.a2 = 174;
+ a9.a3 = 175;
+ a9.a4 = 176;
+ a9.a5 = 177;
+ a9.a6 = 178;
+ a9.a7 = 179;
+ a9.a8 = 180;
+ a9.a9 = 181;
+ a9.a10 = 182;
+ a9.a11 = 183;
+ a9.a12 = 184;
+ a9.a13 = 185;
+ a9.a14 = 186;
+ a9.a15 = 187;
+ a9.a16 = 188;
+ a9.a17 = 189;
+ a9.a18 = 190;
+
+ std::cout
+ << "Calling TestPassStruct19BytesHomogeneousUint8x10("
+ << "((" << static_cast<int>(a0.a0) << ", " << static_cast<int>(a0.a1)
+ << ", " << static_cast<int>(a0.a2) << ", " << static_cast<int>(a0.a3)
+ << ", " << static_cast<int>(a0.a4) << ", " << static_cast<int>(a0.a5)
+ << ", " << static_cast<int>(a0.a6) << ", " << static_cast<int>(a0.a7)
+ << ", " << static_cast<int>(a0.a8) << ", " << static_cast<int>(a0.a9)
+ << ", " << static_cast<int>(a0.a10) << ", " << static_cast<int>(a0.a11)
+ << ", " << static_cast<int>(a0.a12) << ", " << static_cast<int>(a0.a13)
+ << ", " << static_cast<int>(a0.a14) << ", " << static_cast<int>(a0.a15)
+ << ", " << static_cast<int>(a0.a16) << ", " << static_cast<int>(a0.a17)
+ << ", " << static_cast<int>(a0.a18) << "), (" << static_cast<int>(a1.a0)
+ << ", " << static_cast<int>(a1.a1) << ", " << static_cast<int>(a1.a2)
+ << ", " << static_cast<int>(a1.a3) << ", " << static_cast<int>(a1.a4)
+ << ", " << static_cast<int>(a1.a5) << ", " << static_cast<int>(a1.a6)
+ << ", " << static_cast<int>(a1.a7) << ", " << static_cast<int>(a1.a8)
+ << ", " << static_cast<int>(a1.a9) << ", " << static_cast<int>(a1.a10)
+ << ", " << static_cast<int>(a1.a11) << ", " << static_cast<int>(a1.a12)
+ << ", " << static_cast<int>(a1.a13) << ", " << static_cast<int>(a1.a14)
+ << ", " << static_cast<int>(a1.a15) << ", " << static_cast<int>(a1.a16)
+ << ", " << static_cast<int>(a1.a17) << ", " << static_cast<int>(a1.a18)
+ << "), (" << static_cast<int>(a2.a0) << ", " << static_cast<int>(a2.a1)
+ << ", " << static_cast<int>(a2.a2) << ", " << static_cast<int>(a2.a3)
+ << ", " << static_cast<int>(a2.a4) << ", " << static_cast<int>(a2.a5)
+ << ", " << static_cast<int>(a2.a6) << ", " << static_cast<int>(a2.a7)
+ << ", " << static_cast<int>(a2.a8) << ", " << static_cast<int>(a2.a9)
+ << ", " << static_cast<int>(a2.a10) << ", " << static_cast<int>(a2.a11)
+ << ", " << static_cast<int>(a2.a12) << ", " << static_cast<int>(a2.a13)
+ << ", " << static_cast<int>(a2.a14) << ", " << static_cast<int>(a2.a15)
+ << ", " << static_cast<int>(a2.a16) << ", " << static_cast<int>(a2.a17)
+ << ", " << static_cast<int>(a2.a18) << "), (" << static_cast<int>(a3.a0)
+ << ", " << static_cast<int>(a3.a1) << ", " << static_cast<int>(a3.a2)
+ << ", " << static_cast<int>(a3.a3) << ", " << static_cast<int>(a3.a4)
+ << ", " << static_cast<int>(a3.a5) << ", " << static_cast<int>(a3.a6)
+ << ", " << static_cast<int>(a3.a7) << ", " << static_cast<int>(a3.a8)
+ << ", " << static_cast<int>(a3.a9) << ", " << static_cast<int>(a3.a10)
+ << ", " << static_cast<int>(a3.a11) << ", " << static_cast<int>(a3.a12)
+ << ", " << static_cast<int>(a3.a13) << ", " << static_cast<int>(a3.a14)
+ << ", " << static_cast<int>(a3.a15) << ", " << static_cast<int>(a3.a16)
+ << ", " << static_cast<int>(a3.a17) << ", " << static_cast<int>(a3.a18)
+ << "), (" << static_cast<int>(a4.a0) << ", " << static_cast<int>(a4.a1)
+ << ", " << static_cast<int>(a4.a2) << ", " << static_cast<int>(a4.a3)
+ << ", " << static_cast<int>(a4.a4) << ", " << static_cast<int>(a4.a5)
+ << ", " << static_cast<int>(a4.a6) << ", " << static_cast<int>(a4.a7)
+ << ", " << static_cast<int>(a4.a8) << ", " << static_cast<int>(a4.a9)
+ << ", " << static_cast<int>(a4.a10) << ", " << static_cast<int>(a4.a11)
+ << ", " << static_cast<int>(a4.a12) << ", " << static_cast<int>(a4.a13)
+ << ", " << static_cast<int>(a4.a14) << ", " << static_cast<int>(a4.a15)
+ << ", " << static_cast<int>(a4.a16) << ", " << static_cast<int>(a4.a17)
+ << ", " << static_cast<int>(a4.a18) << "), (" << static_cast<int>(a5.a0)
+ << ", " << static_cast<int>(a5.a1) << ", " << static_cast<int>(a5.a2)
+ << ", " << static_cast<int>(a5.a3) << ", " << static_cast<int>(a5.a4)
+ << ", " << static_cast<int>(a5.a5) << ", " << static_cast<int>(a5.a6)
+ << ", " << static_cast<int>(a5.a7) << ", " << static_cast<int>(a5.a8)
+ << ", " << static_cast<int>(a5.a9) << ", " << static_cast<int>(a5.a10)
+ << ", " << static_cast<int>(a5.a11) << ", " << static_cast<int>(a5.a12)
+ << ", " << static_cast<int>(a5.a13) << ", " << static_cast<int>(a5.a14)
+ << ", " << static_cast<int>(a5.a15) << ", " << static_cast<int>(a5.a16)
+ << ", " << static_cast<int>(a5.a17) << ", " << static_cast<int>(a5.a18)
+ << "), (" << static_cast<int>(a6.a0) << ", " << static_cast<int>(a6.a1)
+ << ", " << static_cast<int>(a6.a2) << ", " << static_cast<int>(a6.a3)
+ << ", " << static_cast<int>(a6.a4) << ", " << static_cast<int>(a6.a5)
+ << ", " << static_cast<int>(a6.a6) << ", " << static_cast<int>(a6.a7)
+ << ", " << static_cast<int>(a6.a8) << ", " << static_cast<int>(a6.a9)
+ << ", " << static_cast<int>(a6.a10) << ", " << static_cast<int>(a6.a11)
+ << ", " << static_cast<int>(a6.a12) << ", " << static_cast<int>(a6.a13)
+ << ", " << static_cast<int>(a6.a14) << ", " << static_cast<int>(a6.a15)
+ << ", " << static_cast<int>(a6.a16) << ", " << static_cast<int>(a6.a17)
+ << ", " << static_cast<int>(a6.a18) << "), (" << static_cast<int>(a7.a0)
+ << ", " << static_cast<int>(a7.a1) << ", " << static_cast<int>(a7.a2)
+ << ", " << static_cast<int>(a7.a3) << ", " << static_cast<int>(a7.a4)
+ << ", " << static_cast<int>(a7.a5) << ", " << static_cast<int>(a7.a6)
+ << ", " << static_cast<int>(a7.a7) << ", " << static_cast<int>(a7.a8)
+ << ", " << static_cast<int>(a7.a9) << ", " << static_cast<int>(a7.a10)
+ << ", " << static_cast<int>(a7.a11) << ", " << static_cast<int>(a7.a12)
+ << ", " << static_cast<int>(a7.a13) << ", " << static_cast<int>(a7.a14)
+ << ", " << static_cast<int>(a7.a15) << ", " << static_cast<int>(a7.a16)
+ << ", " << static_cast<int>(a7.a17) << ", " << static_cast<int>(a7.a18)
+ << "), (" << static_cast<int>(a8.a0) << ", " << static_cast<int>(a8.a1)
+ << ", " << static_cast<int>(a8.a2) << ", " << static_cast<int>(a8.a3)
+ << ", " << static_cast<int>(a8.a4) << ", " << static_cast<int>(a8.a5)
+ << ", " << static_cast<int>(a8.a6) << ", " << static_cast<int>(a8.a7)
+ << ", " << static_cast<int>(a8.a8) << ", " << static_cast<int>(a8.a9)
+ << ", " << static_cast<int>(a8.a10) << ", " << static_cast<int>(a8.a11)
+ << ", " << static_cast<int>(a8.a12) << ", " << static_cast<int>(a8.a13)
+ << ", " << static_cast<int>(a8.a14) << ", " << static_cast<int>(a8.a15)
+ << ", " << static_cast<int>(a8.a16) << ", " << static_cast<int>(a8.a17)
+ << ", " << static_cast<int>(a8.a18) << "), (" << static_cast<int>(a9.a0)
+ << ", " << static_cast<int>(a9.a1) << ", " << static_cast<int>(a9.a2)
+ << ", " << static_cast<int>(a9.a3) << ", " << static_cast<int>(a9.a4)
+ << ", " << static_cast<int>(a9.a5) << ", " << static_cast<int>(a9.a6)
+ << ", " << static_cast<int>(a9.a7) << ", " << static_cast<int>(a9.a8)
+ << ", " << static_cast<int>(a9.a9) << ", " << static_cast<int>(a9.a10)
+ << ", " << static_cast<int>(a9.a11) << ", " << static_cast<int>(a9.a12)
+ << ", " << static_cast<int>(a9.a13) << ", " << static_cast<int>(a9.a14)
+ << ", " << static_cast<int>(a9.a15) << ", " << static_cast<int>(a9.a16)
+ << ", " << static_cast<int>(a9.a17) << ", " << static_cast<int>(a9.a18)
+ << "))"
+ << ")\n";
+
+ int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_EQ(18145, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_EQ(0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_EQ(0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Argument too big to go into integer registers on arm64.
+// The arguments are passed as pointers to copies.
+// The amount of arguments exhausts the number of integer registers, such that
+// pointers to copies are also passed on the stack.
+DART_EXPORT intptr_t TestPassStruct20BytesHomogeneousInt32x10(
+ // NOLINTNEXTLINE(whitespace/parens)
+ int32_t (*f)(Struct20BytesHomogeneousInt32 a0,
+ Struct20BytesHomogeneousInt32 a1,
+ Struct20BytesHomogeneousInt32 a2,
+ Struct20BytesHomogeneousInt32 a3,
+ Struct20BytesHomogeneousInt32 a4,
+ Struct20BytesHomogeneousInt32 a5,
+ Struct20BytesHomogeneousInt32 a6,
+ Struct20BytesHomogeneousInt32 a7,
+ Struct20BytesHomogeneousInt32 a8,
+ Struct20BytesHomogeneousInt32 a9)) {
+ Struct20BytesHomogeneousInt32 a0;
+ Struct20BytesHomogeneousInt32 a1;
+ Struct20BytesHomogeneousInt32 a2;
+ Struct20BytesHomogeneousInt32 a3;
+ Struct20BytesHomogeneousInt32 a4;
+ Struct20BytesHomogeneousInt32 a5;
+ Struct20BytesHomogeneousInt32 a6;
+ Struct20BytesHomogeneousInt32 a7;
+ Struct20BytesHomogeneousInt32 a8;
+ Struct20BytesHomogeneousInt32 a9;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+ a0.a3 = 4;
+ a0.a4 = -5;
+ a1.a0 = 6;
+ a1.a1 = -7;
+ a1.a2 = 8;
+ a1.a3 = -9;
+ a1.a4 = 10;
+ a2.a0 = -11;
+ a2.a1 = 12;
+ a2.a2 = -13;
+ a2.a3 = 14;
+ a2.a4 = -15;
+ a3.a0 = 16;
+ a3.a1 = -17;
+ a3.a2 = 18;
+ a3.a3 = -19;
+ a3.a4 = 20;
+ a4.a0 = -21;
+ a4.a1 = 22;
+ a4.a2 = -23;
+ a4.a3 = 24;
+ a4.a4 = -25;
+ a5.a0 = 26;
+ a5.a1 = -27;
+ a5.a2 = 28;
+ a5.a3 = -29;
+ a5.a4 = 30;
+ a6.a0 = -31;
+ a6.a1 = 32;
+ a6.a2 = -33;
+ a6.a3 = 34;
+ a6.a4 = -35;
+ a7.a0 = 36;
+ a7.a1 = -37;
+ a7.a2 = 38;
+ a7.a3 = -39;
+ a7.a4 = 40;
+ a8.a0 = -41;
+ a8.a1 = 42;
+ a8.a2 = -43;
+ a8.a3 = 44;
+ a8.a4 = -45;
+ a9.a0 = 46;
+ a9.a1 = -47;
+ a9.a2 = 48;
+ a9.a3 = -49;
+ a9.a4 = 50;
+
+ std::cout << "Calling TestPassStruct20BytesHomogeneousInt32x10("
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3
+ << ", " << a0.a4 << "), (" << a1.a0 << ", " << a1.a1 << ", "
+ << a1.a2 << ", " << a1.a3 << ", " << a1.a4 << "), (" << a2.a0
+ << ", " << a2.a1 << ", " << a2.a2 << ", " << a2.a3 << ", " << a2.a4
+ << "), (" << a3.a0 << ", " << a3.a1 << ", " << a3.a2 << ", "
+ << a3.a3 << ", " << a3.a4 << "), (" << a4.a0 << ", " << a4.a1
+ << ", " << a4.a2 << ", " << a4.a3 << ", " << a4.a4 << "), ("
+ << a5.a0 << ", " << a5.a1 << ", " << a5.a2 << ", " << a5.a3 << ", "
+ << a5.a4 << "), (" << a6.a0 << ", " << a6.a1 << ", " << a6.a2
+ << ", " << a6.a3 << ", " << a6.a4 << "), (" << a7.a0 << ", "
+ << a7.a1 << ", " << a7.a2 << ", " << a7.a3 << ", " << a7.a4
+ << "), (" << a8.a0 << ", " << a8.a1 << ", " << a8.a2 << ", "
+ << a8.a3 << ", " << a8.a4 << "), (" << a9.a0 << ", " << a9.a1
+ << ", " << a9.a2 << ", " << a9.a3 << ", " << a9.a4 << "))"
+ << ")\n";
+
+ int32_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_EQ(25, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_EQ(0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ CHECK_EQ(0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Argument too big to go into FPU registers in hardfp and arm64.
+DART_EXPORT intptr_t TestPassStruct20BytesHomogeneousFloat(
+ // NOLINTNEXTLINE(whitespace/parens)
+ float (*f)(Struct20BytesHomogeneousFloat a0)) {
+ Struct20BytesHomogeneousFloat a0;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a0.a2 = -3.0;
+ a0.a3 = 4.0;
+ a0.a4 = -5.0;
+
+ std::cout << "Calling TestPassStruct20BytesHomogeneousFloat("
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3
+ << ", " << a0.a4 << "))"
+ << ")\n";
+
+ float result = f(a0);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_APPROX(-3.0, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0);
+
+ CHECK_APPROX(0.0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0);
+
+ CHECK_APPROX(0.0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Arguments in FPU registers on arm64.
+// 5 struct arguments will exhaust available registers.
+DART_EXPORT intptr_t TestPassStruct32BytesHomogeneousDoublex5(
+ // NOLINTNEXTLINE(whitespace/parens)
+ double (*f)(Struct32BytesHomogeneousDouble a0,
+ Struct32BytesHomogeneousDouble a1,
+ Struct32BytesHomogeneousDouble a2,
+ Struct32BytesHomogeneousDouble a3,
+ Struct32BytesHomogeneousDouble a4)) {
+ Struct32BytesHomogeneousDouble a0;
+ Struct32BytesHomogeneousDouble a1;
+ Struct32BytesHomogeneousDouble a2;
+ Struct32BytesHomogeneousDouble a3;
+ Struct32BytesHomogeneousDouble a4;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a0.a2 = -3.0;
+ a0.a3 = 4.0;
+ a1.a0 = -5.0;
+ a1.a1 = 6.0;
+ a1.a2 = -7.0;
+ a1.a3 = 8.0;
+ a2.a0 = -9.0;
+ a2.a1 = 10.0;
+ a2.a2 = -11.0;
+ a2.a3 = 12.0;
+ a3.a0 = -13.0;
+ a3.a1 = 14.0;
+ a3.a2 = -15.0;
+ a3.a3 = 16.0;
+ a4.a0 = -17.0;
+ a4.a1 = 18.0;
+ a4.a2 = -19.0;
+ a4.a3 = 20.0;
+
+ std::cout << "Calling TestPassStruct32BytesHomogeneousDoublex5("
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3
+ << "), (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << ", "
+ << a1.a3 << "), (" << a2.a0 << ", " << a2.a1 << ", " << a2.a2
+ << ", " << a2.a3 << "), (" << a3.a0 << ", " << a3.a1 << ", "
+ << a3.a2 << ", " << a3.a3 << "), (" << a4.a0 << ", " << a4.a1
+ << ", " << a4.a2 << ", " << a4.a3 << "))"
+ << ")\n";
+
+ double result = f(a0, a1, a2, a3, a4);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_APPROX(10.0, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4);
+
+ CHECK_APPROX(0.0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4);
+
+ CHECK_APPROX(0.0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Argument too big to go into FPU registers in arm64.
+DART_EXPORT intptr_t TestPassStruct40BytesHomogeneousDouble(
+ // NOLINTNEXTLINE(whitespace/parens)
+ double (*f)(Struct40BytesHomogeneousDouble a0)) {
+ Struct40BytesHomogeneousDouble a0;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a0.a2 = -3.0;
+ a0.a3 = 4.0;
+ a0.a4 = -5.0;
+
+ std::cout << "Calling TestPassStruct40BytesHomogeneousDouble("
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3
+ << ", " << a0.a4 << "))"
+ << ")\n";
+
+ double result = f(a0);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_APPROX(-3.0, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0);
+
+ CHECK_APPROX(0.0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0);
+
+ CHECK_APPROX(0.0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Test 1kb struct.
+DART_EXPORT intptr_t TestPassStruct1024BytesHomogeneousUint64(
+ // NOLINTNEXTLINE(whitespace/parens)
+ uint64_t (*f)(Struct1024BytesHomogeneousUint64 a0)) {
+ Struct1024BytesHomogeneousUint64 a0;
+
+ a0.a0 = 1;
+ a0.a1 = 2;
+ a0.a2 = 3;
+ a0.a3 = 4;
+ a0.a4 = 5;
+ a0.a5 = 6;
+ a0.a6 = 7;
+ a0.a7 = 8;
+ a0.a8 = 9;
+ a0.a9 = 10;
+ a0.a10 = 11;
+ a0.a11 = 12;
+ a0.a12 = 13;
+ a0.a13 = 14;
+ a0.a14 = 15;
+ a0.a15 = 16;
+ a0.a16 = 17;
+ a0.a17 = 18;
+ a0.a18 = 19;
+ a0.a19 = 20;
+ a0.a20 = 21;
+ a0.a21 = 22;
+ a0.a22 = 23;
+ a0.a23 = 24;
+ a0.a24 = 25;
+ a0.a25 = 26;
+ a0.a26 = 27;
+ a0.a27 = 28;
+ a0.a28 = 29;
+ a0.a29 = 30;
+ a0.a30 = 31;
+ a0.a31 = 32;
+ a0.a32 = 33;
+ a0.a33 = 34;
+ a0.a34 = 35;
+ a0.a35 = 36;
+ a0.a36 = 37;
+ a0.a37 = 38;
+ a0.a38 = 39;
+ a0.a39 = 40;
+ a0.a40 = 41;
+ a0.a41 = 42;
+ a0.a42 = 43;
+ a0.a43 = 44;
+ a0.a44 = 45;
+ a0.a45 = 46;
+ a0.a46 = 47;
+ a0.a47 = 48;
+ a0.a48 = 49;
+ a0.a49 = 50;
+ a0.a50 = 51;
+ a0.a51 = 52;
+ a0.a52 = 53;
+ a0.a53 = 54;
+ a0.a54 = 55;
+ a0.a55 = 56;
+ a0.a56 = 57;
+ a0.a57 = 58;
+ a0.a58 = 59;
+ a0.a59 = 60;
+ a0.a60 = 61;
+ a0.a61 = 62;
+ a0.a62 = 63;
+ a0.a63 = 64;
+ a0.a64 = 65;
+ a0.a65 = 66;
+ a0.a66 = 67;
+ a0.a67 = 68;
+ a0.a68 = 69;
+ a0.a69 = 70;
+ a0.a70 = 71;
+ a0.a71 = 72;
+ a0.a72 = 73;
+ a0.a73 = 74;
+ a0.a74 = 75;
+ a0.a75 = 76;
+ a0.a76 = 77;
+ a0.a77 = 78;
+ a0.a78 = 79;
+ a0.a79 = 80;
+ a0.a80 = 81;
+ a0.a81 = 82;
+ a0.a82 = 83;
+ a0.a83 = 84;
+ a0.a84 = 85;
+ a0.a85 = 86;
+ a0.a86 = 87;
+ a0.a87 = 88;
+ a0.a88 = 89;
+ a0.a89 = 90;
+ a0.a90 = 91;
+ a0.a91 = 92;
+ a0.a92 = 93;
+ a0.a93 = 94;
+ a0.a94 = 95;
+ a0.a95 = 96;
+ a0.a96 = 97;
+ a0.a97 = 98;
+ a0.a98 = 99;
+ a0.a99 = 100;
+ a0.a100 = 101;
+ a0.a101 = 102;
+ a0.a102 = 103;
+ a0.a103 = 104;
+ a0.a104 = 105;
+ a0.a105 = 106;
+ a0.a106 = 107;
+ a0.a107 = 108;
+ a0.a108 = 109;
+ a0.a109 = 110;
+ a0.a110 = 111;
+ a0.a111 = 112;
+ a0.a112 = 113;
+ a0.a113 = 114;
+ a0.a114 = 115;
+ a0.a115 = 116;
+ a0.a116 = 117;
+ a0.a117 = 118;
+ a0.a118 = 119;
+ a0.a119 = 120;
+ a0.a120 = 121;
+ a0.a121 = 122;
+ a0.a122 = 123;
+ a0.a123 = 124;
+ a0.a124 = 125;
+ a0.a125 = 126;
+ a0.a126 = 127;
+ a0.a127 = 128;
+
+ std::cout << "Calling TestPassStruct1024BytesHomogeneousUint64("
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3
+ << ", " << a0.a4 << ", " << a0.a5 << ", " << a0.a6 << ", " << a0.a7
+ << ", " << a0.a8 << ", " << a0.a9 << ", " << a0.a10 << ", "
+ << a0.a11 << ", " << a0.a12 << ", " << a0.a13 << ", " << a0.a14
+ << ", " << a0.a15 << ", " << a0.a16 << ", " << a0.a17 << ", "
+ << a0.a18 << ", " << a0.a19 << ", " << a0.a20 << ", " << a0.a21
+ << ", " << a0.a22 << ", " << a0.a23 << ", " << a0.a24 << ", "
+ << a0.a25 << ", " << a0.a26 << ", " << a0.a27 << ", " << a0.a28
+ << ", " << a0.a29 << ", " << a0.a30 << ", " << a0.a31 << ", "
+ << a0.a32 << ", " << a0.a33 << ", " << a0.a34 << ", " << a0.a35
+ << ", " << a0.a36 << ", " << a0.a37 << ", " << a0.a38 << ", "
+ << a0.a39 << ", " << a0.a40 << ", " << a0.a41 << ", " << a0.a42
+ << ", " << a0.a43 << ", " << a0.a44 << ", " << a0.a45 << ", "
+ << a0.a46 << ", " << a0.a47 << ", " << a0.a48 << ", " << a0.a49
+ << ", " << a0.a50 << ", " << a0.a51 << ", " << a0.a52 << ", "
+ << a0.a53 << ", " << a0.a54 << ", " << a0.a55 << ", " << a0.a56
+ << ", " << a0.a57 << ", " << a0.a58 << ", " << a0.a59 << ", "
+ << a0.a60 << ", " << a0.a61 << ", " << a0.a62 << ", " << a0.a63
+ << ", " << a0.a64 << ", " << a0.a65 << ", " << a0.a66 << ", "
+ << a0.a67 << ", " << a0.a68 << ", " << a0.a69 << ", " << a0.a70
+ << ", " << a0.a71 << ", " << a0.a72 << ", " << a0.a73 << ", "
+ << a0.a74 << ", " << a0.a75 << ", " << a0.a76 << ", " << a0.a77
+ << ", " << a0.a78 << ", " << a0.a79 << ", " << a0.a80 << ", "
+ << a0.a81 << ", " << a0.a82 << ", " << a0.a83 << ", " << a0.a84
+ << ", " << a0.a85 << ", " << a0.a86 << ", " << a0.a87 << ", "
+ << a0.a88 << ", " << a0.a89 << ", " << a0.a90 << ", " << a0.a91
+ << ", " << a0.a92 << ", " << a0.a93 << ", " << a0.a94 << ", "
+ << a0.a95 << ", " << a0.a96 << ", " << a0.a97 << ", " << a0.a98
+ << ", " << a0.a99 << ", " << a0.a100 << ", " << a0.a101 << ", "
+ << a0.a102 << ", " << a0.a103 << ", " << a0.a104 << ", " << a0.a105
+ << ", " << a0.a106 << ", " << a0.a107 << ", " << a0.a108 << ", "
+ << a0.a109 << ", " << a0.a110 << ", " << a0.a111 << ", " << a0.a112
+ << ", " << a0.a113 << ", " << a0.a114 << ", " << a0.a115 << ", "
+ << a0.a116 << ", " << a0.a117 << ", " << a0.a118 << ", " << a0.a119
+ << ", " << a0.a120 << ", " << a0.a121 << ", " << a0.a122 << ", "
+ << a0.a123 << ", " << a0.a124 << ", " << a0.a125 << ", " << a0.a126
+ << ", " << a0.a127 << "))"
+ << ")\n";
+
+ uint64_t result = f(a0);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_EQ(8256, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0);
+
+ CHECK_EQ(0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0);
+
+ CHECK_EQ(0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Tests the alignment of structs in FPU registers and backfilling.
+DART_EXPORT intptr_t TestPassFloatStruct16BytesHomogeneousFloatFloatStruct1(
+ // NOLINTNEXTLINE(whitespace/parens)
+ float (*f)(float a0,
+ Struct16BytesHomogeneousFloat a1,
+ float a2,
+ Struct16BytesHomogeneousFloat a3,
+ float a4,
+ Struct16BytesHomogeneousFloat a5,
+ float a6,
+ Struct16BytesHomogeneousFloat a7,
+ float a8)) {
+ float a0;
+ Struct16BytesHomogeneousFloat a1;
+ float a2;
+ Struct16BytesHomogeneousFloat a3;
+ float a4;
+ Struct16BytesHomogeneousFloat a5;
+ float a6;
+ Struct16BytesHomogeneousFloat a7;
+ float a8;
+
+ a0 = -1.0;
+ a1.a0 = 2.0;
+ a1.a1 = -3.0;
+ a1.a2 = 4.0;
+ a1.a3 = -5.0;
+ a2 = 6.0;
+ a3.a0 = -7.0;
+ a3.a1 = 8.0;
+ a3.a2 = -9.0;
+ a3.a3 = 10.0;
+ a4 = -11.0;
+ a5.a0 = 12.0;
+ a5.a1 = -13.0;
+ a5.a2 = 14.0;
+ a5.a3 = -15.0;
+ a6 = 16.0;
+ a7.a0 = -17.0;
+ a7.a1 = 18.0;
+ a7.a2 = -19.0;
+ a7.a3 = 20.0;
+ a8 = -21.0;
+
+ std::cout << "Calling TestPassFloatStruct16BytesHomogeneousFloatFloatStruct1("
+ << "(" << a0 << ", (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2
+ << ", " << a1.a3 << "), " << a2 << ", (" << a3.a0 << ", " << a3.a1
+ << ", " << a3.a2 << ", " << a3.a3 << "), " << a4 << ", (" << a5.a0
+ << ", " << a5.a1 << ", " << a5.a2 << ", " << a5.a3 << "), " << a6
+ << ", (" << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << ", " << a7.a3
+ << "), " << a8 << ")"
+ << ")\n";
+
+ float result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_APPROX(-11.0, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ CHECK_APPROX(0.0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ CHECK_APPROX(0.0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Tests the alignment of structs in FPU registers and backfilling.
+DART_EXPORT intptr_t TestPassFloatStruct32BytesHomogeneousDoubleFloatStruct(
+ // NOLINTNEXTLINE(whitespace/parens)
+ double (*f)(float a0,
+ Struct32BytesHomogeneousDouble a1,
+ float a2,
+ Struct32BytesHomogeneousDouble a3,
+ float a4,
+ Struct32BytesHomogeneousDouble a5,
+ float a6,
+ Struct32BytesHomogeneousDouble a7,
+ float a8)) {
+ float a0;
+ Struct32BytesHomogeneousDouble a1;
+ float a2;
+ Struct32BytesHomogeneousDouble a3;
+ float a4;
+ Struct32BytesHomogeneousDouble a5;
+ float a6;
+ Struct32BytesHomogeneousDouble a7;
+ float a8;
+
+ a0 = -1.0;
+ a1.a0 = 2.0;
+ a1.a1 = -3.0;
+ a1.a2 = 4.0;
+ a1.a3 = -5.0;
+ a2 = 6.0;
+ a3.a0 = -7.0;
+ a3.a1 = 8.0;
+ a3.a2 = -9.0;
+ a3.a3 = 10.0;
+ a4 = -11.0;
+ a5.a0 = 12.0;
+ a5.a1 = -13.0;
+ a5.a2 = 14.0;
+ a5.a3 = -15.0;
+ a6 = 16.0;
+ a7.a0 = -17.0;
+ a7.a1 = 18.0;
+ a7.a2 = -19.0;
+ a7.a3 = 20.0;
+ a8 = -21.0;
+
+ std::cout << "Calling TestPassFloatStruct32BytesHomogeneousDoubleFloatStruct("
+ << "(" << a0 << ", (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2
+ << ", " << a1.a3 << "), " << a2 << ", (" << a3.a0 << ", " << a3.a1
+ << ", " << a3.a2 << ", " << a3.a3 << "), " << a4 << ", (" << a5.a0
+ << ", " << a5.a1 << ", " << a5.a2 << ", " << a5.a3 << "), " << a6
+ << ", (" << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << ", " << a7.a3
+ << "), " << a8 << ")"
+ << ")\n";
+
+ double result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_APPROX(-11.0, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ CHECK_APPROX(0.0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ CHECK_APPROX(0.0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Tests the alignment of structs in integers registers and on the stack.
+// Arm32 aligns this struct at 8.
+// Also, arm32 allocates the second struct partially in registers, partially
+// on stack.
+// Test backfilling of integer registers.
+DART_EXPORT intptr_t TestPassInt8Struct16BytesMixedInt8Struct16BytesMixedIn(
+ // NOLINTNEXTLINE(whitespace/parens)
+ double (*f)(int8_t a0,
+ Struct16BytesMixed a1,
+ int8_t a2,
+ Struct16BytesMixed a3,
+ int8_t a4,
+ Struct16BytesMixed a5,
+ int8_t a6,
+ Struct16BytesMixed a7,
+ int8_t a8)) {
+ int8_t a0;
+ Struct16BytesMixed a1;
+ int8_t a2;
+ Struct16BytesMixed a3;
+ int8_t a4;
+ Struct16BytesMixed a5;
+ int8_t a6;
+ Struct16BytesMixed a7;
+ int8_t a8;
+
+ a0 = -1;
+ a1.a0 = 2.0;
+ a1.a1 = -3;
+ a2 = 4;
+ a3.a0 = -5.0;
+ a3.a1 = 6;
+ a4 = -7;
+ a5.a0 = 8.0;
+ a5.a1 = -9;
+ a6 = 10;
+ a7.a0 = -11.0;
+ a7.a1 = 12;
+ a8 = -13;
+
+ std::cout << "Calling TestPassInt8Struct16BytesMixedInt8Struct16BytesMixedIn("
+ << "(" << static_cast<int>(a0) << ", (" << a1.a0 << ", " << a1.a1
+ << "), " << static_cast<int>(a2) << ", (" << a3.a0 << ", " << a3.a1
+ << "), " << static_cast<int>(a4) << ", (" << a5.a0 << ", " << a5.a1
+ << "), " << static_cast<int>(a6) << ", (" << a7.a0 << ", " << a7.a1
+ << "), " << static_cast<int>(a8) << ")"
+ << ")\n";
+
+ double result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_APPROX(-7.0, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ CHECK_APPROX(0.0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ CHECK_APPROX(0.0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// On Linux x64, it will exhaust xmm registers first, after 6 doubles and 2
+// structs. The rest of the structs will go on the stack.
+// The int will be backfilled into the int register.
+DART_EXPORT intptr_t TestPassDoublex6Struct16BytesMixedx4Int32(
+ // NOLINTNEXTLINE(whitespace/parens)
+ double (*f)(double a0,
+ double a1,
+ double a2,
+ double a3,
+ double a4,
+ double a5,
+ Struct16BytesMixed a6,
+ Struct16BytesMixed a7,
+ Struct16BytesMixed a8,
+ Struct16BytesMixed a9,
+ int32_t a10)) {
+ double a0;
+ double a1;
+ double a2;
+ double a3;
+ double a4;
+ double a5;
+ Struct16BytesMixed a6;
+ Struct16BytesMixed a7;
+ Struct16BytesMixed a8;
+ Struct16BytesMixed a9;
+ int32_t a10;
+
+ a0 = -1.0;
+ a1 = 2.0;
+ a2 = -3.0;
+ a3 = 4.0;
+ a4 = -5.0;
+ a5 = 6.0;
+ a6.a0 = -7.0;
+ a6.a1 = 8;
+ a7.a0 = -9.0;
+ a7.a1 = 10;
+ a8.a0 = -11.0;
+ a8.a1 = 12;
+ a9.a0 = -13.0;
+ a9.a1 = 14;
+ a10 = -15;
+
+ std::cout << "Calling TestPassDoublex6Struct16BytesMixedx4Int32("
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4
+ << ", " << a5 << ", (" << a6.a0 << ", " << a6.a1 << "), (" << a7.a0
+ << ", " << a7.a1 << "), (" << a8.a0 << ", " << a8.a1 << "), ("
+ << a9.a0 << ", " << a9.a1 << "), " << a10 << ")"
+ << ")\n";
+
+ double result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_APPROX(-8.0, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
+
+ CHECK_APPROX(0.0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
+
+ CHECK_APPROX(0.0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// On Linux x64, it will exhaust int registers first.
+// The rest of the structs will go on the stack.
+// The double will be backfilled into the xmm register.
+DART_EXPORT intptr_t TestPassInt32x4Struct16BytesMixedx4Double(
+ // NOLINTNEXTLINE(whitespace/parens)
+ double (*f)(int32_t a0,
+ int32_t a1,
+ int32_t a2,
+ int32_t a3,
+ Struct16BytesMixed a4,
+ Struct16BytesMixed a5,
+ Struct16BytesMixed a6,
+ Struct16BytesMixed a7,
+ double a8)) {
+ int32_t a0;
+ int32_t a1;
+ int32_t a2;
+ int32_t a3;
+ Struct16BytesMixed a4;
+ Struct16BytesMixed a5;
+ Struct16BytesMixed a6;
+ Struct16BytesMixed a7;
+ double a8;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+ a3 = 4;
+ a4.a0 = -5.0;
+ a4.a1 = 6;
+ a5.a0 = -7.0;
+ a5.a1 = 8;
+ a6.a0 = -9.0;
+ a6.a1 = 10;
+ a7.a0 = -11.0;
+ a7.a1 = 12;
+ a8 = -13.0;
+
+ std::cout << "Calling TestPassInt32x4Struct16BytesMixedx4Double("
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", ("
+ << a4.a0 << ", " << a4.a1 << "), (" << a5.a0 << ", " << a5.a1
+ << "), (" << a6.a0 << ", " << a6.a1 << "), (" << a7.a0 << ", "
+ << a7.a1 << "), " << a8 << ")"
+ << ")\n";
+
+ double result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_APPROX(-7.0, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ CHECK_APPROX(0.0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ CHECK_APPROX(0.0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// On various architectures, first struct is allocated on stack.
+// Check that the other two arguments are allocated on registers.
+DART_EXPORT intptr_t TestPassStruct40BytesHomogeneousDoubleStruct4BytesHomo(
+ // NOLINTNEXTLINE(whitespace/parens)
+ double (*f)(Struct40BytesHomogeneousDouble a0,
+ Struct4BytesHomogeneousInt16 a1,
+ Struct8BytesHomogeneousFloat a2)) {
+ Struct40BytesHomogeneousDouble a0;
+ Struct4BytesHomogeneousInt16 a1;
+ Struct8BytesHomogeneousFloat a2;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a0.a2 = -3.0;
+ a0.a3 = 4.0;
+ a0.a4 = -5.0;
+ a1.a0 = 6;
+ a1.a1 = -7;
+ a2.a0 = 8.0;
+ a2.a1 = -9.0;
+
+ std::cout << "Calling TestPassStruct40BytesHomogeneousDoubleStruct4BytesHomo("
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3
+ << ", " << a0.a4 << "), (" << a1.a0 << ", " << a1.a1 << "), ("
+ << a2.a0 << ", " << a2.a1 << "))"
+ << ")\n";
+
+ double result = f(a0, a1, a2);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_APPROX(-5.0, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0, a1, a2);
+
+ CHECK_APPROX(0.0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0, a1, a2);
+
+ CHECK_APPROX(0.0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of 16 byte int within struct.
+DART_EXPORT intptr_t TestPassStructAlignmentInt16(
+ // NOLINTNEXTLINE(whitespace/parens)
+ int64_t (*f)(StructAlignmentInt16 a0)) {
+ StructAlignmentInt16 a0;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+
+ std::cout << "Calling TestPassStructAlignmentInt16("
+ << "((" << static_cast<int>(a0.a0) << ", " << a0.a1 << ", "
+ << static_cast<int>(a0.a2) << "))"
+ << ")\n";
+
+ int64_t result = f(a0);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_EQ(-2, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0);
+
+ CHECK_EQ(0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0);
+
+ CHECK_EQ(0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of 32 byte int within struct.
+DART_EXPORT intptr_t TestPassStructAlignmentInt32(
+ // NOLINTNEXTLINE(whitespace/parens)
+ int64_t (*f)(StructAlignmentInt32 a0)) {
+ StructAlignmentInt32 a0;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+
+ std::cout << "Calling TestPassStructAlignmentInt32("
+ << "((" << static_cast<int>(a0.a0) << ", " << a0.a1 << ", "
+ << static_cast<int>(a0.a2) << "))"
+ << ")\n";
+
+ int64_t result = f(a0);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_EQ(-2, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0);
+
+ CHECK_EQ(0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0);
+
+ CHECK_EQ(0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of 64 byte int within struct.
+DART_EXPORT intptr_t TestPassStructAlignmentInt64(
+ // NOLINTNEXTLINE(whitespace/parens)
+ int64_t (*f)(StructAlignmentInt64 a0)) {
+ StructAlignmentInt64 a0;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+
+ std::cout << "Calling TestPassStructAlignmentInt64("
+ << "((" << static_cast<int>(a0.a0) << ", " << a0.a1 << ", "
+ << static_cast<int>(a0.a2) << "))"
+ << ")\n";
+
+ int64_t result = f(a0);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_EQ(-2, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0);
+
+ CHECK_EQ(0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0);
+
+ CHECK_EQ(0, result);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Smallest struct with data.
+DART_EXPORT intptr_t TestReturnStruct1ByteInt(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct1ByteInt (*f)(int8_t a0)) {
+ int8_t a0;
+
+ a0 = -1;
+
+ std::cout << "Calling TestReturnStruct1ByteInt("
+ << "(" << static_cast<int>(a0) << ")"
+ << ")\n";
+
+ Struct1ByteInt result = f(a0);
+
+ std::cout << "result = "
+ << "(" << static_cast<int>(result.a0) << ")"
+ << "\n";
+
+ CHECK_EQ(a0, result.a0);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0);
+
+ CHECK_EQ(0, result.a0);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0);
+
+ CHECK_EQ(0, result.a0);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Smaller than word size return value on all architectures.
+DART_EXPORT intptr_t TestReturnStruct3BytesInt(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct3BytesInt (*f)(int16_t a0, int8_t a1)) {
+ int16_t a0;
+ int8_t a1;
+
+ a0 = -1;
+ a1 = 2;
+
+ std::cout << "Calling TestReturnStruct3BytesInt("
+ << "(" << a0 << ", " << static_cast<int>(a1) << ")"
+ << ")\n";
+
+ Struct3BytesInt result = f(a0, a1);
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << static_cast<int>(result.a1) << ")"
+ << "\n";
+
+ CHECK_EQ(a0, result.a0);
+ CHECK_EQ(a1, result.a1);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Word size return value on 32 bit architectures..
+DART_EXPORT intptr_t TestReturnStruct4BytesHomogeneousInt16(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct4BytesHomogeneousInt16 (*f)(int16_t a0, int16_t a1)) {
+ int16_t a0;
+ int16_t a1;
+
+ a0 = -1;
+ a1 = 2;
+
+ std::cout << "Calling TestReturnStruct4BytesHomogeneousInt16("
+ << "(" << a0 << ", " << a1 << ")"
+ << ")\n";
+
+ Struct4BytesHomogeneousInt16 result = f(a0, a1);
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ")"
+ << "\n";
+
+ CHECK_EQ(a0, result.a0);
+ CHECK_EQ(a1, result.a1);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Non-wordsize return value.
+DART_EXPORT intptr_t TestReturnStruct7BytesInt(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct7BytesInt (*f)(int32_t a0, int16_t a1, int8_t a2)) {
+ int32_t a0;
+ int16_t a1;
+ int8_t a2;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+
+ std::cout << "Calling TestReturnStruct7BytesInt("
+ << "(" << a0 << ", " << a1 << ", " << static_cast<int>(a2) << ")"
+ << ")\n";
+
+ Struct7BytesInt result = f(a0, a1, a2);
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", "
+ << static_cast<int>(result.a2) << ")"
+ << "\n";
+
+ CHECK_EQ(a0, result.a0);
+ CHECK_EQ(a1, result.a1);
+ CHECK_EQ(a2, result.a2);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Return value in integer registers on many architectures.
+DART_EXPORT intptr_t TestReturnStruct8BytesInt(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct8BytesInt (*f)(int16_t a0, int16_t a1, int32_t a2)) {
+ int16_t a0;
+ int16_t a1;
+ int32_t a2;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+
+ std::cout << "Calling TestReturnStruct8BytesInt("
+ << "(" << a0 << ", " << a1 << ", " << a2 << ")"
+ << ")\n";
+
+ Struct8BytesInt result = f(a0, a1, a2);
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ")"
+ << "\n";
+
+ CHECK_EQ(a0, result.a0);
+ CHECK_EQ(a1, result.a1);
+ CHECK_EQ(a2, result.a2);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Return value in FP registers on many architectures.
+DART_EXPORT intptr_t TestReturnStruct8BytesHomogeneousFloat(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct8BytesHomogeneousFloat (*f)(float a0, float a1)) {
+ float a0;
+ float a1;
+
+ a0 = -1.0;
+ a1 = 2.0;
+
+ std::cout << "Calling TestReturnStruct8BytesHomogeneousFloat("
+ << "(" << a0 << ", " << a1 << ")"
+ << ")\n";
+
+ Struct8BytesHomogeneousFloat result = f(a0, a1);
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ")"
+ << "\n";
+
+ CHECK_APPROX(a0, result.a0);
+ CHECK_APPROX(a1, result.a1);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1);
+
+ CHECK_APPROX(0.0, result.a0);
+ CHECK_APPROX(0.0, result.a1);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1);
+
+ CHECK_APPROX(0.0, result.a0);
+ CHECK_APPROX(0.0, result.a1);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Return value split over FP and integer register in x64.
+DART_EXPORT intptr_t TestReturnStruct8BytesMixed(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct8BytesMixed (*f)(float a0, int16_t a1, int16_t a2)) {
+ float a0;
+ int16_t a1;
+ int16_t a2;
+
+ a0 = -1.0;
+ a1 = 2;
+ a2 = -3;
+
+ std::cout << "Calling TestReturnStruct8BytesMixed("
+ << "(" << a0 << ", " << a1 << ", " << a2 << ")"
+ << ")\n";
+
+ Struct8BytesMixed result = f(a0, a1, a2);
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ")"
+ << "\n";
+
+ CHECK_APPROX(a0, result.a0);
+ CHECK_EQ(a1, result.a1);
+ CHECK_EQ(a2, result.a2);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2);
+
+ CHECK_APPROX(0.0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2);
+
+ CHECK_APPROX(0.0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Return value in two integer registers on x64.
+// The second register only contains a single byte.
+DART_EXPORT intptr_t TestReturnStruct9BytesInt(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct9BytesInt (*f)(int64_t a0, int8_t a1)) {
+ int64_t a0;
+ int8_t a1;
+
+ a0 = -1;
+ a1 = 2;
+
+ std::cout << "Calling TestReturnStruct9BytesInt("
+ << "(" << a0 << ", " << static_cast<int>(a1) << ")"
+ << ")\n";
+
+ Struct9BytesInt result = f(a0, a1);
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << static_cast<int>(result.a1) << ")"
+ << "\n";
+
+ CHECK_EQ(a0, result.a0);
+ CHECK_EQ(a1, result.a1);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// The minimum alignment of this struct is only 1 byte based on its fields.
+// Test that the memory backing these structs is the right size and that
+// dart:ffi trampolines do not write outside this size.
+DART_EXPORT intptr_t TestReturnStruct9BytesHomogeneousUint82(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct9BytesHomogeneousUint82 (*f)(uint8_t a0,
+ uint8_t a1,
+ uint8_t a2,
+ uint8_t a3,
+ uint8_t a4,
+ uint8_t a5,
+ uint8_t a6,
+ uint8_t a7,
+ uint8_t a8)) {
+ uint8_t a0;
+ uint8_t a1;
+ uint8_t a2;
+ uint8_t a3;
+ uint8_t a4;
+ uint8_t a5;
+ uint8_t a6;
+ uint8_t a7;
+ uint8_t a8;
+
+ a0 = 1;
+ a1 = 2;
+ a2 = 3;
+ a3 = 4;
+ a4 = 5;
+ a5 = 6;
+ a6 = 7;
+ a7 = 8;
+ a8 = 9;
+
+ std::cout << "Calling TestReturnStruct9BytesHomogeneousUint82("
+ << "(" << static_cast<int>(a0) << ", " << static_cast<int>(a1)
+ << ", " << static_cast<int>(a2) << ", " << static_cast<int>(a3)
+ << ", " << static_cast<int>(a4) << ", " << static_cast<int>(a5)
+ << ", " << static_cast<int>(a6) << ", " << static_cast<int>(a7)
+ << ", " << static_cast<int>(a8) << ")"
+ << ")\n";
+
+ Struct9BytesHomogeneousUint82 result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ std::cout << "result = "
+ << "(" << static_cast<int>(result.a0) << ", "
+ << static_cast<int>(result.a1) << ", "
+ << static_cast<int>(result.a2) << ", "
+ << static_cast<int>(result.a3) << ", "
+ << static_cast<int>(result.a4) << ", "
+ << static_cast<int>(result.a5) << ", "
+ << static_cast<int>(result.a6) << ", "
+ << static_cast<int>(result.a7) << ", "
+ << static_cast<int>(result.a8) << ")"
+ << "\n";
+
+ CHECK_EQ(a0, result.a0);
+ CHECK_EQ(a1, result.a1);
+ CHECK_EQ(a2, result.a2);
+ CHECK_EQ(a3, result.a3);
+ CHECK_EQ(a4, result.a4);
+ CHECK_EQ(a5, result.a5);
+ CHECK_EQ(a6, result.a6);
+ CHECK_EQ(a7, result.a7);
+ CHECK_EQ(a8, result.a8);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+ CHECK_EQ(0, result.a3);
+ CHECK_EQ(0, result.a4);
+ CHECK_EQ(0, result.a5);
+ CHECK_EQ(0, result.a6);
+ CHECK_EQ(0, result.a7);
+ CHECK_EQ(0, result.a8);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+ CHECK_EQ(0, result.a3);
+ CHECK_EQ(0, result.a4);
+ CHECK_EQ(0, result.a5);
+ CHECK_EQ(0, result.a6);
+ CHECK_EQ(0, result.a7);
+ CHECK_EQ(0, result.a8);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Return value in FPU registers, but does not use all registers on arm hardfp
+// and arm64.
+DART_EXPORT intptr_t TestReturnStruct12BytesHomogeneousFloat(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct12BytesHomogeneousFloat (*f)(float a0, float a1, float a2)) {
+ float a0;
+ float a1;
+ float a2;
+
+ a0 = -1.0;
+ a1 = 2.0;
+ a2 = -3.0;
+
+ std::cout << "Calling TestReturnStruct12BytesHomogeneousFloat("
+ << "(" << a0 << ", " << a1 << ", " << a2 << ")"
+ << ")\n";
+
+ Struct12BytesHomogeneousFloat result = f(a0, a1, a2);
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ")"
+ << "\n";
+
+ CHECK_APPROX(a0, result.a0);
+ CHECK_APPROX(a1, result.a1);
+ CHECK_APPROX(a2, result.a2);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2);
+
+ CHECK_APPROX(0.0, result.a0);
+ CHECK_APPROX(0.0, result.a1);
+ CHECK_APPROX(0.0, result.a2);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2);
+
+ CHECK_APPROX(0.0, result.a0);
+ CHECK_APPROX(0.0, result.a1);
+ CHECK_APPROX(0.0, result.a2);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Return value in FPU registers on arm hardfp and arm64.
+DART_EXPORT intptr_t TestReturnStruct16BytesHomogeneousFloat(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct16BytesHomogeneousFloat (
+ *f)(float a0, float a1, float a2, float a3)) {
+ float a0;
+ float a1;
+ float a2;
+ float a3;
+
+ a0 = -1.0;
+ a1 = 2.0;
+ a2 = -3.0;
+ a3 = 4.0;
+
+ std::cout << "Calling TestReturnStruct16BytesHomogeneousFloat("
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ")"
+ << ")\n";
+
+ Struct16BytesHomogeneousFloat result = f(a0, a1, a2, a3);
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2
+ << ", " << result.a3 << ")"
+ << "\n";
+
+ CHECK_APPROX(a0, result.a0);
+ CHECK_APPROX(a1, result.a1);
+ CHECK_APPROX(a2, result.a2);
+ CHECK_APPROX(a3, result.a3);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2, a3);
+
+ CHECK_APPROX(0.0, result.a0);
+ CHECK_APPROX(0.0, result.a1);
+ CHECK_APPROX(0.0, result.a2);
+ CHECK_APPROX(0.0, result.a3);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2, a3);
+
+ CHECK_APPROX(0.0, result.a0);
+ CHECK_APPROX(0.0, result.a1);
+ CHECK_APPROX(0.0, result.a2);
+ CHECK_APPROX(0.0, result.a3);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Return value split over FP and integer register in x64.
+DART_EXPORT intptr_t TestReturnStruct16BytesMixed(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct16BytesMixed (*f)(double a0, int64_t a1)) {
+ double a0;
+ int64_t a1;
+
+ a0 = -1.0;
+ a1 = 2;
+
+ std::cout << "Calling TestReturnStruct16BytesMixed("
+ << "(" << a0 << ", " << a1 << ")"
+ << ")\n";
+
+ Struct16BytesMixed result = f(a0, a1);
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ")"
+ << "\n";
+
+ CHECK_APPROX(a0, result.a0);
+ CHECK_EQ(a1, result.a1);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1);
+
+ CHECK_APPROX(0.0, result.a0);
+ CHECK_EQ(0, result.a1);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1);
+
+ CHECK_APPROX(0.0, result.a0);
+ CHECK_EQ(0, result.a1);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Return value split over FP and integer register in x64.
+// The integer register contains half float half int.
+DART_EXPORT intptr_t TestReturnStruct16BytesMixed2(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct16BytesMixed2 (*f)(float a0, float a1, float a2, int32_t a3)) {
+ float a0;
+ float a1;
+ float a2;
+ int32_t a3;
+
+ a0 = -1.0;
+ a1 = 2.0;
+ a2 = -3.0;
+ a3 = 4;
+
+ std::cout << "Calling TestReturnStruct16BytesMixed2("
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ")"
+ << ")\n";
+
+ Struct16BytesMixed2 result = f(a0, a1, a2, a3);
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2
+ << ", " << result.a3 << ")"
+ << "\n";
+
+ CHECK_APPROX(a0, result.a0);
+ CHECK_APPROX(a1, result.a1);
+ CHECK_APPROX(a2, result.a2);
+ CHECK_EQ(a3, result.a3);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2, a3);
+
+ CHECK_APPROX(0.0, result.a0);
+ CHECK_APPROX(0.0, result.a1);
+ CHECK_APPROX(0.0, result.a2);
+ CHECK_EQ(0, result.a3);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2, a3);
+
+ CHECK_APPROX(0.0, result.a0);
+ CHECK_APPROX(0.0, result.a1);
+ CHECK_APPROX(0.0, result.a2);
+ CHECK_EQ(0, result.a3);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Rerturn value returned in preallocated space passed by pointer on most ABIs.
+// Is non word size on purpose, to test that structs are rounded up to word size
+// on all ABIs.
+DART_EXPORT intptr_t TestReturnStruct17BytesInt(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct17BytesInt (*f)(int64_t a0, int64_t a1, int8_t a2)) {
+ int64_t a0;
+ int64_t a1;
+ int8_t a2;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+
+ std::cout << "Calling TestReturnStruct17BytesInt("
+ << "(" << a0 << ", " << a1 << ", " << static_cast<int>(a2) << ")"
+ << ")\n";
+
+ Struct17BytesInt result = f(a0, a1, a2);
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", "
+ << static_cast<int>(result.a2) << ")"
+ << "\n";
+
+ CHECK_EQ(a0, result.a0);
+ CHECK_EQ(a1, result.a1);
+ CHECK_EQ(a2, result.a2);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// The minimum alignment of this struct is only 1 byte based on its fields.
+// Test that the memory backing these structs is the right size and that
+// dart:ffi trampolines do not write outside this size.
+DART_EXPORT intptr_t TestReturnStruct19BytesHomogeneousUint8(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct19BytesHomogeneousUint8 (*f)(uint8_t a0,
+ uint8_t a1,
+ uint8_t a2,
+ uint8_t a3,
+ uint8_t a4,
+ uint8_t a5,
+ uint8_t a6,
+ uint8_t a7,
+ uint8_t a8,
+ uint8_t a9,
+ uint8_t a10,
+ uint8_t a11,
+ uint8_t a12,
+ uint8_t a13,
+ uint8_t a14,
+ uint8_t a15,
+ uint8_t a16,
+ uint8_t a17,
+ uint8_t a18)) {
+ uint8_t a0;
+ uint8_t a1;
+ uint8_t a2;
+ uint8_t a3;
+ uint8_t a4;
+ uint8_t a5;
+ uint8_t a6;
+ uint8_t a7;
+ uint8_t a8;
+ uint8_t a9;
+ uint8_t a10;
+ uint8_t a11;
+ uint8_t a12;
+ uint8_t a13;
+ uint8_t a14;
+ uint8_t a15;
+ uint8_t a16;
+ uint8_t a17;
+ uint8_t a18;
+
+ a0 = 1;
+ a1 = 2;
+ a2 = 3;
+ a3 = 4;
+ a4 = 5;
+ a5 = 6;
+ a6 = 7;
+ a7 = 8;
+ a8 = 9;
+ a9 = 10;
+ a10 = 11;
+ a11 = 12;
+ a12 = 13;
+ a13 = 14;
+ a14 = 15;
+ a15 = 16;
+ a16 = 17;
+ a17 = 18;
+ a18 = 19;
+
+ std::cout << "Calling TestReturnStruct19BytesHomogeneousUint8("
+ << "(" << static_cast<int>(a0) << ", " << static_cast<int>(a1)
+ << ", " << static_cast<int>(a2) << ", " << static_cast<int>(a3)
+ << ", " << static_cast<int>(a4) << ", " << static_cast<int>(a5)
+ << ", " << static_cast<int>(a6) << ", " << static_cast<int>(a7)
+ << ", " << static_cast<int>(a8) << ", " << static_cast<int>(a9)
+ << ", " << static_cast<int>(a10) << ", " << static_cast<int>(a11)
+ << ", " << static_cast<int>(a12) << ", " << static_cast<int>(a13)
+ << ", " << static_cast<int>(a14) << ", " << static_cast<int>(a15)
+ << ", " << static_cast<int>(a16) << ", " << static_cast<int>(a17)
+ << ", " << static_cast<int>(a18) << ")"
+ << ")\n";
+
+ Struct19BytesHomogeneousUint8 result =
+ f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15,
+ a16, a17, a18);
+
+ std::cout << "result = "
+ << "(" << static_cast<int>(result.a0) << ", "
+ << static_cast<int>(result.a1) << ", "
+ << static_cast<int>(result.a2) << ", "
+ << static_cast<int>(result.a3) << ", "
+ << static_cast<int>(result.a4) << ", "
+ << static_cast<int>(result.a5) << ", "
+ << static_cast<int>(result.a6) << ", "
+ << static_cast<int>(result.a7) << ", "
+ << static_cast<int>(result.a8) << ", "
+ << static_cast<int>(result.a9) << ", "
+ << static_cast<int>(result.a10) << ", "
+ << static_cast<int>(result.a11) << ", "
+ << static_cast<int>(result.a12) << ", "
+ << static_cast<int>(result.a13) << ", "
+ << static_cast<int>(result.a14) << ", "
+ << static_cast<int>(result.a15) << ", "
+ << static_cast<int>(result.a16) << ", "
+ << static_cast<int>(result.a17) << ", "
+ << static_cast<int>(result.a18) << ")"
+ << "\n";
+
+ CHECK_EQ(a0, result.a0);
+ CHECK_EQ(a1, result.a1);
+ CHECK_EQ(a2, result.a2);
+ CHECK_EQ(a3, result.a3);
+ CHECK_EQ(a4, result.a4);
+ CHECK_EQ(a5, result.a5);
+ CHECK_EQ(a6, result.a6);
+ CHECK_EQ(a7, result.a7);
+ CHECK_EQ(a8, result.a8);
+ CHECK_EQ(a9, result.a9);
+ CHECK_EQ(a10, result.a10);
+ CHECK_EQ(a11, result.a11);
+ CHECK_EQ(a12, result.a12);
+ CHECK_EQ(a13, result.a13);
+ CHECK_EQ(a14, result.a14);
+ CHECK_EQ(a15, result.a15);
+ CHECK_EQ(a16, result.a16);
+ CHECK_EQ(a17, result.a17);
+ CHECK_EQ(a18, result.a18);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14,
+ a15, a16, a17, a18);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+ CHECK_EQ(0, result.a3);
+ CHECK_EQ(0, result.a4);
+ CHECK_EQ(0, result.a5);
+ CHECK_EQ(0, result.a6);
+ CHECK_EQ(0, result.a7);
+ CHECK_EQ(0, result.a8);
+ CHECK_EQ(0, result.a9);
+ CHECK_EQ(0, result.a10);
+ CHECK_EQ(0, result.a11);
+ CHECK_EQ(0, result.a12);
+ CHECK_EQ(0, result.a13);
+ CHECK_EQ(0, result.a14);
+ CHECK_EQ(0, result.a15);
+ CHECK_EQ(0, result.a16);
+ CHECK_EQ(0, result.a17);
+ CHECK_EQ(0, result.a18);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14,
+ a15, a16, a17, a18);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+ CHECK_EQ(0, result.a3);
+ CHECK_EQ(0, result.a4);
+ CHECK_EQ(0, result.a5);
+ CHECK_EQ(0, result.a6);
+ CHECK_EQ(0, result.a7);
+ CHECK_EQ(0, result.a8);
+ CHECK_EQ(0, result.a9);
+ CHECK_EQ(0, result.a10);
+ CHECK_EQ(0, result.a11);
+ CHECK_EQ(0, result.a12);
+ CHECK_EQ(0, result.a13);
+ CHECK_EQ(0, result.a14);
+ CHECK_EQ(0, result.a15);
+ CHECK_EQ(0, result.a16);
+ CHECK_EQ(0, result.a17);
+ CHECK_EQ(0, result.a18);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Return value too big to go in cpu registers on arm64.
+DART_EXPORT intptr_t TestReturnStruct20BytesHomogeneousInt32(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct20BytesHomogeneousInt32 (
+ *f)(int32_t a0, int32_t a1, int32_t a2, int32_t a3, int32_t a4)) {
+ int32_t a0;
+ int32_t a1;
+ int32_t a2;
+ int32_t a3;
+ int32_t a4;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+ a3 = 4;
+ a4 = -5;
+
+ std::cout << "Calling TestReturnStruct20BytesHomogeneousInt32("
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4
+ << ")"
+ << ")\n";
+
+ Struct20BytesHomogeneousInt32 result = f(a0, a1, a2, a3, a4);
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2
+ << ", " << result.a3 << ", " << result.a4 << ")"
+ << "\n";
+
+ CHECK_EQ(a0, result.a0);
+ CHECK_EQ(a1, result.a1);
+ CHECK_EQ(a2, result.a2);
+ CHECK_EQ(a3, result.a3);
+ CHECK_EQ(a4, result.a4);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+ CHECK_EQ(0, result.a3);
+ CHECK_EQ(0, result.a4);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+ CHECK_EQ(0, result.a3);
+ CHECK_EQ(0, result.a4);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Return value too big to go in FPU registers on x64, arm hardfp and arm64.
+DART_EXPORT intptr_t TestReturnStruct20BytesHomogeneousFloat(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct20BytesHomogeneousFloat (
+ *f)(float a0, float a1, float a2, float a3, float a4)) {
+ float a0;
+ float a1;
+ float a2;
+ float a3;
+ float a4;
+
+ a0 = -1.0;
+ a1 = 2.0;
+ a2 = -3.0;
+ a3 = 4.0;
+ a4 = -5.0;
+
+ std::cout << "Calling TestReturnStruct20BytesHomogeneousFloat("
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4
+ << ")"
+ << ")\n";
+
+ Struct20BytesHomogeneousFloat result = f(a0, a1, a2, a3, a4);
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2
+ << ", " << result.a3 << ", " << result.a4 << ")"
+ << "\n";
+
+ CHECK_APPROX(a0, result.a0);
+ CHECK_APPROX(a1, result.a1);
+ CHECK_APPROX(a2, result.a2);
+ CHECK_APPROX(a3, result.a3);
+ CHECK_APPROX(a4, result.a4);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4);
+
+ CHECK_APPROX(0.0, result.a0);
+ CHECK_APPROX(0.0, result.a1);
+ CHECK_APPROX(0.0, result.a2);
+ CHECK_APPROX(0.0, result.a3);
+ CHECK_APPROX(0.0, result.a4);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4);
+
+ CHECK_APPROX(0.0, result.a0);
+ CHECK_APPROX(0.0, result.a1);
+ CHECK_APPROX(0.0, result.a2);
+ CHECK_APPROX(0.0, result.a3);
+ CHECK_APPROX(0.0, result.a4);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Return value in FPU registers on arm64.
+DART_EXPORT intptr_t TestReturnStruct32BytesHomogeneousDouble(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct32BytesHomogeneousDouble (
+ *f)(double a0, double a1, double a2, double a3)) {
+ double a0;
+ double a1;
+ double a2;
+ double a3;
+
+ a0 = -1.0;
+ a1 = 2.0;
+ a2 = -3.0;
+ a3 = 4.0;
+
+ std::cout << "Calling TestReturnStruct32BytesHomogeneousDouble("
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ")"
+ << ")\n";
+
+ Struct32BytesHomogeneousDouble result = f(a0, a1, a2, a3);
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2
+ << ", " << result.a3 << ")"
+ << "\n";
+
+ CHECK_APPROX(a0, result.a0);
+ CHECK_APPROX(a1, result.a1);
+ CHECK_APPROX(a2, result.a2);
+ CHECK_APPROX(a3, result.a3);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2, a3);
+
+ CHECK_APPROX(0.0, result.a0);
+ CHECK_APPROX(0.0, result.a1);
+ CHECK_APPROX(0.0, result.a2);
+ CHECK_APPROX(0.0, result.a3);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2, a3);
+
+ CHECK_APPROX(0.0, result.a0);
+ CHECK_APPROX(0.0, result.a1);
+ CHECK_APPROX(0.0, result.a2);
+ CHECK_APPROX(0.0, result.a3);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Return value too big to go in FPU registers on arm64.
+DART_EXPORT intptr_t TestReturnStruct40BytesHomogeneousDouble(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct40BytesHomogeneousDouble (
+ *f)(double a0, double a1, double a2, double a3, double a4)) {
+ double a0;
+ double a1;
+ double a2;
+ double a3;
+ double a4;
+
+ a0 = -1.0;
+ a1 = 2.0;
+ a2 = -3.0;
+ a3 = 4.0;
+ a4 = -5.0;
+
+ std::cout << "Calling TestReturnStruct40BytesHomogeneousDouble("
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4
+ << ")"
+ << ")\n";
+
+ Struct40BytesHomogeneousDouble result = f(a0, a1, a2, a3, a4);
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2
+ << ", " << result.a3 << ", " << result.a4 << ")"
+ << "\n";
+
+ CHECK_APPROX(a0, result.a0);
+ CHECK_APPROX(a1, result.a1);
+ CHECK_APPROX(a2, result.a2);
+ CHECK_APPROX(a3, result.a3);
+ CHECK_APPROX(a4, result.a4);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4);
+
+ CHECK_APPROX(0.0, result.a0);
+ CHECK_APPROX(0.0, result.a1);
+ CHECK_APPROX(0.0, result.a2);
+ CHECK_APPROX(0.0, result.a3);
+ CHECK_APPROX(0.0, result.a4);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4);
+
+ CHECK_APPROX(0.0, result.a0);
+ CHECK_APPROX(0.0, result.a1);
+ CHECK_APPROX(0.0, result.a2);
+ CHECK_APPROX(0.0, result.a3);
+ CHECK_APPROX(0.0, result.a4);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Test 1kb struct.
+DART_EXPORT intptr_t TestReturnStruct1024BytesHomogeneousUint64(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct1024BytesHomogeneousUint64 (*f)(uint64_t a0,
+ uint64_t a1,
+ uint64_t a2,
+ uint64_t a3,
+ uint64_t a4,
+ uint64_t a5,
+ uint64_t a6,
+ uint64_t a7,
+ uint64_t a8,
+ uint64_t a9,
+ uint64_t a10,
+ uint64_t a11,
+ uint64_t a12,
+ uint64_t a13,
+ uint64_t a14,
+ uint64_t a15,
+ uint64_t a16,
+ uint64_t a17,
+ uint64_t a18,
+ uint64_t a19,
+ uint64_t a20,
+ uint64_t a21,
+ uint64_t a22,
+ uint64_t a23,
+ uint64_t a24,
+ uint64_t a25,
+ uint64_t a26,
+ uint64_t a27,
+ uint64_t a28,
+ uint64_t a29,
+ uint64_t a30,
+ uint64_t a31,
+ uint64_t a32,
+ uint64_t a33,
+ uint64_t a34,
+ uint64_t a35,
+ uint64_t a36,
+ uint64_t a37,
+ uint64_t a38,
+ uint64_t a39,
+ uint64_t a40,
+ uint64_t a41,
+ uint64_t a42,
+ uint64_t a43,
+ uint64_t a44,
+ uint64_t a45,
+ uint64_t a46,
+ uint64_t a47,
+ uint64_t a48,
+ uint64_t a49,
+ uint64_t a50,
+ uint64_t a51,
+ uint64_t a52,
+ uint64_t a53,
+ uint64_t a54,
+ uint64_t a55,
+ uint64_t a56,
+ uint64_t a57,
+ uint64_t a58,
+ uint64_t a59,
+ uint64_t a60,
+ uint64_t a61,
+ uint64_t a62,
+ uint64_t a63,
+ uint64_t a64,
+ uint64_t a65,
+ uint64_t a66,
+ uint64_t a67,
+ uint64_t a68,
+ uint64_t a69,
+ uint64_t a70,
+ uint64_t a71,
+ uint64_t a72,
+ uint64_t a73,
+ uint64_t a74,
+ uint64_t a75,
+ uint64_t a76,
+ uint64_t a77,
+ uint64_t a78,
+ uint64_t a79,
+ uint64_t a80,
+ uint64_t a81,
+ uint64_t a82,
+ uint64_t a83,
+ uint64_t a84,
+ uint64_t a85,
+ uint64_t a86,
+ uint64_t a87,
+ uint64_t a88,
+ uint64_t a89,
+ uint64_t a90,
+ uint64_t a91,
+ uint64_t a92,
+ uint64_t a93,
+ uint64_t a94,
+ uint64_t a95,
+ uint64_t a96,
+ uint64_t a97,
+ uint64_t a98,
+ uint64_t a99,
+ uint64_t a100,
+ uint64_t a101,
+ uint64_t a102,
+ uint64_t a103,
+ uint64_t a104,
+ uint64_t a105,
+ uint64_t a106,
+ uint64_t a107,
+ uint64_t a108,
+ uint64_t a109,
+ uint64_t a110,
+ uint64_t a111,
+ uint64_t a112,
+ uint64_t a113,
+ uint64_t a114,
+ uint64_t a115,
+ uint64_t a116,
+ uint64_t a117,
+ uint64_t a118,
+ uint64_t a119,
+ uint64_t a120,
+ uint64_t a121,
+ uint64_t a122,
+ uint64_t a123,
+ uint64_t a124,
+ uint64_t a125,
+ uint64_t a126,
+ uint64_t a127)) {
+ uint64_t a0;
+ uint64_t a1;
+ uint64_t a2;
+ uint64_t a3;
+ uint64_t a4;
+ uint64_t a5;
+ uint64_t a6;
+ uint64_t a7;
+ uint64_t a8;
+ uint64_t a9;
+ uint64_t a10;
+ uint64_t a11;
+ uint64_t a12;
+ uint64_t a13;
+ uint64_t a14;
+ uint64_t a15;
+ uint64_t a16;
+ uint64_t a17;
+ uint64_t a18;
+ uint64_t a19;
+ uint64_t a20;
+ uint64_t a21;
+ uint64_t a22;
+ uint64_t a23;
+ uint64_t a24;
+ uint64_t a25;
+ uint64_t a26;
+ uint64_t a27;
+ uint64_t a28;
+ uint64_t a29;
+ uint64_t a30;
+ uint64_t a31;
+ uint64_t a32;
+ uint64_t a33;
+ uint64_t a34;
+ uint64_t a35;
+ uint64_t a36;
+ uint64_t a37;
+ uint64_t a38;
+ uint64_t a39;
+ uint64_t a40;
+ uint64_t a41;
+ uint64_t a42;
+ uint64_t a43;
+ uint64_t a44;
+ uint64_t a45;
+ uint64_t a46;
+ uint64_t a47;
+ uint64_t a48;
+ uint64_t a49;
+ uint64_t a50;
+ uint64_t a51;
+ uint64_t a52;
+ uint64_t a53;
+ uint64_t a54;
+ uint64_t a55;
+ uint64_t a56;
+ uint64_t a57;
+ uint64_t a58;
+ uint64_t a59;
+ uint64_t a60;
+ uint64_t a61;
+ uint64_t a62;
+ uint64_t a63;
+ uint64_t a64;
+ uint64_t a65;
+ uint64_t a66;
+ uint64_t a67;
+ uint64_t a68;
+ uint64_t a69;
+ uint64_t a70;
+ uint64_t a71;
+ uint64_t a72;
+ uint64_t a73;
+ uint64_t a74;
+ uint64_t a75;
+ uint64_t a76;
+ uint64_t a77;
+ uint64_t a78;
+ uint64_t a79;
+ uint64_t a80;
+ uint64_t a81;
+ uint64_t a82;
+ uint64_t a83;
+ uint64_t a84;
+ uint64_t a85;
+ uint64_t a86;
+ uint64_t a87;
+ uint64_t a88;
+ uint64_t a89;
+ uint64_t a90;
+ uint64_t a91;
+ uint64_t a92;
+ uint64_t a93;
+ uint64_t a94;
+ uint64_t a95;
+ uint64_t a96;
+ uint64_t a97;
+ uint64_t a98;
+ uint64_t a99;
+ uint64_t a100;
+ uint64_t a101;
+ uint64_t a102;
+ uint64_t a103;
+ uint64_t a104;
+ uint64_t a105;
+ uint64_t a106;
+ uint64_t a107;
+ uint64_t a108;
+ uint64_t a109;
+ uint64_t a110;
+ uint64_t a111;
+ uint64_t a112;
+ uint64_t a113;
+ uint64_t a114;
+ uint64_t a115;
+ uint64_t a116;
+ uint64_t a117;
+ uint64_t a118;
+ uint64_t a119;
+ uint64_t a120;
+ uint64_t a121;
+ uint64_t a122;
+ uint64_t a123;
+ uint64_t a124;
+ uint64_t a125;
+ uint64_t a126;
+ uint64_t a127;
+
+ a0 = 1;
+ a1 = 2;
+ a2 = 3;
+ a3 = 4;
+ a4 = 5;
+ a5 = 6;
+ a6 = 7;
+ a7 = 8;
+ a8 = 9;
+ a9 = 10;
+ a10 = 11;
+ a11 = 12;
+ a12 = 13;
+ a13 = 14;
+ a14 = 15;
+ a15 = 16;
+ a16 = 17;
+ a17 = 18;
+ a18 = 19;
+ a19 = 20;
+ a20 = 21;
+ a21 = 22;
+ a22 = 23;
+ a23 = 24;
+ a24 = 25;
+ a25 = 26;
+ a26 = 27;
+ a27 = 28;
+ a28 = 29;
+ a29 = 30;
+ a30 = 31;
+ a31 = 32;
+ a32 = 33;
+ a33 = 34;
+ a34 = 35;
+ a35 = 36;
+ a36 = 37;
+ a37 = 38;
+ a38 = 39;
+ a39 = 40;
+ a40 = 41;
+ a41 = 42;
+ a42 = 43;
+ a43 = 44;
+ a44 = 45;
+ a45 = 46;
+ a46 = 47;
+ a47 = 48;
+ a48 = 49;
+ a49 = 50;
+ a50 = 51;
+ a51 = 52;
+ a52 = 53;
+ a53 = 54;
+ a54 = 55;
+ a55 = 56;
+ a56 = 57;
+ a57 = 58;
+ a58 = 59;
+ a59 = 60;
+ a60 = 61;
+ a61 = 62;
+ a62 = 63;
+ a63 = 64;
+ a64 = 65;
+ a65 = 66;
+ a66 = 67;
+ a67 = 68;
+ a68 = 69;
+ a69 = 70;
+ a70 = 71;
+ a71 = 72;
+ a72 = 73;
+ a73 = 74;
+ a74 = 75;
+ a75 = 76;
+ a76 = 77;
+ a77 = 78;
+ a78 = 79;
+ a79 = 80;
+ a80 = 81;
+ a81 = 82;
+ a82 = 83;
+ a83 = 84;
+ a84 = 85;
+ a85 = 86;
+ a86 = 87;
+ a87 = 88;
+ a88 = 89;
+ a89 = 90;
+ a90 = 91;
+ a91 = 92;
+ a92 = 93;
+ a93 = 94;
+ a94 = 95;
+ a95 = 96;
+ a96 = 97;
+ a97 = 98;
+ a98 = 99;
+ a99 = 100;
+ a100 = 101;
+ a101 = 102;
+ a102 = 103;
+ a103 = 104;
+ a104 = 105;
+ a105 = 106;
+ a106 = 107;
+ a107 = 108;
+ a108 = 109;
+ a109 = 110;
+ a110 = 111;
+ a111 = 112;
+ a112 = 113;
+ a113 = 114;
+ a114 = 115;
+ a115 = 116;
+ a116 = 117;
+ a117 = 118;
+ a118 = 119;
+ a119 = 120;
+ a120 = 121;
+ a121 = 122;
+ a122 = 123;
+ a123 = 124;
+ a124 = 125;
+ a125 = 126;
+ a126 = 127;
+ a127 = 128;
+
+ std::cout << "Calling TestReturnStruct1024BytesHomogeneousUint64("
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4
+ << ", " << a5 << ", " << a6 << ", " << a7 << ", " << a8 << ", "
+ << a9 << ", " << a10 << ", " << a11 << ", " << a12 << ", " << a13
+ << ", " << a14 << ", " << a15 << ", " << a16 << ", " << a17 << ", "
+ << a18 << ", " << a19 << ", " << a20 << ", " << a21 << ", " << a22
+ << ", " << a23 << ", " << a24 << ", " << a25 << ", " << a26 << ", "
+ << a27 << ", " << a28 << ", " << a29 << ", " << a30 << ", " << a31
+ << ", " << a32 << ", " << a33 << ", " << a34 << ", " << a35 << ", "
+ << a36 << ", " << a37 << ", " << a38 << ", " << a39 << ", " << a40
+ << ", " << a41 << ", " << a42 << ", " << a43 << ", " << a44 << ", "
+ << a45 << ", " << a46 << ", " << a47 << ", " << a48 << ", " << a49
+ << ", " << a50 << ", " << a51 << ", " << a52 << ", " << a53 << ", "
+ << a54 << ", " << a55 << ", " << a56 << ", " << a57 << ", " << a58
+ << ", " << a59 << ", " << a60 << ", " << a61 << ", " << a62 << ", "
+ << a63 << ", " << a64 << ", " << a65 << ", " << a66 << ", " << a67
+ << ", " << a68 << ", " << a69 << ", " << a70 << ", " << a71 << ", "
+ << a72 << ", " << a73 << ", " << a74 << ", " << a75 << ", " << a76
+ << ", " << a77 << ", " << a78 << ", " << a79 << ", " << a80 << ", "
+ << a81 << ", " << a82 << ", " << a83 << ", " << a84 << ", " << a85
+ << ", " << a86 << ", " << a87 << ", " << a88 << ", " << a89 << ", "
+ << a90 << ", " << a91 << ", " << a92 << ", " << a93 << ", " << a94
+ << ", " << a95 << ", " << a96 << ", " << a97 << ", " << a98 << ", "
+ << a99 << ", " << a100 << ", " << a101 << ", " << a102 << ", "
+ << a103 << ", " << a104 << ", " << a105 << ", " << a106 << ", "
+ << a107 << ", " << a108 << ", " << a109 << ", " << a110 << ", "
+ << a111 << ", " << a112 << ", " << a113 << ", " << a114 << ", "
+ << a115 << ", " << a116 << ", " << a117 << ", " << a118 << ", "
+ << a119 << ", " << a120 << ", " << a121 << ", " << a122 << ", "
+ << a123 << ", " << a124 << ", " << a125 << ", " << a126 << ", "
+ << a127 << ")"
+ << ")\n";
+
+ Struct1024BytesHomogeneousUint64 result = f(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16,
+ a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31,
+ a32, a33, a34, a35, a36, a37, a38, a39, a40, a41, a42, a43, a44, a45, a46,
+ a47, a48, a49, a50, a51, a52, a53, a54, a55, a56, a57, a58, a59, a60, a61,
+ a62, a63, a64, a65, a66, a67, a68, a69, a70, a71, a72, a73, a74, a75, a76,
+ a77, a78, a79, a80, a81, a82, a83, a84, a85, a86, a87, a88, a89, a90, a91,
+ a92, a93, a94, a95, a96, a97, a98, a99, a100, a101, a102, a103, a104,
+ a105, a106, a107, a108, a109, a110, a111, a112, a113, a114, a115, a116,
+ a117, a118, a119, a120, a121, a122, a123, a124, a125, a126, a127);
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2
+ << ", " << result.a3 << ", " << result.a4 << ", " << result.a5
+ << ", " << result.a6 << ", " << result.a7 << ", " << result.a8
+ << ", " << result.a9 << ", " << result.a10 << ", " << result.a11
+ << ", " << result.a12 << ", " << result.a13 << ", " << result.a14
+ << ", " << result.a15 << ", " << result.a16 << ", " << result.a17
+ << ", " << result.a18 << ", " << result.a19 << ", " << result.a20
+ << ", " << result.a21 << ", " << result.a22 << ", " << result.a23
+ << ", " << result.a24 << ", " << result.a25 << ", " << result.a26
+ << ", " << result.a27 << ", " << result.a28 << ", " << result.a29
+ << ", " << result.a30 << ", " << result.a31 << ", " << result.a32
+ << ", " << result.a33 << ", " << result.a34 << ", " << result.a35
+ << ", " << result.a36 << ", " << result.a37 << ", " << result.a38
+ << ", " << result.a39 << ", " << result.a40 << ", " << result.a41
+ << ", " << result.a42 << ", " << result.a43 << ", " << result.a44
+ << ", " << result.a45 << ", " << result.a46 << ", " << result.a47
+ << ", " << result.a48 << ", " << result.a49 << ", " << result.a50
+ << ", " << result.a51 << ", " << result.a52 << ", " << result.a53
+ << ", " << result.a54 << ", " << result.a55 << ", " << result.a56
+ << ", " << result.a57 << ", " << result.a58 << ", " << result.a59
+ << ", " << result.a60 << ", " << result.a61 << ", " << result.a62
+ << ", " << result.a63 << ", " << result.a64 << ", " << result.a65
+ << ", " << result.a66 << ", " << result.a67 << ", " << result.a68
+ << ", " << result.a69 << ", " << result.a70 << ", " << result.a71
+ << ", " << result.a72 << ", " << result.a73 << ", " << result.a74
+ << ", " << result.a75 << ", " << result.a76 << ", " << result.a77
+ << ", " << result.a78 << ", " << result.a79 << ", " << result.a80
+ << ", " << result.a81 << ", " << result.a82 << ", " << result.a83
+ << ", " << result.a84 << ", " << result.a85 << ", " << result.a86
+ << ", " << result.a87 << ", " << result.a88 << ", " << result.a89
+ << ", " << result.a90 << ", " << result.a91 << ", " << result.a92
+ << ", " << result.a93 << ", " << result.a94 << ", " << result.a95
+ << ", " << result.a96 << ", " << result.a97 << ", " << result.a98
+ << ", " << result.a99 << ", " << result.a100 << ", " << result.a101
+ << ", " << result.a102 << ", " << result.a103 << ", " << result.a104
+ << ", " << result.a105 << ", " << result.a106 << ", " << result.a107
+ << ", " << result.a108 << ", " << result.a109 << ", " << result.a110
+ << ", " << result.a111 << ", " << result.a112 << ", " << result.a113
+ << ", " << result.a114 << ", " << result.a115 << ", " << result.a116
+ << ", " << result.a117 << ", " << result.a118 << ", " << result.a119
+ << ", " << result.a120 << ", " << result.a121 << ", " << result.a122
+ << ", " << result.a123 << ", " << result.a124 << ", " << result.a125
+ << ", " << result.a126 << ", " << result.a127 << ")"
+ << "\n";
+
+ CHECK_EQ(a0, result.a0);
+ CHECK_EQ(a1, result.a1);
+ CHECK_EQ(a2, result.a2);
+ CHECK_EQ(a3, result.a3);
+ CHECK_EQ(a4, result.a4);
+ CHECK_EQ(a5, result.a5);
+ CHECK_EQ(a6, result.a6);
+ CHECK_EQ(a7, result.a7);
+ CHECK_EQ(a8, result.a8);
+ CHECK_EQ(a9, result.a9);
+ CHECK_EQ(a10, result.a10);
+ CHECK_EQ(a11, result.a11);
+ CHECK_EQ(a12, result.a12);
+ CHECK_EQ(a13, result.a13);
+ CHECK_EQ(a14, result.a14);
+ CHECK_EQ(a15, result.a15);
+ CHECK_EQ(a16, result.a16);
+ CHECK_EQ(a17, result.a17);
+ CHECK_EQ(a18, result.a18);
+ CHECK_EQ(a19, result.a19);
+ CHECK_EQ(a20, result.a20);
+ CHECK_EQ(a21, result.a21);
+ CHECK_EQ(a22, result.a22);
+ CHECK_EQ(a23, result.a23);
+ CHECK_EQ(a24, result.a24);
+ CHECK_EQ(a25, result.a25);
+ CHECK_EQ(a26, result.a26);
+ CHECK_EQ(a27, result.a27);
+ CHECK_EQ(a28, result.a28);
+ CHECK_EQ(a29, result.a29);
+ CHECK_EQ(a30, result.a30);
+ CHECK_EQ(a31, result.a31);
+ CHECK_EQ(a32, result.a32);
+ CHECK_EQ(a33, result.a33);
+ CHECK_EQ(a34, result.a34);
+ CHECK_EQ(a35, result.a35);
+ CHECK_EQ(a36, result.a36);
+ CHECK_EQ(a37, result.a37);
+ CHECK_EQ(a38, result.a38);
+ CHECK_EQ(a39, result.a39);
+ CHECK_EQ(a40, result.a40);
+ CHECK_EQ(a41, result.a41);
+ CHECK_EQ(a42, result.a42);
+ CHECK_EQ(a43, result.a43);
+ CHECK_EQ(a44, result.a44);
+ CHECK_EQ(a45, result.a45);
+ CHECK_EQ(a46, result.a46);
+ CHECK_EQ(a47, result.a47);
+ CHECK_EQ(a48, result.a48);
+ CHECK_EQ(a49, result.a49);
+ CHECK_EQ(a50, result.a50);
+ CHECK_EQ(a51, result.a51);
+ CHECK_EQ(a52, result.a52);
+ CHECK_EQ(a53, result.a53);
+ CHECK_EQ(a54, result.a54);
+ CHECK_EQ(a55, result.a55);
+ CHECK_EQ(a56, result.a56);
+ CHECK_EQ(a57, result.a57);
+ CHECK_EQ(a58, result.a58);
+ CHECK_EQ(a59, result.a59);
+ CHECK_EQ(a60, result.a60);
+ CHECK_EQ(a61, result.a61);
+ CHECK_EQ(a62, result.a62);
+ CHECK_EQ(a63, result.a63);
+ CHECK_EQ(a64, result.a64);
+ CHECK_EQ(a65, result.a65);
+ CHECK_EQ(a66, result.a66);
+ CHECK_EQ(a67, result.a67);
+ CHECK_EQ(a68, result.a68);
+ CHECK_EQ(a69, result.a69);
+ CHECK_EQ(a70, result.a70);
+ CHECK_EQ(a71, result.a71);
+ CHECK_EQ(a72, result.a72);
+ CHECK_EQ(a73, result.a73);
+ CHECK_EQ(a74, result.a74);
+ CHECK_EQ(a75, result.a75);
+ CHECK_EQ(a76, result.a76);
+ CHECK_EQ(a77, result.a77);
+ CHECK_EQ(a78, result.a78);
+ CHECK_EQ(a79, result.a79);
+ CHECK_EQ(a80, result.a80);
+ CHECK_EQ(a81, result.a81);
+ CHECK_EQ(a82, result.a82);
+ CHECK_EQ(a83, result.a83);
+ CHECK_EQ(a84, result.a84);
+ CHECK_EQ(a85, result.a85);
+ CHECK_EQ(a86, result.a86);
+ CHECK_EQ(a87, result.a87);
+ CHECK_EQ(a88, result.a88);
+ CHECK_EQ(a89, result.a89);
+ CHECK_EQ(a90, result.a90);
+ CHECK_EQ(a91, result.a91);
+ CHECK_EQ(a92, result.a92);
+ CHECK_EQ(a93, result.a93);
+ CHECK_EQ(a94, result.a94);
+ CHECK_EQ(a95, result.a95);
+ CHECK_EQ(a96, result.a96);
+ CHECK_EQ(a97, result.a97);
+ CHECK_EQ(a98, result.a98);
+ CHECK_EQ(a99, result.a99);
+ CHECK_EQ(a100, result.a100);
+ CHECK_EQ(a101, result.a101);
+ CHECK_EQ(a102, result.a102);
+ CHECK_EQ(a103, result.a103);
+ CHECK_EQ(a104, result.a104);
+ CHECK_EQ(a105, result.a105);
+ CHECK_EQ(a106, result.a106);
+ CHECK_EQ(a107, result.a107);
+ CHECK_EQ(a108, result.a108);
+ CHECK_EQ(a109, result.a109);
+ CHECK_EQ(a110, result.a110);
+ CHECK_EQ(a111, result.a111);
+ CHECK_EQ(a112, result.a112);
+ CHECK_EQ(a113, result.a113);
+ CHECK_EQ(a114, result.a114);
+ CHECK_EQ(a115, result.a115);
+ CHECK_EQ(a116, result.a116);
+ CHECK_EQ(a117, result.a117);
+ CHECK_EQ(a118, result.a118);
+ CHECK_EQ(a119, result.a119);
+ CHECK_EQ(a120, result.a120);
+ CHECK_EQ(a121, result.a121);
+ CHECK_EQ(a122, result.a122);
+ CHECK_EQ(a123, result.a123);
+ CHECK_EQ(a124, result.a124);
+ CHECK_EQ(a125, result.a125);
+ CHECK_EQ(a126, result.a126);
+ CHECK_EQ(a127, result.a127);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16,
+ a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31,
+ a32, a33, a34, a35, a36, a37, a38, a39, a40, a41, a42, a43, a44, a45, a46,
+ a47, a48, a49, a50, a51, a52, a53, a54, a55, a56, a57, a58, a59, a60, a61,
+ a62, a63, a64, a65, a66, a67, a68, a69, a70, a71, a72, a73, a74, a75, a76,
+ a77, a78, a79, a80, a81, a82, a83, a84, a85, a86, a87, a88, a89, a90, a91,
+ a92, a93, a94, a95, a96, a97, a98, a99, a100, a101, a102, a103, a104,
+ a105, a106, a107, a108, a109, a110, a111, a112, a113, a114, a115, a116,
+ a117, a118, a119, a120, a121, a122, a123, a124, a125, a126, a127);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+ CHECK_EQ(0, result.a3);
+ CHECK_EQ(0, result.a4);
+ CHECK_EQ(0, result.a5);
+ CHECK_EQ(0, result.a6);
+ CHECK_EQ(0, result.a7);
+ CHECK_EQ(0, result.a8);
+ CHECK_EQ(0, result.a9);
+ CHECK_EQ(0, result.a10);
+ CHECK_EQ(0, result.a11);
+ CHECK_EQ(0, result.a12);
+ CHECK_EQ(0, result.a13);
+ CHECK_EQ(0, result.a14);
+ CHECK_EQ(0, result.a15);
+ CHECK_EQ(0, result.a16);
+ CHECK_EQ(0, result.a17);
+ CHECK_EQ(0, result.a18);
+ CHECK_EQ(0, result.a19);
+ CHECK_EQ(0, result.a20);
+ CHECK_EQ(0, result.a21);
+ CHECK_EQ(0, result.a22);
+ CHECK_EQ(0, result.a23);
+ CHECK_EQ(0, result.a24);
+ CHECK_EQ(0, result.a25);
+ CHECK_EQ(0, result.a26);
+ CHECK_EQ(0, result.a27);
+ CHECK_EQ(0, result.a28);
+ CHECK_EQ(0, result.a29);
+ CHECK_EQ(0, result.a30);
+ CHECK_EQ(0, result.a31);
+ CHECK_EQ(0, result.a32);
+ CHECK_EQ(0, result.a33);
+ CHECK_EQ(0, result.a34);
+ CHECK_EQ(0, result.a35);
+ CHECK_EQ(0, result.a36);
+ CHECK_EQ(0, result.a37);
+ CHECK_EQ(0, result.a38);
+ CHECK_EQ(0, result.a39);
+ CHECK_EQ(0, result.a40);
+ CHECK_EQ(0, result.a41);
+ CHECK_EQ(0, result.a42);
+ CHECK_EQ(0, result.a43);
+ CHECK_EQ(0, result.a44);
+ CHECK_EQ(0, result.a45);
+ CHECK_EQ(0, result.a46);
+ CHECK_EQ(0, result.a47);
+ CHECK_EQ(0, result.a48);
+ CHECK_EQ(0, result.a49);
+ CHECK_EQ(0, result.a50);
+ CHECK_EQ(0, result.a51);
+ CHECK_EQ(0, result.a52);
+ CHECK_EQ(0, result.a53);
+ CHECK_EQ(0, result.a54);
+ CHECK_EQ(0, result.a55);
+ CHECK_EQ(0, result.a56);
+ CHECK_EQ(0, result.a57);
+ CHECK_EQ(0, result.a58);
+ CHECK_EQ(0, result.a59);
+ CHECK_EQ(0, result.a60);
+ CHECK_EQ(0, result.a61);
+ CHECK_EQ(0, result.a62);
+ CHECK_EQ(0, result.a63);
+ CHECK_EQ(0, result.a64);
+ CHECK_EQ(0, result.a65);
+ CHECK_EQ(0, result.a66);
+ CHECK_EQ(0, result.a67);
+ CHECK_EQ(0, result.a68);
+ CHECK_EQ(0, result.a69);
+ CHECK_EQ(0, result.a70);
+ CHECK_EQ(0, result.a71);
+ CHECK_EQ(0, result.a72);
+ CHECK_EQ(0, result.a73);
+ CHECK_EQ(0, result.a74);
+ CHECK_EQ(0, result.a75);
+ CHECK_EQ(0, result.a76);
+ CHECK_EQ(0, result.a77);
+ CHECK_EQ(0, result.a78);
+ CHECK_EQ(0, result.a79);
+ CHECK_EQ(0, result.a80);
+ CHECK_EQ(0, result.a81);
+ CHECK_EQ(0, result.a82);
+ CHECK_EQ(0, result.a83);
+ CHECK_EQ(0, result.a84);
+ CHECK_EQ(0, result.a85);
+ CHECK_EQ(0, result.a86);
+ CHECK_EQ(0, result.a87);
+ CHECK_EQ(0, result.a88);
+ CHECK_EQ(0, result.a89);
+ CHECK_EQ(0, result.a90);
+ CHECK_EQ(0, result.a91);
+ CHECK_EQ(0, result.a92);
+ CHECK_EQ(0, result.a93);
+ CHECK_EQ(0, result.a94);
+ CHECK_EQ(0, result.a95);
+ CHECK_EQ(0, result.a96);
+ CHECK_EQ(0, result.a97);
+ CHECK_EQ(0, result.a98);
+ CHECK_EQ(0, result.a99);
+ CHECK_EQ(0, result.a100);
+ CHECK_EQ(0, result.a101);
+ CHECK_EQ(0, result.a102);
+ CHECK_EQ(0, result.a103);
+ CHECK_EQ(0, result.a104);
+ CHECK_EQ(0, result.a105);
+ CHECK_EQ(0, result.a106);
+ CHECK_EQ(0, result.a107);
+ CHECK_EQ(0, result.a108);
+ CHECK_EQ(0, result.a109);
+ CHECK_EQ(0, result.a110);
+ CHECK_EQ(0, result.a111);
+ CHECK_EQ(0, result.a112);
+ CHECK_EQ(0, result.a113);
+ CHECK_EQ(0, result.a114);
+ CHECK_EQ(0, result.a115);
+ CHECK_EQ(0, result.a116);
+ CHECK_EQ(0, result.a117);
+ CHECK_EQ(0, result.a118);
+ CHECK_EQ(0, result.a119);
+ CHECK_EQ(0, result.a120);
+ CHECK_EQ(0, result.a121);
+ CHECK_EQ(0, result.a122);
+ CHECK_EQ(0, result.a123);
+ CHECK_EQ(0, result.a124);
+ CHECK_EQ(0, result.a125);
+ CHECK_EQ(0, result.a126);
+ CHECK_EQ(0, result.a127);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16,
+ a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31,
+ a32, a33, a34, a35, a36, a37, a38, a39, a40, a41, a42, a43, a44, a45, a46,
+ a47, a48, a49, a50, a51, a52, a53, a54, a55, a56, a57, a58, a59, a60, a61,
+ a62, a63, a64, a65, a66, a67, a68, a69, a70, a71, a72, a73, a74, a75, a76,
+ a77, a78, a79, a80, a81, a82, a83, a84, a85, a86, a87, a88, a89, a90, a91,
+ a92, a93, a94, a95, a96, a97, a98, a99, a100, a101, a102, a103, a104,
+ a105, a106, a107, a108, a109, a110, a111, a112, a113, a114, a115, a116,
+ a117, a118, a119, a120, a121, a122, a123, a124, a125, a126, a127);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+ CHECK_EQ(0, result.a3);
+ CHECK_EQ(0, result.a4);
+ CHECK_EQ(0, result.a5);
+ CHECK_EQ(0, result.a6);
+ CHECK_EQ(0, result.a7);
+ CHECK_EQ(0, result.a8);
+ CHECK_EQ(0, result.a9);
+ CHECK_EQ(0, result.a10);
+ CHECK_EQ(0, result.a11);
+ CHECK_EQ(0, result.a12);
+ CHECK_EQ(0, result.a13);
+ CHECK_EQ(0, result.a14);
+ CHECK_EQ(0, result.a15);
+ CHECK_EQ(0, result.a16);
+ CHECK_EQ(0, result.a17);
+ CHECK_EQ(0, result.a18);
+ CHECK_EQ(0, result.a19);
+ CHECK_EQ(0, result.a20);
+ CHECK_EQ(0, result.a21);
+ CHECK_EQ(0, result.a22);
+ CHECK_EQ(0, result.a23);
+ CHECK_EQ(0, result.a24);
+ CHECK_EQ(0, result.a25);
+ CHECK_EQ(0, result.a26);
+ CHECK_EQ(0, result.a27);
+ CHECK_EQ(0, result.a28);
+ CHECK_EQ(0, result.a29);
+ CHECK_EQ(0, result.a30);
+ CHECK_EQ(0, result.a31);
+ CHECK_EQ(0, result.a32);
+ CHECK_EQ(0, result.a33);
+ CHECK_EQ(0, result.a34);
+ CHECK_EQ(0, result.a35);
+ CHECK_EQ(0, result.a36);
+ CHECK_EQ(0, result.a37);
+ CHECK_EQ(0, result.a38);
+ CHECK_EQ(0, result.a39);
+ CHECK_EQ(0, result.a40);
+ CHECK_EQ(0, result.a41);
+ CHECK_EQ(0, result.a42);
+ CHECK_EQ(0, result.a43);
+ CHECK_EQ(0, result.a44);
+ CHECK_EQ(0, result.a45);
+ CHECK_EQ(0, result.a46);
+ CHECK_EQ(0, result.a47);
+ CHECK_EQ(0, result.a48);
+ CHECK_EQ(0, result.a49);
+ CHECK_EQ(0, result.a50);
+ CHECK_EQ(0, result.a51);
+ CHECK_EQ(0, result.a52);
+ CHECK_EQ(0, result.a53);
+ CHECK_EQ(0, result.a54);
+ CHECK_EQ(0, result.a55);
+ CHECK_EQ(0, result.a56);
+ CHECK_EQ(0, result.a57);
+ CHECK_EQ(0, result.a58);
+ CHECK_EQ(0, result.a59);
+ CHECK_EQ(0, result.a60);
+ CHECK_EQ(0, result.a61);
+ CHECK_EQ(0, result.a62);
+ CHECK_EQ(0, result.a63);
+ CHECK_EQ(0, result.a64);
+ CHECK_EQ(0, result.a65);
+ CHECK_EQ(0, result.a66);
+ CHECK_EQ(0, result.a67);
+ CHECK_EQ(0, result.a68);
+ CHECK_EQ(0, result.a69);
+ CHECK_EQ(0, result.a70);
+ CHECK_EQ(0, result.a71);
+ CHECK_EQ(0, result.a72);
+ CHECK_EQ(0, result.a73);
+ CHECK_EQ(0, result.a74);
+ CHECK_EQ(0, result.a75);
+ CHECK_EQ(0, result.a76);
+ CHECK_EQ(0, result.a77);
+ CHECK_EQ(0, result.a78);
+ CHECK_EQ(0, result.a79);
+ CHECK_EQ(0, result.a80);
+ CHECK_EQ(0, result.a81);
+ CHECK_EQ(0, result.a82);
+ CHECK_EQ(0, result.a83);
+ CHECK_EQ(0, result.a84);
+ CHECK_EQ(0, result.a85);
+ CHECK_EQ(0, result.a86);
+ CHECK_EQ(0, result.a87);
+ CHECK_EQ(0, result.a88);
+ CHECK_EQ(0, result.a89);
+ CHECK_EQ(0, result.a90);
+ CHECK_EQ(0, result.a91);
+ CHECK_EQ(0, result.a92);
+ CHECK_EQ(0, result.a93);
+ CHECK_EQ(0, result.a94);
+ CHECK_EQ(0, result.a95);
+ CHECK_EQ(0, result.a96);
+ CHECK_EQ(0, result.a97);
+ CHECK_EQ(0, result.a98);
+ CHECK_EQ(0, result.a99);
+ CHECK_EQ(0, result.a100);
+ CHECK_EQ(0, result.a101);
+ CHECK_EQ(0, result.a102);
+ CHECK_EQ(0, result.a103);
+ CHECK_EQ(0, result.a104);
+ CHECK_EQ(0, result.a105);
+ CHECK_EQ(0, result.a106);
+ CHECK_EQ(0, result.a107);
+ CHECK_EQ(0, result.a108);
+ CHECK_EQ(0, result.a109);
+ CHECK_EQ(0, result.a110);
+ CHECK_EQ(0, result.a111);
+ CHECK_EQ(0, result.a112);
+ CHECK_EQ(0, result.a113);
+ CHECK_EQ(0, result.a114);
+ CHECK_EQ(0, result.a115);
+ CHECK_EQ(0, result.a116);
+ CHECK_EQ(0, result.a117);
+ CHECK_EQ(0, result.a118);
+ CHECK_EQ(0, result.a119);
+ CHECK_EQ(0, result.a120);
+ CHECK_EQ(0, result.a121);
+ CHECK_EQ(0, result.a122);
+ CHECK_EQ(0, result.a123);
+ CHECK_EQ(0, result.a124);
+ CHECK_EQ(0, result.a125);
+ CHECK_EQ(0, result.a126);
+ CHECK_EQ(0, result.a127);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Test that a struct passed in as argument can be returned.
+// Especially for ffi callbacks.
+// Struct is passed in int registers in most ABIs.
+DART_EXPORT intptr_t TestReturnStructArgumentStruct1ByteInt(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct1ByteInt (*f)(Struct1ByteInt a0)) {
+ Struct1ByteInt a0;
+
+ a0.a0 = -1;
+
+ std::cout << "Calling TestReturnStructArgumentStruct1ByteInt("
+ << "((" << static_cast<int>(a0.a0) << "))"
+ << ")\n";
+
+ Struct1ByteInt result = f(a0);
+
+ std::cout << "result = "
+ << "(" << static_cast<int>(result.a0) << ")"
+ << "\n";
+
+ CHECK_EQ(a0.a0, result.a0);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0);
+
+ CHECK_EQ(0, result.a0);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0);
+
+ CHECK_EQ(0, result.a0);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Test that a struct passed in as argument can be returned.
+// Especially for ffi callbacks.
+// Struct is passed on stack on all ABIs.
+DART_EXPORT intptr_t TestReturnStructArgumentInt32x8Struct1ByteInt(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct1ByteInt (*f)(int32_t a0,
+ int32_t a1,
+ int32_t a2,
+ int32_t a3,
+ int32_t a4,
+ int32_t a5,
+ int32_t a6,
+ int32_t a7,
+ Struct1ByteInt a8)) {
+ int32_t a0;
+ int32_t a1;
+ int32_t a2;
+ int32_t a3;
+ int32_t a4;
+ int32_t a5;
+ int32_t a6;
+ int32_t a7;
+ Struct1ByteInt a8;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+ a3 = 4;
+ a4 = -5;
+ a5 = 6;
+ a6 = -7;
+ a7 = 8;
+ a8.a0 = -9;
+
+ std::cout << "Calling TestReturnStructArgumentInt32x8Struct1ByteInt("
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4
+ << ", " << a5 << ", " << a6 << ", " << a7 << ", ("
+ << static_cast<int>(a8.a0) << "))"
+ << ")\n";
+
+ Struct1ByteInt result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ std::cout << "result = "
+ << "(" << static_cast<int>(result.a0) << ")"
+ << "\n";
+
+ CHECK_EQ(a8.a0, result.a0);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ CHECK_EQ(0, result.a0);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ CHECK_EQ(0, result.a0);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Test that a struct passed in as argument can be returned.
+// Especially for ffi callbacks.
+// Struct is passed in float registers in most ABIs.
+DART_EXPORT intptr_t TestReturnStructArgumentStruct8BytesHomogeneousFloat(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct8BytesHomogeneousFloat (*f)(Struct8BytesHomogeneousFloat a0)) {
+ Struct8BytesHomogeneousFloat a0;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+
+ std::cout << "Calling TestReturnStructArgumentStruct8BytesHomogeneousFloat("
+ << "((" << a0.a0 << ", " << a0.a1 << "))"
+ << ")\n";
+
+ Struct8BytesHomogeneousFloat result = f(a0);
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ")"
+ << "\n";
+
+ CHECK_APPROX(a0.a0, result.a0);
+ CHECK_APPROX(a0.a1, result.a1);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0);
+
+ CHECK_APPROX(0.0, result.a0);
+ CHECK_APPROX(0.0, result.a1);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0);
+
+ CHECK_APPROX(0.0, result.a0);
+ CHECK_APPROX(0.0, result.a1);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// On arm64, both argument and return value are passed in by pointer.
+DART_EXPORT intptr_t TestReturnStructArgumentStruct20BytesHomogeneousInt32(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct20BytesHomogeneousInt32 (*f)(Struct20BytesHomogeneousInt32 a0)) {
+ Struct20BytesHomogeneousInt32 a0;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+ a0.a3 = 4;
+ a0.a4 = -5;
+
+ std::cout << "Calling TestReturnStructArgumentStruct20BytesHomogeneousInt32("
+ << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3
+ << ", " << a0.a4 << "))"
+ << ")\n";
+
+ Struct20BytesHomogeneousInt32 result = f(a0);
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2
+ << ", " << result.a3 << ", " << result.a4 << ")"
+ << "\n";
+
+ CHECK_EQ(a0.a0, result.a0);
+ CHECK_EQ(a0.a1, result.a1);
+ CHECK_EQ(a0.a2, result.a2);
+ CHECK_EQ(a0.a3, result.a3);
+ CHECK_EQ(a0.a4, result.a4);
+
+ // Pass argument that will make the Dart callback throw.
+ a0.a0 = 42;
+
+ result = f(a0);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+ CHECK_EQ(0, result.a3);
+ CHECK_EQ(0, result.a4);
+
+ // Pass argument that will make the Dart callback return null.
+ a0.a0 = 84;
+
+ result = f(a0);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+ CHECK_EQ(0, result.a3);
+ CHECK_EQ(0, result.a4);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// On arm64, both argument and return value are passed in by pointer.
+// Ints exhaust registers, so that pointer is passed on stack.
+DART_EXPORT intptr_t TestReturnStructArgumentInt32x8Struct20BytesHomogeneou(
+ // NOLINTNEXTLINE(whitespace/parens)
+ Struct20BytesHomogeneousInt32 (*f)(int32_t a0,
+ int32_t a1,
+ int32_t a2,
+ int32_t a3,
+ int32_t a4,
+ int32_t a5,
+ int32_t a6,
+ int32_t a7,
+ Struct20BytesHomogeneousInt32 a8)) {
+ int32_t a0;
+ int32_t a1;
+ int32_t a2;
+ int32_t a3;
+ int32_t a4;
+ int32_t a5;
+ int32_t a6;
+ int32_t a7;
+ Struct20BytesHomogeneousInt32 a8;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+ a3 = 4;
+ a4 = -5;
+ a5 = 6;
+ a6 = -7;
+ a7 = 8;
+ a8.a0 = -9;
+ a8.a1 = 10;
+ a8.a2 = -11;
+ a8.a3 = 12;
+ a8.a4 = -13;
+
+ std::cout << "Calling TestReturnStructArgumentInt32x8Struct20BytesHomogeneou("
+ << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4
+ << ", " << a5 << ", " << a6 << ", " << a7 << ", (" << a8.a0 << ", "
+ << a8.a1 << ", " << a8.a2 << ", " << a8.a3 << ", " << a8.a4 << "))"
+ << ")\n";
+
+ Struct20BytesHomogeneousInt32 result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ std::cout << "result = "
+ << "(" << result.a0 << ", " << result.a1 << ", " << result.a2
+ << ", " << result.a3 << ", " << result.a4 << ")"
+ << "\n";
+
+ CHECK_EQ(a8.a0, result.a0);
+ CHECK_EQ(a8.a1, result.a1);
+ CHECK_EQ(a8.a2, result.a2);
+ CHECK_EQ(a8.a3, result.a3);
+ CHECK_EQ(a8.a4, result.a4);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+ CHECK_EQ(0, result.a3);
+ CHECK_EQ(0, result.a4);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+ CHECK_EQ(0, result.a3);
+ CHECK_EQ(0, result.a4);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of 16 byte int within struct.
+DART_EXPORT intptr_t TestReturnStructAlignmentInt16(
+ // NOLINTNEXTLINE(whitespace/parens)
+ StructAlignmentInt16 (*f)(int8_t a0, int16_t a1, int8_t a2)) {
+ int8_t a0;
+ int16_t a1;
+ int8_t a2;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+
+ std::cout << "Calling TestReturnStructAlignmentInt16("
+ << "(" << static_cast<int>(a0) << ", " << a1 << ", "
+ << static_cast<int>(a2) << ")"
+ << ")\n";
+
+ StructAlignmentInt16 result = f(a0, a1, a2);
+
+ std::cout << "result = "
+ << "(" << static_cast<int>(result.a0) << ", " << result.a1 << ", "
+ << static_cast<int>(result.a2) << ")"
+ << "\n";
+
+ CHECK_EQ(a0, result.a0);
+ CHECK_EQ(a1, result.a1);
+ CHECK_EQ(a2, result.a2);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of 32 byte int within struct.
+DART_EXPORT intptr_t TestReturnStructAlignmentInt32(
+ // NOLINTNEXTLINE(whitespace/parens)
+ StructAlignmentInt32 (*f)(int8_t a0, int32_t a1, int8_t a2)) {
+ int8_t a0;
+ int32_t a1;
+ int8_t a2;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+
+ std::cout << "Calling TestReturnStructAlignmentInt32("
+ << "(" << static_cast<int>(a0) << ", " << a1 << ", "
+ << static_cast<int>(a2) << ")"
+ << ")\n";
+
+ StructAlignmentInt32 result = f(a0, a1, a2);
+
+ std::cout << "result = "
+ << "(" << static_cast<int>(result.a0) << ", " << result.a1 << ", "
+ << static_cast<int>(result.a2) << ")"
+ << "\n";
+
+ CHECK_EQ(a0, result.a0);
+ CHECK_EQ(a1, result.a1);
+ CHECK_EQ(a2, result.a2);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+
+ return 0;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of 64 byte int within struct.
+DART_EXPORT intptr_t TestReturnStructAlignmentInt64(
+ // NOLINTNEXTLINE(whitespace/parens)
+ StructAlignmentInt64 (*f)(int8_t a0, int64_t a1, int8_t a2)) {
+ int8_t a0;
+ int64_t a1;
+ int8_t a2;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+
+ std::cout << "Calling TestReturnStructAlignmentInt64("
+ << "(" << static_cast<int>(a0) << ", " << a1 << ", "
+ << static_cast<int>(a2) << ")"
+ << ")\n";
+
+ StructAlignmentInt64 result = f(a0, a1, a2);
+
+ std::cout << "result = "
+ << "(" << static_cast<int>(result.a0) << ", " << result.a1 << ", "
+ << static_cast<int>(result.a2) << ")"
+ << "\n";
+
+ CHECK_EQ(a0, result.a0);
+ CHECK_EQ(a1, result.a1);
+ CHECK_EQ(a2, result.a2);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2);
+
+ CHECK_EQ(0, result.a0);
+ CHECK_EQ(0, result.a1);
+ CHECK_EQ(0, result.a2);
+
+ return 0;
+}
+
+} // namespace dart
diff --git a/tests/ffi/callback_tests_utils.dart b/tests/ffi/callback_tests_utils.dart
index ac5fdcb..e34a52b 100644
--- a/tests/ffi/callback_tests_utils.dart
+++ b/tests/ffi/callback_tests_utils.dart
@@ -16,19 +16,23 @@
class CallbackTest {
final String name;
final Pointer callback;
- final bool skip;
+ final void Function() afterCallbackChecks;
- CallbackTest(this.name, this.callback, {bool skipIf: false})
- : skip = skipIf {}
+ CallbackTest(this.name, this.callback) : afterCallbackChecks = noChecks {}
+ CallbackTest.withCheck(this.name, this.callback, this.afterCallbackChecks) {}
void run() {
- if (skip) return;
-
final NativeCallbackTestFn tester = ffiTestFunctions
.lookupFunction<NativeCallbackTest, NativeCallbackTestFn>("Test$name");
+
final int testCode = tester(callback);
+
if (testCode != 0) {
Expect.fail("Test $name failed.");
}
+
+ afterCallbackChecks();
}
}
+
+void noChecks() {}
diff --git a/tests/ffi/ffi.status b/tests/ffi/ffi.status
index 37ab3e9..3baf069 100644
--- a/tests/ffi/ffi.status
+++ b/tests/ffi/ffi.status
@@ -2,6 +2,11 @@
# 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.
+# TODO(dartbug.com/36730): Implement structs by value.
+function_callbacks_structs_by_value_generated_test: Skip
+function_callbacks_structs_by_value_test: Skip
+function_structs_by_value_generated_test: Skip
+
[ $builder_tag == msan ]
vmspecific_handle_test: Skip # https://dartbug.com/42314
diff --git a/tests/ffi/function_callbacks_structs_by_value_generated_test.dart b/tests/ffi/function_callbacks_structs_by_value_generated_test.dart
new file mode 100644
index 0000000..8499285
--- /dev/null
+++ b/tests/ffi/function_callbacks_structs_by_value_generated_test.dart
@@ -0,0 +1,5896 @@
+// Copyright (c) 2020, 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.
+//
+// This file has been automatically generated. Please do not edit it manually.
+//
+// SharedObjects=ffi_test_functions
+// VMOptions=
+// VMOptions=--deterministic --optimization-counter-threshold=10
+// VMOptions=--use-slow-path
+// VMOptions=--use-slow-path --stacktrace-every=100
+
+import 'dart:ffi';
+
+import "package:expect/expect.dart";
+import "package:ffi/ffi.dart";
+
+import 'callback_tests_utils.dart';
+
+// Reuse the struct classes.
+import 'function_structs_by_value_generated_test.dart';
+
+void main() {
+ testCases.forEach((t) {
+ print("==== Running " + t.name);
+ t.run();
+ });
+}
+
+final testCases = [
+ CallbackTest.withCheck(
+ "PassStruct1ByteIntx10",
+ Pointer.fromFunction<PassStruct1ByteIntx10Type>(passStruct1ByteIntx10, 0),
+ passStruct1ByteIntx10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct3BytesIntx10",
+ Pointer.fromFunction<PassStruct3BytesIntx10Type>(
+ passStruct3BytesIntx10, 0),
+ passStruct3BytesIntx10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct4BytesHomogeneousInt16x10",
+ Pointer.fromFunction<PassStruct4BytesHomogeneousInt16x10Type>(
+ passStruct4BytesHomogeneousInt16x10, 0),
+ passStruct4BytesHomogeneousInt16x10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct7BytesIntx10",
+ Pointer.fromFunction<PassStruct7BytesIntx10Type>(
+ passStruct7BytesIntx10, 0),
+ passStruct7BytesIntx10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct8BytesIntx10",
+ Pointer.fromFunction<PassStruct8BytesIntx10Type>(
+ passStruct8BytesIntx10, 0),
+ passStruct8BytesIntx10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct8BytesHomogeneousFloatx10",
+ Pointer.fromFunction<PassStruct8BytesHomogeneousFloatx10Type>(
+ passStruct8BytesHomogeneousFloatx10, 0.0),
+ passStruct8BytesHomogeneousFloatx10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct8BytesMixedx10",
+ Pointer.fromFunction<PassStruct8BytesMixedx10Type>(
+ passStruct8BytesMixedx10, 0.0),
+ passStruct8BytesMixedx10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct9BytesIntx10",
+ Pointer.fromFunction<PassStruct9BytesIntx10Type>(
+ passStruct9BytesIntx10, 0),
+ passStruct9BytesIntx10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct9BytesHomogeneousUint82x10",
+ Pointer.fromFunction<PassStruct9BytesHomogeneousUint82x10Type>(
+ passStruct9BytesHomogeneousUint82x10, 0),
+ passStruct9BytesHomogeneousUint82x10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct12BytesHomogeneousFloatx6",
+ Pointer.fromFunction<PassStruct12BytesHomogeneousFloatx6Type>(
+ passStruct12BytesHomogeneousFloatx6, 0.0),
+ passStruct12BytesHomogeneousFloatx6AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct16BytesHomogeneousFloatx5",
+ Pointer.fromFunction<PassStruct16BytesHomogeneousFloatx5Type>(
+ passStruct16BytesHomogeneousFloatx5, 0.0),
+ passStruct16BytesHomogeneousFloatx5AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct16BytesMixedx10",
+ Pointer.fromFunction<PassStruct16BytesMixedx10Type>(
+ passStruct16BytesMixedx10, 0.0),
+ passStruct16BytesMixedx10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct16BytesMixed2x10",
+ Pointer.fromFunction<PassStruct16BytesMixed2x10Type>(
+ passStruct16BytesMixed2x10, 0.0),
+ passStruct16BytesMixed2x10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct17BytesIntx10",
+ Pointer.fromFunction<PassStruct17BytesIntx10Type>(
+ passStruct17BytesIntx10, 0),
+ passStruct17BytesIntx10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct19BytesHomogeneousUint8x10",
+ Pointer.fromFunction<PassStruct19BytesHomogeneousUint8x10Type>(
+ passStruct19BytesHomogeneousUint8x10, 0),
+ passStruct19BytesHomogeneousUint8x10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct20BytesHomogeneousInt32x10",
+ Pointer.fromFunction<PassStruct20BytesHomogeneousInt32x10Type>(
+ passStruct20BytesHomogeneousInt32x10, 0),
+ passStruct20BytesHomogeneousInt32x10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct20BytesHomogeneousFloat",
+ Pointer.fromFunction<PassStruct20BytesHomogeneousFloatType>(
+ passStruct20BytesHomogeneousFloat, 0.0),
+ passStruct20BytesHomogeneousFloatAfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct32BytesHomogeneousDoublex5",
+ Pointer.fromFunction<PassStruct32BytesHomogeneousDoublex5Type>(
+ passStruct32BytesHomogeneousDoublex5, 0.0),
+ passStruct32BytesHomogeneousDoublex5AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct40BytesHomogeneousDouble",
+ Pointer.fromFunction<PassStruct40BytesHomogeneousDoubleType>(
+ passStruct40BytesHomogeneousDouble, 0.0),
+ passStruct40BytesHomogeneousDoubleAfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct1024BytesHomogeneousUint64",
+ Pointer.fromFunction<PassStruct1024BytesHomogeneousUint64Type>(
+ passStruct1024BytesHomogeneousUint64, 0),
+ passStruct1024BytesHomogeneousUint64AfterCallback),
+ CallbackTest.withCheck(
+ "PassFloatStruct16BytesHomogeneousFloatFloatStruct1",
+ Pointer.fromFunction<
+ PassFloatStruct16BytesHomogeneousFloatFloatStruct1Type>(
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1, 0.0),
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1AfterCallback),
+ CallbackTest.withCheck(
+ "PassFloatStruct32BytesHomogeneousDoubleFloatStruct",
+ Pointer.fromFunction<
+ PassFloatStruct32BytesHomogeneousDoubleFloatStructType>(
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct, 0.0),
+ passFloatStruct32BytesHomogeneousDoubleFloatStructAfterCallback),
+ CallbackTest.withCheck(
+ "PassInt8Struct16BytesMixedInt8Struct16BytesMixedIn",
+ Pointer.fromFunction<
+ PassInt8Struct16BytesMixedInt8Struct16BytesMixedInType>(
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedIn, 0.0),
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedInAfterCallback),
+ CallbackTest.withCheck(
+ "PassDoublex6Struct16BytesMixedx4Int32",
+ Pointer.fromFunction<PassDoublex6Struct16BytesMixedx4Int32Type>(
+ passDoublex6Struct16BytesMixedx4Int32, 0.0),
+ passDoublex6Struct16BytesMixedx4Int32AfterCallback),
+ CallbackTest.withCheck(
+ "PassInt32x4Struct16BytesMixedx4Double",
+ Pointer.fromFunction<PassInt32x4Struct16BytesMixedx4DoubleType>(
+ passInt32x4Struct16BytesMixedx4Double, 0.0),
+ passInt32x4Struct16BytesMixedx4DoubleAfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct40BytesHomogeneousDoubleStruct4BytesHomo",
+ Pointer.fromFunction<
+ PassStruct40BytesHomogeneousDoubleStruct4BytesHomoType>(
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomo, 0.0),
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomoAfterCallback),
+ CallbackTest.withCheck(
+ "PassStructAlignmentInt16",
+ Pointer.fromFunction<PassStructAlignmentInt16Type>(
+ passStructAlignmentInt16, 0),
+ passStructAlignmentInt16AfterCallback),
+ CallbackTest.withCheck(
+ "PassStructAlignmentInt32",
+ Pointer.fromFunction<PassStructAlignmentInt32Type>(
+ passStructAlignmentInt32, 0),
+ passStructAlignmentInt32AfterCallback),
+ CallbackTest.withCheck(
+ "PassStructAlignmentInt64",
+ Pointer.fromFunction<PassStructAlignmentInt64Type>(
+ passStructAlignmentInt64, 0),
+ passStructAlignmentInt64AfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct1ByteInt",
+ Pointer.fromFunction<ReturnStruct1ByteIntType>(returnStruct1ByteInt),
+ returnStruct1ByteIntAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct3BytesInt",
+ Pointer.fromFunction<ReturnStruct3BytesIntType>(returnStruct3BytesInt),
+ returnStruct3BytesIntAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct4BytesHomogeneousInt16",
+ Pointer.fromFunction<ReturnStruct4BytesHomogeneousInt16Type>(
+ returnStruct4BytesHomogeneousInt16),
+ returnStruct4BytesHomogeneousInt16AfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct7BytesInt",
+ Pointer.fromFunction<ReturnStruct7BytesIntType>(returnStruct7BytesInt),
+ returnStruct7BytesIntAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct8BytesInt",
+ Pointer.fromFunction<ReturnStruct8BytesIntType>(returnStruct8BytesInt),
+ returnStruct8BytesIntAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct8BytesHomogeneousFloat",
+ Pointer.fromFunction<ReturnStruct8BytesHomogeneousFloatType>(
+ returnStruct8BytesHomogeneousFloat),
+ returnStruct8BytesHomogeneousFloatAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct8BytesMixed",
+ Pointer.fromFunction<ReturnStruct8BytesMixedType>(
+ returnStruct8BytesMixed),
+ returnStruct8BytesMixedAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct9BytesInt",
+ Pointer.fromFunction<ReturnStruct9BytesIntType>(returnStruct9BytesInt),
+ returnStruct9BytesIntAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct9BytesHomogeneousUint82",
+ Pointer.fromFunction<ReturnStruct9BytesHomogeneousUint82Type>(
+ returnStruct9BytesHomogeneousUint82),
+ returnStruct9BytesHomogeneousUint82AfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct12BytesHomogeneousFloat",
+ Pointer.fromFunction<ReturnStruct12BytesHomogeneousFloatType>(
+ returnStruct12BytesHomogeneousFloat),
+ returnStruct12BytesHomogeneousFloatAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct16BytesHomogeneousFloat",
+ Pointer.fromFunction<ReturnStruct16BytesHomogeneousFloatType>(
+ returnStruct16BytesHomogeneousFloat),
+ returnStruct16BytesHomogeneousFloatAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct16BytesMixed",
+ Pointer.fromFunction<ReturnStruct16BytesMixedType>(
+ returnStruct16BytesMixed),
+ returnStruct16BytesMixedAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct16BytesMixed2",
+ Pointer.fromFunction<ReturnStruct16BytesMixed2Type>(
+ returnStruct16BytesMixed2),
+ returnStruct16BytesMixed2AfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct17BytesInt",
+ Pointer.fromFunction<ReturnStruct17BytesIntType>(returnStruct17BytesInt),
+ returnStruct17BytesIntAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct19BytesHomogeneousUint8",
+ Pointer.fromFunction<ReturnStruct19BytesHomogeneousUint8Type>(
+ returnStruct19BytesHomogeneousUint8),
+ returnStruct19BytesHomogeneousUint8AfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct20BytesHomogeneousInt32",
+ Pointer.fromFunction<ReturnStruct20BytesHomogeneousInt32Type>(
+ returnStruct20BytesHomogeneousInt32),
+ returnStruct20BytesHomogeneousInt32AfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct20BytesHomogeneousFloat",
+ Pointer.fromFunction<ReturnStruct20BytesHomogeneousFloatType>(
+ returnStruct20BytesHomogeneousFloat),
+ returnStruct20BytesHomogeneousFloatAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct32BytesHomogeneousDouble",
+ Pointer.fromFunction<ReturnStruct32BytesHomogeneousDoubleType>(
+ returnStruct32BytesHomogeneousDouble),
+ returnStruct32BytesHomogeneousDoubleAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct40BytesHomogeneousDouble",
+ Pointer.fromFunction<ReturnStruct40BytesHomogeneousDoubleType>(
+ returnStruct40BytesHomogeneousDouble),
+ returnStruct40BytesHomogeneousDoubleAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct1024BytesHomogeneousUint64",
+ Pointer.fromFunction<ReturnStruct1024BytesHomogeneousUint64Type>(
+ returnStruct1024BytesHomogeneousUint64),
+ returnStruct1024BytesHomogeneousUint64AfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStructArgumentStruct1ByteInt",
+ Pointer.fromFunction<ReturnStructArgumentStruct1ByteIntType>(
+ returnStructArgumentStruct1ByteInt),
+ returnStructArgumentStruct1ByteIntAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStructArgumentInt32x8Struct1ByteInt",
+ Pointer.fromFunction<ReturnStructArgumentInt32x8Struct1ByteIntType>(
+ returnStructArgumentInt32x8Struct1ByteInt),
+ returnStructArgumentInt32x8Struct1ByteIntAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStructArgumentStruct8BytesHomogeneousFloat",
+ Pointer.fromFunction<
+ ReturnStructArgumentStruct8BytesHomogeneousFloatType>(
+ returnStructArgumentStruct8BytesHomogeneousFloat),
+ returnStructArgumentStruct8BytesHomogeneousFloatAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStructArgumentStruct20BytesHomogeneousInt32",
+ Pointer.fromFunction<
+ ReturnStructArgumentStruct20BytesHomogeneousInt32Type>(
+ returnStructArgumentStruct20BytesHomogeneousInt32),
+ returnStructArgumentStruct20BytesHomogeneousInt32AfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStructArgumentInt32x8Struct20BytesHomogeneou",
+ Pointer.fromFunction<
+ ReturnStructArgumentInt32x8Struct20BytesHomogeneouType>(
+ returnStructArgumentInt32x8Struct20BytesHomogeneou),
+ returnStructArgumentInt32x8Struct20BytesHomogeneouAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStructAlignmentInt16",
+ Pointer.fromFunction<ReturnStructAlignmentInt16Type>(
+ returnStructAlignmentInt16),
+ returnStructAlignmentInt16AfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStructAlignmentInt32",
+ Pointer.fromFunction<ReturnStructAlignmentInt32Type>(
+ returnStructAlignmentInt32),
+ returnStructAlignmentInt32AfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStructAlignmentInt64",
+ Pointer.fromFunction<ReturnStructAlignmentInt64Type>(
+ returnStructAlignmentInt64),
+ returnStructAlignmentInt64AfterCallback),
+];
+typedef PassStruct1ByteIntx10Type = Int64 Function(
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct1ByteInt passStruct1ByteIntx10_a0 = Struct1ByteInt();
+Struct1ByteInt passStruct1ByteIntx10_a1 = Struct1ByteInt();
+Struct1ByteInt passStruct1ByteIntx10_a2 = Struct1ByteInt();
+Struct1ByteInt passStruct1ByteIntx10_a3 = Struct1ByteInt();
+Struct1ByteInt passStruct1ByteIntx10_a4 = Struct1ByteInt();
+Struct1ByteInt passStruct1ByteIntx10_a5 = Struct1ByteInt();
+Struct1ByteInt passStruct1ByteIntx10_a6 = Struct1ByteInt();
+Struct1ByteInt passStruct1ByteIntx10_a7 = Struct1ByteInt();
+Struct1ByteInt passStruct1ByteIntx10_a8 = Struct1ByteInt();
+Struct1ByteInt passStruct1ByteIntx10_a9 = Struct1ByteInt();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct1ByteIntx10Result = 0;
+
+int passStruct1ByteIntx10CalculateResult() {
+ int result = 0;
+
+ result += passStruct1ByteIntx10_a0.a0;
+ result += passStruct1ByteIntx10_a1.a0;
+ result += passStruct1ByteIntx10_a2.a0;
+ result += passStruct1ByteIntx10_a3.a0;
+ result += passStruct1ByteIntx10_a4.a0;
+ result += passStruct1ByteIntx10_a5.a0;
+ result += passStruct1ByteIntx10_a6.a0;
+ result += passStruct1ByteIntx10_a7.a0;
+ result += passStruct1ByteIntx10_a8.a0;
+ result += passStruct1ByteIntx10_a9.a0;
+
+ passStruct1ByteIntx10Result = result;
+
+ return result;
+}
+
+/// Smallest struct with data.
+/// 10 struct arguments will exhaust available registers.
+int passStruct1ByteIntx10(
+ Struct1ByteInt a0,
+ Struct1ByteInt a1,
+ Struct1ByteInt a2,
+ Struct1ByteInt a3,
+ Struct1ByteInt a4,
+ Struct1ByteInt a5,
+ Struct1ByteInt a6,
+ Struct1ByteInt a7,
+ Struct1ByteInt a8,
+ Struct1ByteInt a9) {
+ print(
+ "passStruct1ByteIntx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct1ByteIntx10 throwing on purpuse!");
+ }
+
+ passStruct1ByteIntx10_a0 = a0;
+ passStruct1ByteIntx10_a1 = a1;
+ passStruct1ByteIntx10_a2 = a2;
+ passStruct1ByteIntx10_a3 = a3;
+ passStruct1ByteIntx10_a4 = a4;
+ passStruct1ByteIntx10_a5 = a5;
+ passStruct1ByteIntx10_a6 = a6;
+ passStruct1ByteIntx10_a7 = a7;
+ passStruct1ByteIntx10_a8 = a8;
+ passStruct1ByteIntx10_a9 = a9;
+
+ final result = passStruct1ByteIntx10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct1ByteIntx10AfterCallback() {
+ final result = passStruct1ByteIntx10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(5, result);
+}
+
+typedef PassStruct3BytesIntx10Type = Int64 Function(
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct3BytesInt passStruct3BytesIntx10_a0 = Struct3BytesInt();
+Struct3BytesInt passStruct3BytesIntx10_a1 = Struct3BytesInt();
+Struct3BytesInt passStruct3BytesIntx10_a2 = Struct3BytesInt();
+Struct3BytesInt passStruct3BytesIntx10_a3 = Struct3BytesInt();
+Struct3BytesInt passStruct3BytesIntx10_a4 = Struct3BytesInt();
+Struct3BytesInt passStruct3BytesIntx10_a5 = Struct3BytesInt();
+Struct3BytesInt passStruct3BytesIntx10_a6 = Struct3BytesInt();
+Struct3BytesInt passStruct3BytesIntx10_a7 = Struct3BytesInt();
+Struct3BytesInt passStruct3BytesIntx10_a8 = Struct3BytesInt();
+Struct3BytesInt passStruct3BytesIntx10_a9 = Struct3BytesInt();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct3BytesIntx10Result = 0;
+
+int passStruct3BytesIntx10CalculateResult() {
+ int result = 0;
+
+ result += passStruct3BytesIntx10_a0.a0;
+ result += passStruct3BytesIntx10_a0.a1;
+ result += passStruct3BytesIntx10_a1.a0;
+ result += passStruct3BytesIntx10_a1.a1;
+ result += passStruct3BytesIntx10_a2.a0;
+ result += passStruct3BytesIntx10_a2.a1;
+ result += passStruct3BytesIntx10_a3.a0;
+ result += passStruct3BytesIntx10_a3.a1;
+ result += passStruct3BytesIntx10_a4.a0;
+ result += passStruct3BytesIntx10_a4.a1;
+ result += passStruct3BytesIntx10_a5.a0;
+ result += passStruct3BytesIntx10_a5.a1;
+ result += passStruct3BytesIntx10_a6.a0;
+ result += passStruct3BytesIntx10_a6.a1;
+ result += passStruct3BytesIntx10_a7.a0;
+ result += passStruct3BytesIntx10_a7.a1;
+ result += passStruct3BytesIntx10_a8.a0;
+ result += passStruct3BytesIntx10_a8.a1;
+ result += passStruct3BytesIntx10_a9.a0;
+ result += passStruct3BytesIntx10_a9.a1;
+
+ passStruct3BytesIntx10Result = result;
+
+ return result;
+}
+
+/// Not a multiple of word size, not a power of two.
+/// 10 struct arguments will exhaust available registers.
+int passStruct3BytesIntx10(
+ Struct3BytesInt a0,
+ Struct3BytesInt a1,
+ Struct3BytesInt a2,
+ Struct3BytesInt a3,
+ Struct3BytesInt a4,
+ Struct3BytesInt a5,
+ Struct3BytesInt a6,
+ Struct3BytesInt a7,
+ Struct3BytesInt a8,
+ Struct3BytesInt a9) {
+ print(
+ "passStruct3BytesIntx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct3BytesIntx10 throwing on purpuse!");
+ }
+
+ passStruct3BytesIntx10_a0 = a0;
+ passStruct3BytesIntx10_a1 = a1;
+ passStruct3BytesIntx10_a2 = a2;
+ passStruct3BytesIntx10_a3 = a3;
+ passStruct3BytesIntx10_a4 = a4;
+ passStruct3BytesIntx10_a5 = a5;
+ passStruct3BytesIntx10_a6 = a6;
+ passStruct3BytesIntx10_a7 = a7;
+ passStruct3BytesIntx10_a8 = a8;
+ passStruct3BytesIntx10_a9 = a9;
+
+ final result = passStruct3BytesIntx10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct3BytesIntx10AfterCallback() {
+ final result = passStruct3BytesIntx10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(10, result);
+}
+
+typedef PassStruct4BytesHomogeneousInt16x10Type = Int64 Function(
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16);
+
+// Global variables to be able to test inputs after callback returned.
+Struct4BytesHomogeneousInt16 passStruct4BytesHomogeneousInt16x10_a0 =
+ Struct4BytesHomogeneousInt16();
+Struct4BytesHomogeneousInt16 passStruct4BytesHomogeneousInt16x10_a1 =
+ Struct4BytesHomogeneousInt16();
+Struct4BytesHomogeneousInt16 passStruct4BytesHomogeneousInt16x10_a2 =
+ Struct4BytesHomogeneousInt16();
+Struct4BytesHomogeneousInt16 passStruct4BytesHomogeneousInt16x10_a3 =
+ Struct4BytesHomogeneousInt16();
+Struct4BytesHomogeneousInt16 passStruct4BytesHomogeneousInt16x10_a4 =
+ Struct4BytesHomogeneousInt16();
+Struct4BytesHomogeneousInt16 passStruct4BytesHomogeneousInt16x10_a5 =
+ Struct4BytesHomogeneousInt16();
+Struct4BytesHomogeneousInt16 passStruct4BytesHomogeneousInt16x10_a6 =
+ Struct4BytesHomogeneousInt16();
+Struct4BytesHomogeneousInt16 passStruct4BytesHomogeneousInt16x10_a7 =
+ Struct4BytesHomogeneousInt16();
+Struct4BytesHomogeneousInt16 passStruct4BytesHomogeneousInt16x10_a8 =
+ Struct4BytesHomogeneousInt16();
+Struct4BytesHomogeneousInt16 passStruct4BytesHomogeneousInt16x10_a9 =
+ Struct4BytesHomogeneousInt16();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct4BytesHomogeneousInt16x10Result = 0;
+
+int passStruct4BytesHomogeneousInt16x10CalculateResult() {
+ int result = 0;
+
+ result += passStruct4BytesHomogeneousInt16x10_a0.a0;
+ result += passStruct4BytesHomogeneousInt16x10_a0.a1;
+ result += passStruct4BytesHomogeneousInt16x10_a1.a0;
+ result += passStruct4BytesHomogeneousInt16x10_a1.a1;
+ result += passStruct4BytesHomogeneousInt16x10_a2.a0;
+ result += passStruct4BytesHomogeneousInt16x10_a2.a1;
+ result += passStruct4BytesHomogeneousInt16x10_a3.a0;
+ result += passStruct4BytesHomogeneousInt16x10_a3.a1;
+ result += passStruct4BytesHomogeneousInt16x10_a4.a0;
+ result += passStruct4BytesHomogeneousInt16x10_a4.a1;
+ result += passStruct4BytesHomogeneousInt16x10_a5.a0;
+ result += passStruct4BytesHomogeneousInt16x10_a5.a1;
+ result += passStruct4BytesHomogeneousInt16x10_a6.a0;
+ result += passStruct4BytesHomogeneousInt16x10_a6.a1;
+ result += passStruct4BytesHomogeneousInt16x10_a7.a0;
+ result += passStruct4BytesHomogeneousInt16x10_a7.a1;
+ result += passStruct4BytesHomogeneousInt16x10_a8.a0;
+ result += passStruct4BytesHomogeneousInt16x10_a8.a1;
+ result += passStruct4BytesHomogeneousInt16x10_a9.a0;
+ result += passStruct4BytesHomogeneousInt16x10_a9.a1;
+
+ passStruct4BytesHomogeneousInt16x10Result = result;
+
+ return result;
+}
+
+/// Exactly word size on 32-bit architectures.
+/// 10 struct arguments will exhaust available registers.
+int passStruct4BytesHomogeneousInt16x10(
+ Struct4BytesHomogeneousInt16 a0,
+ Struct4BytesHomogeneousInt16 a1,
+ Struct4BytesHomogeneousInt16 a2,
+ Struct4BytesHomogeneousInt16 a3,
+ Struct4BytesHomogeneousInt16 a4,
+ Struct4BytesHomogeneousInt16 a5,
+ Struct4BytesHomogeneousInt16 a6,
+ Struct4BytesHomogeneousInt16 a7,
+ Struct4BytesHomogeneousInt16 a8,
+ Struct4BytesHomogeneousInt16 a9) {
+ print(
+ "passStruct4BytesHomogeneousInt16x10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct4BytesHomogeneousInt16x10 throwing on purpuse!");
+ }
+
+ passStruct4BytesHomogeneousInt16x10_a0 = a0;
+ passStruct4BytesHomogeneousInt16x10_a1 = a1;
+ passStruct4BytesHomogeneousInt16x10_a2 = a2;
+ passStruct4BytesHomogeneousInt16x10_a3 = a3;
+ passStruct4BytesHomogeneousInt16x10_a4 = a4;
+ passStruct4BytesHomogeneousInt16x10_a5 = a5;
+ passStruct4BytesHomogeneousInt16x10_a6 = a6;
+ passStruct4BytesHomogeneousInt16x10_a7 = a7;
+ passStruct4BytesHomogeneousInt16x10_a8 = a8;
+ passStruct4BytesHomogeneousInt16x10_a9 = a9;
+
+ final result = passStruct4BytesHomogeneousInt16x10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct4BytesHomogeneousInt16x10AfterCallback() {
+ final result = passStruct4BytesHomogeneousInt16x10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(10, result);
+}
+
+typedef PassStruct7BytesIntx10Type = Int64 Function(
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct7BytesInt passStruct7BytesIntx10_a0 = Struct7BytesInt();
+Struct7BytesInt passStruct7BytesIntx10_a1 = Struct7BytesInt();
+Struct7BytesInt passStruct7BytesIntx10_a2 = Struct7BytesInt();
+Struct7BytesInt passStruct7BytesIntx10_a3 = Struct7BytesInt();
+Struct7BytesInt passStruct7BytesIntx10_a4 = Struct7BytesInt();
+Struct7BytesInt passStruct7BytesIntx10_a5 = Struct7BytesInt();
+Struct7BytesInt passStruct7BytesIntx10_a6 = Struct7BytesInt();
+Struct7BytesInt passStruct7BytesIntx10_a7 = Struct7BytesInt();
+Struct7BytesInt passStruct7BytesIntx10_a8 = Struct7BytesInt();
+Struct7BytesInt passStruct7BytesIntx10_a9 = Struct7BytesInt();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct7BytesIntx10Result = 0;
+
+int passStruct7BytesIntx10CalculateResult() {
+ int result = 0;
+
+ result += passStruct7BytesIntx10_a0.a0;
+ result += passStruct7BytesIntx10_a0.a1;
+ result += passStruct7BytesIntx10_a0.a2;
+ result += passStruct7BytesIntx10_a1.a0;
+ result += passStruct7BytesIntx10_a1.a1;
+ result += passStruct7BytesIntx10_a1.a2;
+ result += passStruct7BytesIntx10_a2.a0;
+ result += passStruct7BytesIntx10_a2.a1;
+ result += passStruct7BytesIntx10_a2.a2;
+ result += passStruct7BytesIntx10_a3.a0;
+ result += passStruct7BytesIntx10_a3.a1;
+ result += passStruct7BytesIntx10_a3.a2;
+ result += passStruct7BytesIntx10_a4.a0;
+ result += passStruct7BytesIntx10_a4.a1;
+ result += passStruct7BytesIntx10_a4.a2;
+ result += passStruct7BytesIntx10_a5.a0;
+ result += passStruct7BytesIntx10_a5.a1;
+ result += passStruct7BytesIntx10_a5.a2;
+ result += passStruct7BytesIntx10_a6.a0;
+ result += passStruct7BytesIntx10_a6.a1;
+ result += passStruct7BytesIntx10_a6.a2;
+ result += passStruct7BytesIntx10_a7.a0;
+ result += passStruct7BytesIntx10_a7.a1;
+ result += passStruct7BytesIntx10_a7.a2;
+ result += passStruct7BytesIntx10_a8.a0;
+ result += passStruct7BytesIntx10_a8.a1;
+ result += passStruct7BytesIntx10_a8.a2;
+ result += passStruct7BytesIntx10_a9.a0;
+ result += passStruct7BytesIntx10_a9.a1;
+ result += passStruct7BytesIntx10_a9.a2;
+
+ passStruct7BytesIntx10Result = result;
+
+ return result;
+}
+
+/// Sub word size on 64 bit architectures.
+/// 10 struct arguments will exhaust available registers.
+int passStruct7BytesIntx10(
+ Struct7BytesInt a0,
+ Struct7BytesInt a1,
+ Struct7BytesInt a2,
+ Struct7BytesInt a3,
+ Struct7BytesInt a4,
+ Struct7BytesInt a5,
+ Struct7BytesInt a6,
+ Struct7BytesInt a7,
+ Struct7BytesInt a8,
+ Struct7BytesInt a9) {
+ print(
+ "passStruct7BytesIntx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct7BytesIntx10 throwing on purpuse!");
+ }
+
+ passStruct7BytesIntx10_a0 = a0;
+ passStruct7BytesIntx10_a1 = a1;
+ passStruct7BytesIntx10_a2 = a2;
+ passStruct7BytesIntx10_a3 = a3;
+ passStruct7BytesIntx10_a4 = a4;
+ passStruct7BytesIntx10_a5 = a5;
+ passStruct7BytesIntx10_a6 = a6;
+ passStruct7BytesIntx10_a7 = a7;
+ passStruct7BytesIntx10_a8 = a8;
+ passStruct7BytesIntx10_a9 = a9;
+
+ final result = passStruct7BytesIntx10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct7BytesIntx10AfterCallback() {
+ final result = passStruct7BytesIntx10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(15, result);
+}
+
+typedef PassStruct8BytesIntx10Type = Int64 Function(
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct8BytesInt passStruct8BytesIntx10_a0 = Struct8BytesInt();
+Struct8BytesInt passStruct8BytesIntx10_a1 = Struct8BytesInt();
+Struct8BytesInt passStruct8BytesIntx10_a2 = Struct8BytesInt();
+Struct8BytesInt passStruct8BytesIntx10_a3 = Struct8BytesInt();
+Struct8BytesInt passStruct8BytesIntx10_a4 = Struct8BytesInt();
+Struct8BytesInt passStruct8BytesIntx10_a5 = Struct8BytesInt();
+Struct8BytesInt passStruct8BytesIntx10_a6 = Struct8BytesInt();
+Struct8BytesInt passStruct8BytesIntx10_a7 = Struct8BytesInt();
+Struct8BytesInt passStruct8BytesIntx10_a8 = Struct8BytesInt();
+Struct8BytesInt passStruct8BytesIntx10_a9 = Struct8BytesInt();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct8BytesIntx10Result = 0;
+
+int passStruct8BytesIntx10CalculateResult() {
+ int result = 0;
+
+ result += passStruct8BytesIntx10_a0.a0;
+ result += passStruct8BytesIntx10_a0.a1;
+ result += passStruct8BytesIntx10_a0.a2;
+ result += passStruct8BytesIntx10_a1.a0;
+ result += passStruct8BytesIntx10_a1.a1;
+ result += passStruct8BytesIntx10_a1.a2;
+ result += passStruct8BytesIntx10_a2.a0;
+ result += passStruct8BytesIntx10_a2.a1;
+ result += passStruct8BytesIntx10_a2.a2;
+ result += passStruct8BytesIntx10_a3.a0;
+ result += passStruct8BytesIntx10_a3.a1;
+ result += passStruct8BytesIntx10_a3.a2;
+ result += passStruct8BytesIntx10_a4.a0;
+ result += passStruct8BytesIntx10_a4.a1;
+ result += passStruct8BytesIntx10_a4.a2;
+ result += passStruct8BytesIntx10_a5.a0;
+ result += passStruct8BytesIntx10_a5.a1;
+ result += passStruct8BytesIntx10_a5.a2;
+ result += passStruct8BytesIntx10_a6.a0;
+ result += passStruct8BytesIntx10_a6.a1;
+ result += passStruct8BytesIntx10_a6.a2;
+ result += passStruct8BytesIntx10_a7.a0;
+ result += passStruct8BytesIntx10_a7.a1;
+ result += passStruct8BytesIntx10_a7.a2;
+ result += passStruct8BytesIntx10_a8.a0;
+ result += passStruct8BytesIntx10_a8.a1;
+ result += passStruct8BytesIntx10_a8.a2;
+ result += passStruct8BytesIntx10_a9.a0;
+ result += passStruct8BytesIntx10_a9.a1;
+ result += passStruct8BytesIntx10_a9.a2;
+
+ passStruct8BytesIntx10Result = result;
+
+ return result;
+}
+
+/// Exactly word size struct on 64bit architectures.
+/// 10 struct arguments will exhaust available registers.
+int passStruct8BytesIntx10(
+ Struct8BytesInt a0,
+ Struct8BytesInt a1,
+ Struct8BytesInt a2,
+ Struct8BytesInt a3,
+ Struct8BytesInt a4,
+ Struct8BytesInt a5,
+ Struct8BytesInt a6,
+ Struct8BytesInt a7,
+ Struct8BytesInt a8,
+ Struct8BytesInt a9) {
+ print(
+ "passStruct8BytesIntx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct8BytesIntx10 throwing on purpuse!");
+ }
+
+ passStruct8BytesIntx10_a0 = a0;
+ passStruct8BytesIntx10_a1 = a1;
+ passStruct8BytesIntx10_a2 = a2;
+ passStruct8BytesIntx10_a3 = a3;
+ passStruct8BytesIntx10_a4 = a4;
+ passStruct8BytesIntx10_a5 = a5;
+ passStruct8BytesIntx10_a6 = a6;
+ passStruct8BytesIntx10_a7 = a7;
+ passStruct8BytesIntx10_a8 = a8;
+ passStruct8BytesIntx10_a9 = a9;
+
+ final result = passStruct8BytesIntx10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct8BytesIntx10AfterCallback() {
+ final result = passStruct8BytesIntx10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(15, result);
+}
+
+typedef PassStruct8BytesHomogeneousFloatx10Type = Float Function(
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat);
+
+// Global variables to be able to test inputs after callback returned.
+Struct8BytesHomogeneousFloat passStruct8BytesHomogeneousFloatx10_a0 =
+ Struct8BytesHomogeneousFloat();
+Struct8BytesHomogeneousFloat passStruct8BytesHomogeneousFloatx10_a1 =
+ Struct8BytesHomogeneousFloat();
+Struct8BytesHomogeneousFloat passStruct8BytesHomogeneousFloatx10_a2 =
+ Struct8BytesHomogeneousFloat();
+Struct8BytesHomogeneousFloat passStruct8BytesHomogeneousFloatx10_a3 =
+ Struct8BytesHomogeneousFloat();
+Struct8BytesHomogeneousFloat passStruct8BytesHomogeneousFloatx10_a4 =
+ Struct8BytesHomogeneousFloat();
+Struct8BytesHomogeneousFloat passStruct8BytesHomogeneousFloatx10_a5 =
+ Struct8BytesHomogeneousFloat();
+Struct8BytesHomogeneousFloat passStruct8BytesHomogeneousFloatx10_a6 =
+ Struct8BytesHomogeneousFloat();
+Struct8BytesHomogeneousFloat passStruct8BytesHomogeneousFloatx10_a7 =
+ Struct8BytesHomogeneousFloat();
+Struct8BytesHomogeneousFloat passStruct8BytesHomogeneousFloatx10_a8 =
+ Struct8BytesHomogeneousFloat();
+Struct8BytesHomogeneousFloat passStruct8BytesHomogeneousFloatx10_a9 =
+ Struct8BytesHomogeneousFloat();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct8BytesHomogeneousFloatx10Result = 0.0;
+
+double passStruct8BytesHomogeneousFloatx10CalculateResult() {
+ double result = 0;
+
+ result += passStruct8BytesHomogeneousFloatx10_a0.a0;
+ result += passStruct8BytesHomogeneousFloatx10_a0.a1;
+ result += passStruct8BytesHomogeneousFloatx10_a1.a0;
+ result += passStruct8BytesHomogeneousFloatx10_a1.a1;
+ result += passStruct8BytesHomogeneousFloatx10_a2.a0;
+ result += passStruct8BytesHomogeneousFloatx10_a2.a1;
+ result += passStruct8BytesHomogeneousFloatx10_a3.a0;
+ result += passStruct8BytesHomogeneousFloatx10_a3.a1;
+ result += passStruct8BytesHomogeneousFloatx10_a4.a0;
+ result += passStruct8BytesHomogeneousFloatx10_a4.a1;
+ result += passStruct8BytesHomogeneousFloatx10_a5.a0;
+ result += passStruct8BytesHomogeneousFloatx10_a5.a1;
+ result += passStruct8BytesHomogeneousFloatx10_a6.a0;
+ result += passStruct8BytesHomogeneousFloatx10_a6.a1;
+ result += passStruct8BytesHomogeneousFloatx10_a7.a0;
+ result += passStruct8BytesHomogeneousFloatx10_a7.a1;
+ result += passStruct8BytesHomogeneousFloatx10_a8.a0;
+ result += passStruct8BytesHomogeneousFloatx10_a8.a1;
+ result += passStruct8BytesHomogeneousFloatx10_a9.a0;
+ result += passStruct8BytesHomogeneousFloatx10_a9.a1;
+
+ passStruct8BytesHomogeneousFloatx10Result = result;
+
+ return result;
+}
+
+/// Arguments passed in FP registers as long as they fit.
+/// 10 struct arguments will exhaust available registers.
+double passStruct8BytesHomogeneousFloatx10(
+ Struct8BytesHomogeneousFloat a0,
+ Struct8BytesHomogeneousFloat a1,
+ Struct8BytesHomogeneousFloat a2,
+ Struct8BytesHomogeneousFloat a3,
+ Struct8BytesHomogeneousFloat a4,
+ Struct8BytesHomogeneousFloat a5,
+ Struct8BytesHomogeneousFloat a6,
+ Struct8BytesHomogeneousFloat a7,
+ Struct8BytesHomogeneousFloat a8,
+ Struct8BytesHomogeneousFloat a9) {
+ print(
+ "passStruct8BytesHomogeneousFloatx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct8BytesHomogeneousFloatx10 throwing on purpuse!");
+ }
+
+ passStruct8BytesHomogeneousFloatx10_a0 = a0;
+ passStruct8BytesHomogeneousFloatx10_a1 = a1;
+ passStruct8BytesHomogeneousFloatx10_a2 = a2;
+ passStruct8BytesHomogeneousFloatx10_a3 = a3;
+ passStruct8BytesHomogeneousFloatx10_a4 = a4;
+ passStruct8BytesHomogeneousFloatx10_a5 = a5;
+ passStruct8BytesHomogeneousFloatx10_a6 = a6;
+ passStruct8BytesHomogeneousFloatx10_a7 = a7;
+ passStruct8BytesHomogeneousFloatx10_a8 = a8;
+ passStruct8BytesHomogeneousFloatx10_a9 = a9;
+
+ final result = passStruct8BytesHomogeneousFloatx10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct8BytesHomogeneousFloatx10AfterCallback() {
+ final result = passStruct8BytesHomogeneousFloatx10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(10.0, result);
+}
+
+typedef PassStruct8BytesMixedx10Type = Float Function(
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed);
+
+// Global variables to be able to test inputs after callback returned.
+Struct8BytesMixed passStruct8BytesMixedx10_a0 = Struct8BytesMixed();
+Struct8BytesMixed passStruct8BytesMixedx10_a1 = Struct8BytesMixed();
+Struct8BytesMixed passStruct8BytesMixedx10_a2 = Struct8BytesMixed();
+Struct8BytesMixed passStruct8BytesMixedx10_a3 = Struct8BytesMixed();
+Struct8BytesMixed passStruct8BytesMixedx10_a4 = Struct8BytesMixed();
+Struct8BytesMixed passStruct8BytesMixedx10_a5 = Struct8BytesMixed();
+Struct8BytesMixed passStruct8BytesMixedx10_a6 = Struct8BytesMixed();
+Struct8BytesMixed passStruct8BytesMixedx10_a7 = Struct8BytesMixed();
+Struct8BytesMixed passStruct8BytesMixedx10_a8 = Struct8BytesMixed();
+Struct8BytesMixed passStruct8BytesMixedx10_a9 = Struct8BytesMixed();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct8BytesMixedx10Result = 0.0;
+
+double passStruct8BytesMixedx10CalculateResult() {
+ double result = 0;
+
+ result += passStruct8BytesMixedx10_a0.a0;
+ result += passStruct8BytesMixedx10_a0.a1;
+ result += passStruct8BytesMixedx10_a0.a2;
+ result += passStruct8BytesMixedx10_a1.a0;
+ result += passStruct8BytesMixedx10_a1.a1;
+ result += passStruct8BytesMixedx10_a1.a2;
+ result += passStruct8BytesMixedx10_a2.a0;
+ result += passStruct8BytesMixedx10_a2.a1;
+ result += passStruct8BytesMixedx10_a2.a2;
+ result += passStruct8BytesMixedx10_a3.a0;
+ result += passStruct8BytesMixedx10_a3.a1;
+ result += passStruct8BytesMixedx10_a3.a2;
+ result += passStruct8BytesMixedx10_a4.a0;
+ result += passStruct8BytesMixedx10_a4.a1;
+ result += passStruct8BytesMixedx10_a4.a2;
+ result += passStruct8BytesMixedx10_a5.a0;
+ result += passStruct8BytesMixedx10_a5.a1;
+ result += passStruct8BytesMixedx10_a5.a2;
+ result += passStruct8BytesMixedx10_a6.a0;
+ result += passStruct8BytesMixedx10_a6.a1;
+ result += passStruct8BytesMixedx10_a6.a2;
+ result += passStruct8BytesMixedx10_a7.a0;
+ result += passStruct8BytesMixedx10_a7.a1;
+ result += passStruct8BytesMixedx10_a7.a2;
+ result += passStruct8BytesMixedx10_a8.a0;
+ result += passStruct8BytesMixedx10_a8.a1;
+ result += passStruct8BytesMixedx10_a8.a2;
+ result += passStruct8BytesMixedx10_a9.a0;
+ result += passStruct8BytesMixedx10_a9.a1;
+ result += passStruct8BytesMixedx10_a9.a2;
+
+ passStruct8BytesMixedx10Result = result;
+
+ return result;
+}
+
+/// On x64, arguments go in int registers because it is not only float.
+/// 10 struct arguments will exhaust available registers.
+double passStruct8BytesMixedx10(
+ Struct8BytesMixed a0,
+ Struct8BytesMixed a1,
+ Struct8BytesMixed a2,
+ Struct8BytesMixed a3,
+ Struct8BytesMixed a4,
+ Struct8BytesMixed a5,
+ Struct8BytesMixed a6,
+ Struct8BytesMixed a7,
+ Struct8BytesMixed a8,
+ Struct8BytesMixed a9) {
+ print(
+ "passStruct8BytesMixedx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct8BytesMixedx10 throwing on purpuse!");
+ }
+
+ passStruct8BytesMixedx10_a0 = a0;
+ passStruct8BytesMixedx10_a1 = a1;
+ passStruct8BytesMixedx10_a2 = a2;
+ passStruct8BytesMixedx10_a3 = a3;
+ passStruct8BytesMixedx10_a4 = a4;
+ passStruct8BytesMixedx10_a5 = a5;
+ passStruct8BytesMixedx10_a6 = a6;
+ passStruct8BytesMixedx10_a7 = a7;
+ passStruct8BytesMixedx10_a8 = a8;
+ passStruct8BytesMixedx10_a9 = a9;
+
+ final result = passStruct8BytesMixedx10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct8BytesMixedx10AfterCallback() {
+ final result = passStruct8BytesMixedx10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(15.0, result);
+}
+
+typedef PassStruct9BytesIntx10Type = Int64 Function(
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct9BytesInt passStruct9BytesIntx10_a0 = Struct9BytesInt();
+Struct9BytesInt passStruct9BytesIntx10_a1 = Struct9BytesInt();
+Struct9BytesInt passStruct9BytesIntx10_a2 = Struct9BytesInt();
+Struct9BytesInt passStruct9BytesIntx10_a3 = Struct9BytesInt();
+Struct9BytesInt passStruct9BytesIntx10_a4 = Struct9BytesInt();
+Struct9BytesInt passStruct9BytesIntx10_a5 = Struct9BytesInt();
+Struct9BytesInt passStruct9BytesIntx10_a6 = Struct9BytesInt();
+Struct9BytesInt passStruct9BytesIntx10_a7 = Struct9BytesInt();
+Struct9BytesInt passStruct9BytesIntx10_a8 = Struct9BytesInt();
+Struct9BytesInt passStruct9BytesIntx10_a9 = Struct9BytesInt();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct9BytesIntx10Result = 0;
+
+int passStruct9BytesIntx10CalculateResult() {
+ int result = 0;
+
+ result += passStruct9BytesIntx10_a0.a0;
+ result += passStruct9BytesIntx10_a0.a1;
+ result += passStruct9BytesIntx10_a1.a0;
+ result += passStruct9BytesIntx10_a1.a1;
+ result += passStruct9BytesIntx10_a2.a0;
+ result += passStruct9BytesIntx10_a2.a1;
+ result += passStruct9BytesIntx10_a3.a0;
+ result += passStruct9BytesIntx10_a3.a1;
+ result += passStruct9BytesIntx10_a4.a0;
+ result += passStruct9BytesIntx10_a4.a1;
+ result += passStruct9BytesIntx10_a5.a0;
+ result += passStruct9BytesIntx10_a5.a1;
+ result += passStruct9BytesIntx10_a6.a0;
+ result += passStruct9BytesIntx10_a6.a1;
+ result += passStruct9BytesIntx10_a7.a0;
+ result += passStruct9BytesIntx10_a7.a1;
+ result += passStruct9BytesIntx10_a8.a0;
+ result += passStruct9BytesIntx10_a8.a1;
+ result += passStruct9BytesIntx10_a9.a0;
+ result += passStruct9BytesIntx10_a9.a1;
+
+ passStruct9BytesIntx10Result = result;
+
+ return result;
+}
+
+/// Argument is a single byte over a multiple of word size.
+/// 10 struct arguments will exhaust available registers.
+/// Tests upper bytes in the integer registers that are partly filled.
+/// Tests stack alignment of non word size stack arguments.
+int passStruct9BytesIntx10(
+ Struct9BytesInt a0,
+ Struct9BytesInt a1,
+ Struct9BytesInt a2,
+ Struct9BytesInt a3,
+ Struct9BytesInt a4,
+ Struct9BytesInt a5,
+ Struct9BytesInt a6,
+ Struct9BytesInt a7,
+ Struct9BytesInt a8,
+ Struct9BytesInt a9) {
+ print(
+ "passStruct9BytesIntx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct9BytesIntx10 throwing on purpuse!");
+ }
+
+ passStruct9BytesIntx10_a0 = a0;
+ passStruct9BytesIntx10_a1 = a1;
+ passStruct9BytesIntx10_a2 = a2;
+ passStruct9BytesIntx10_a3 = a3;
+ passStruct9BytesIntx10_a4 = a4;
+ passStruct9BytesIntx10_a5 = a5;
+ passStruct9BytesIntx10_a6 = a6;
+ passStruct9BytesIntx10_a7 = a7;
+ passStruct9BytesIntx10_a8 = a8;
+ passStruct9BytesIntx10_a9 = a9;
+
+ final result = passStruct9BytesIntx10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct9BytesIntx10AfterCallback() {
+ final result = passStruct9BytesIntx10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(10, result);
+}
+
+typedef PassStruct9BytesHomogeneousUint82x10Type = Int64 Function(
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82);
+
+// Global variables to be able to test inputs after callback returned.
+Struct9BytesHomogeneousUint82 passStruct9BytesHomogeneousUint82x10_a0 =
+ Struct9BytesHomogeneousUint82();
+Struct9BytesHomogeneousUint82 passStruct9BytesHomogeneousUint82x10_a1 =
+ Struct9BytesHomogeneousUint82();
+Struct9BytesHomogeneousUint82 passStruct9BytesHomogeneousUint82x10_a2 =
+ Struct9BytesHomogeneousUint82();
+Struct9BytesHomogeneousUint82 passStruct9BytesHomogeneousUint82x10_a3 =
+ Struct9BytesHomogeneousUint82();
+Struct9BytesHomogeneousUint82 passStruct9BytesHomogeneousUint82x10_a4 =
+ Struct9BytesHomogeneousUint82();
+Struct9BytesHomogeneousUint82 passStruct9BytesHomogeneousUint82x10_a5 =
+ Struct9BytesHomogeneousUint82();
+Struct9BytesHomogeneousUint82 passStruct9BytesHomogeneousUint82x10_a6 =
+ Struct9BytesHomogeneousUint82();
+Struct9BytesHomogeneousUint82 passStruct9BytesHomogeneousUint82x10_a7 =
+ Struct9BytesHomogeneousUint82();
+Struct9BytesHomogeneousUint82 passStruct9BytesHomogeneousUint82x10_a8 =
+ Struct9BytesHomogeneousUint82();
+Struct9BytesHomogeneousUint82 passStruct9BytesHomogeneousUint82x10_a9 =
+ Struct9BytesHomogeneousUint82();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct9BytesHomogeneousUint82x10Result = 0;
+
+int passStruct9BytesHomogeneousUint82x10CalculateResult() {
+ int result = 0;
+
+ result += passStruct9BytesHomogeneousUint82x10_a0.a0;
+ result += passStruct9BytesHomogeneousUint82x10_a0.a1;
+ result += passStruct9BytesHomogeneousUint82x10_a0.a2;
+ result += passStruct9BytesHomogeneousUint82x10_a0.a3;
+ result += passStruct9BytesHomogeneousUint82x10_a0.a4;
+ result += passStruct9BytesHomogeneousUint82x10_a0.a5;
+ result += passStruct9BytesHomogeneousUint82x10_a0.a6;
+ result += passStruct9BytesHomogeneousUint82x10_a0.a7;
+ result += passStruct9BytesHomogeneousUint82x10_a0.a8;
+ result += passStruct9BytesHomogeneousUint82x10_a1.a0;
+ result += passStruct9BytesHomogeneousUint82x10_a1.a1;
+ result += passStruct9BytesHomogeneousUint82x10_a1.a2;
+ result += passStruct9BytesHomogeneousUint82x10_a1.a3;
+ result += passStruct9BytesHomogeneousUint82x10_a1.a4;
+ result += passStruct9BytesHomogeneousUint82x10_a1.a5;
+ result += passStruct9BytesHomogeneousUint82x10_a1.a6;
+ result += passStruct9BytesHomogeneousUint82x10_a1.a7;
+ result += passStruct9BytesHomogeneousUint82x10_a1.a8;
+ result += passStruct9BytesHomogeneousUint82x10_a2.a0;
+ result += passStruct9BytesHomogeneousUint82x10_a2.a1;
+ result += passStruct9BytesHomogeneousUint82x10_a2.a2;
+ result += passStruct9BytesHomogeneousUint82x10_a2.a3;
+ result += passStruct9BytesHomogeneousUint82x10_a2.a4;
+ result += passStruct9BytesHomogeneousUint82x10_a2.a5;
+ result += passStruct9BytesHomogeneousUint82x10_a2.a6;
+ result += passStruct9BytesHomogeneousUint82x10_a2.a7;
+ result += passStruct9BytesHomogeneousUint82x10_a2.a8;
+ result += passStruct9BytesHomogeneousUint82x10_a3.a0;
+ result += passStruct9BytesHomogeneousUint82x10_a3.a1;
+ result += passStruct9BytesHomogeneousUint82x10_a3.a2;
+ result += passStruct9BytesHomogeneousUint82x10_a3.a3;
+ result += passStruct9BytesHomogeneousUint82x10_a3.a4;
+ result += passStruct9BytesHomogeneousUint82x10_a3.a5;
+ result += passStruct9BytesHomogeneousUint82x10_a3.a6;
+ result += passStruct9BytesHomogeneousUint82x10_a3.a7;
+ result += passStruct9BytesHomogeneousUint82x10_a3.a8;
+ result += passStruct9BytesHomogeneousUint82x10_a4.a0;
+ result += passStruct9BytesHomogeneousUint82x10_a4.a1;
+ result += passStruct9BytesHomogeneousUint82x10_a4.a2;
+ result += passStruct9BytesHomogeneousUint82x10_a4.a3;
+ result += passStruct9BytesHomogeneousUint82x10_a4.a4;
+ result += passStruct9BytesHomogeneousUint82x10_a4.a5;
+ result += passStruct9BytesHomogeneousUint82x10_a4.a6;
+ result += passStruct9BytesHomogeneousUint82x10_a4.a7;
+ result += passStruct9BytesHomogeneousUint82x10_a4.a8;
+ result += passStruct9BytesHomogeneousUint82x10_a5.a0;
+ result += passStruct9BytesHomogeneousUint82x10_a5.a1;
+ result += passStruct9BytesHomogeneousUint82x10_a5.a2;
+ result += passStruct9BytesHomogeneousUint82x10_a5.a3;
+ result += passStruct9BytesHomogeneousUint82x10_a5.a4;
+ result += passStruct9BytesHomogeneousUint82x10_a5.a5;
+ result += passStruct9BytesHomogeneousUint82x10_a5.a6;
+ result += passStruct9BytesHomogeneousUint82x10_a5.a7;
+ result += passStruct9BytesHomogeneousUint82x10_a5.a8;
+ result += passStruct9BytesHomogeneousUint82x10_a6.a0;
+ result += passStruct9BytesHomogeneousUint82x10_a6.a1;
+ result += passStruct9BytesHomogeneousUint82x10_a6.a2;
+ result += passStruct9BytesHomogeneousUint82x10_a6.a3;
+ result += passStruct9BytesHomogeneousUint82x10_a6.a4;
+ result += passStruct9BytesHomogeneousUint82x10_a6.a5;
+ result += passStruct9BytesHomogeneousUint82x10_a6.a6;
+ result += passStruct9BytesHomogeneousUint82x10_a6.a7;
+ result += passStruct9BytesHomogeneousUint82x10_a6.a8;
+ result += passStruct9BytesHomogeneousUint82x10_a7.a0;
+ result += passStruct9BytesHomogeneousUint82x10_a7.a1;
+ result += passStruct9BytesHomogeneousUint82x10_a7.a2;
+ result += passStruct9BytesHomogeneousUint82x10_a7.a3;
+ result += passStruct9BytesHomogeneousUint82x10_a7.a4;
+ result += passStruct9BytesHomogeneousUint82x10_a7.a5;
+ result += passStruct9BytesHomogeneousUint82x10_a7.a6;
+ result += passStruct9BytesHomogeneousUint82x10_a7.a7;
+ result += passStruct9BytesHomogeneousUint82x10_a7.a8;
+ result += passStruct9BytesHomogeneousUint82x10_a8.a0;
+ result += passStruct9BytesHomogeneousUint82x10_a8.a1;
+ result += passStruct9BytesHomogeneousUint82x10_a8.a2;
+ result += passStruct9BytesHomogeneousUint82x10_a8.a3;
+ result += passStruct9BytesHomogeneousUint82x10_a8.a4;
+ result += passStruct9BytesHomogeneousUint82x10_a8.a5;
+ result += passStruct9BytesHomogeneousUint82x10_a8.a6;
+ result += passStruct9BytesHomogeneousUint82x10_a8.a7;
+ result += passStruct9BytesHomogeneousUint82x10_a8.a8;
+ result += passStruct9BytesHomogeneousUint82x10_a9.a0;
+ result += passStruct9BytesHomogeneousUint82x10_a9.a1;
+ result += passStruct9BytesHomogeneousUint82x10_a9.a2;
+ result += passStruct9BytesHomogeneousUint82x10_a9.a3;
+ result += passStruct9BytesHomogeneousUint82x10_a9.a4;
+ result += passStruct9BytesHomogeneousUint82x10_a9.a5;
+ result += passStruct9BytesHomogeneousUint82x10_a9.a6;
+ result += passStruct9BytesHomogeneousUint82x10_a9.a7;
+ result += passStruct9BytesHomogeneousUint82x10_a9.a8;
+
+ passStruct9BytesHomogeneousUint82x10Result = result;
+
+ return result;
+}
+
+/// Argument is a single byte over a multiple of word size.
+/// 10 struct arguments will exhaust available registers.
+/// Struct only has 1-byte aligned fields to test struct alignment itself.
+///
+int passStruct9BytesHomogeneousUint82x10(
+ Struct9BytesHomogeneousUint82 a0,
+ Struct9BytesHomogeneousUint82 a1,
+ Struct9BytesHomogeneousUint82 a2,
+ Struct9BytesHomogeneousUint82 a3,
+ Struct9BytesHomogeneousUint82 a4,
+ Struct9BytesHomogeneousUint82 a5,
+ Struct9BytesHomogeneousUint82 a6,
+ Struct9BytesHomogeneousUint82 a7,
+ Struct9BytesHomogeneousUint82 a8,
+ Struct9BytesHomogeneousUint82 a9) {
+ print(
+ "passStruct9BytesHomogeneousUint82x10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassStruct9BytesHomogeneousUint82x10 throwing on purpuse!");
+ }
+
+ passStruct9BytesHomogeneousUint82x10_a0 = a0;
+ passStruct9BytesHomogeneousUint82x10_a1 = a1;
+ passStruct9BytesHomogeneousUint82x10_a2 = a2;
+ passStruct9BytesHomogeneousUint82x10_a3 = a3;
+ passStruct9BytesHomogeneousUint82x10_a4 = a4;
+ passStruct9BytesHomogeneousUint82x10_a5 = a5;
+ passStruct9BytesHomogeneousUint82x10_a6 = a6;
+ passStruct9BytesHomogeneousUint82x10_a7 = a7;
+ passStruct9BytesHomogeneousUint82x10_a8 = a8;
+ passStruct9BytesHomogeneousUint82x10_a9 = a9;
+
+ final result = passStruct9BytesHomogeneousUint82x10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct9BytesHomogeneousUint82x10AfterCallback() {
+ final result = passStruct9BytesHomogeneousUint82x10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(4095, result);
+}
+
+typedef PassStruct12BytesHomogeneousFloatx6Type = Float Function(
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat);
+
+// Global variables to be able to test inputs after callback returned.
+Struct12BytesHomogeneousFloat passStruct12BytesHomogeneousFloatx6_a0 =
+ Struct12BytesHomogeneousFloat();
+Struct12BytesHomogeneousFloat passStruct12BytesHomogeneousFloatx6_a1 =
+ Struct12BytesHomogeneousFloat();
+Struct12BytesHomogeneousFloat passStruct12BytesHomogeneousFloatx6_a2 =
+ Struct12BytesHomogeneousFloat();
+Struct12BytesHomogeneousFloat passStruct12BytesHomogeneousFloatx6_a3 =
+ Struct12BytesHomogeneousFloat();
+Struct12BytesHomogeneousFloat passStruct12BytesHomogeneousFloatx6_a4 =
+ Struct12BytesHomogeneousFloat();
+Struct12BytesHomogeneousFloat passStruct12BytesHomogeneousFloatx6_a5 =
+ Struct12BytesHomogeneousFloat();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct12BytesHomogeneousFloatx6Result = 0.0;
+
+double passStruct12BytesHomogeneousFloatx6CalculateResult() {
+ double result = 0;
+
+ result += passStruct12BytesHomogeneousFloatx6_a0.a0;
+ result += passStruct12BytesHomogeneousFloatx6_a0.a1;
+ result += passStruct12BytesHomogeneousFloatx6_a0.a2;
+ result += passStruct12BytesHomogeneousFloatx6_a1.a0;
+ result += passStruct12BytesHomogeneousFloatx6_a1.a1;
+ result += passStruct12BytesHomogeneousFloatx6_a1.a2;
+ result += passStruct12BytesHomogeneousFloatx6_a2.a0;
+ result += passStruct12BytesHomogeneousFloatx6_a2.a1;
+ result += passStruct12BytesHomogeneousFloatx6_a2.a2;
+ result += passStruct12BytesHomogeneousFloatx6_a3.a0;
+ result += passStruct12BytesHomogeneousFloatx6_a3.a1;
+ result += passStruct12BytesHomogeneousFloatx6_a3.a2;
+ result += passStruct12BytesHomogeneousFloatx6_a4.a0;
+ result += passStruct12BytesHomogeneousFloatx6_a4.a1;
+ result += passStruct12BytesHomogeneousFloatx6_a4.a2;
+ result += passStruct12BytesHomogeneousFloatx6_a5.a0;
+ result += passStruct12BytesHomogeneousFloatx6_a5.a1;
+ result += passStruct12BytesHomogeneousFloatx6_a5.a2;
+
+ passStruct12BytesHomogeneousFloatx6Result = result;
+
+ return result;
+}
+
+/// Arguments in FPU registers on arm hardfp and arm64.
+/// Struct arguments will exhaust available registers, and leave some empty.
+/// The last argument is to test whether arguments are backfilled.
+double passStruct12BytesHomogeneousFloatx6(
+ Struct12BytesHomogeneousFloat a0,
+ Struct12BytesHomogeneousFloat a1,
+ Struct12BytesHomogeneousFloat a2,
+ Struct12BytesHomogeneousFloat a3,
+ Struct12BytesHomogeneousFloat a4,
+ Struct12BytesHomogeneousFloat a5) {
+ print(
+ "passStruct12BytesHomogeneousFloatx6(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct12BytesHomogeneousFloatx6 throwing on purpuse!");
+ }
+
+ passStruct12BytesHomogeneousFloatx6_a0 = a0;
+ passStruct12BytesHomogeneousFloatx6_a1 = a1;
+ passStruct12BytesHomogeneousFloatx6_a2 = a2;
+ passStruct12BytesHomogeneousFloatx6_a3 = a3;
+ passStruct12BytesHomogeneousFloatx6_a4 = a4;
+ passStruct12BytesHomogeneousFloatx6_a5 = a5;
+
+ final result = passStruct12BytesHomogeneousFloatx6CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct12BytesHomogeneousFloatx6AfterCallback() {
+ final result = passStruct12BytesHomogeneousFloatx6CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(9.0, result);
+}
+
+typedef PassStruct16BytesHomogeneousFloatx5Type = Float Function(
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat);
+
+// Global variables to be able to test inputs after callback returned.
+Struct16BytesHomogeneousFloat passStruct16BytesHomogeneousFloatx5_a0 =
+ Struct16BytesHomogeneousFloat();
+Struct16BytesHomogeneousFloat passStruct16BytesHomogeneousFloatx5_a1 =
+ Struct16BytesHomogeneousFloat();
+Struct16BytesHomogeneousFloat passStruct16BytesHomogeneousFloatx5_a2 =
+ Struct16BytesHomogeneousFloat();
+Struct16BytesHomogeneousFloat passStruct16BytesHomogeneousFloatx5_a3 =
+ Struct16BytesHomogeneousFloat();
+Struct16BytesHomogeneousFloat passStruct16BytesHomogeneousFloatx5_a4 =
+ Struct16BytesHomogeneousFloat();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct16BytesHomogeneousFloatx5Result = 0.0;
+
+double passStruct16BytesHomogeneousFloatx5CalculateResult() {
+ double result = 0;
+
+ result += passStruct16BytesHomogeneousFloatx5_a0.a0;
+ result += passStruct16BytesHomogeneousFloatx5_a0.a1;
+ result += passStruct16BytesHomogeneousFloatx5_a0.a2;
+ result += passStruct16BytesHomogeneousFloatx5_a0.a3;
+ result += passStruct16BytesHomogeneousFloatx5_a1.a0;
+ result += passStruct16BytesHomogeneousFloatx5_a1.a1;
+ result += passStruct16BytesHomogeneousFloatx5_a1.a2;
+ result += passStruct16BytesHomogeneousFloatx5_a1.a3;
+ result += passStruct16BytesHomogeneousFloatx5_a2.a0;
+ result += passStruct16BytesHomogeneousFloatx5_a2.a1;
+ result += passStruct16BytesHomogeneousFloatx5_a2.a2;
+ result += passStruct16BytesHomogeneousFloatx5_a2.a3;
+ result += passStruct16BytesHomogeneousFloatx5_a3.a0;
+ result += passStruct16BytesHomogeneousFloatx5_a3.a1;
+ result += passStruct16BytesHomogeneousFloatx5_a3.a2;
+ result += passStruct16BytesHomogeneousFloatx5_a3.a3;
+ result += passStruct16BytesHomogeneousFloatx5_a4.a0;
+ result += passStruct16BytesHomogeneousFloatx5_a4.a1;
+ result += passStruct16BytesHomogeneousFloatx5_a4.a2;
+ result += passStruct16BytesHomogeneousFloatx5_a4.a3;
+
+ passStruct16BytesHomogeneousFloatx5Result = result;
+
+ return result;
+}
+
+/// On Linux x64 argument is transferred on stack because it is over 16 bytes.
+/// Arguments in FPU registers on arm hardfp and arm64.
+/// 5 struct arguments will exhaust available registers.
+double passStruct16BytesHomogeneousFloatx5(
+ Struct16BytesHomogeneousFloat a0,
+ Struct16BytesHomogeneousFloat a1,
+ Struct16BytesHomogeneousFloat a2,
+ Struct16BytesHomogeneousFloat a3,
+ Struct16BytesHomogeneousFloat a4) {
+ print(
+ "passStruct16BytesHomogeneousFloatx5(${a0}, ${a1}, ${a2}, ${a3}, ${a4})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct16BytesHomogeneousFloatx5 throwing on purpuse!");
+ }
+
+ passStruct16BytesHomogeneousFloatx5_a0 = a0;
+ passStruct16BytesHomogeneousFloatx5_a1 = a1;
+ passStruct16BytesHomogeneousFloatx5_a2 = a2;
+ passStruct16BytesHomogeneousFloatx5_a3 = a3;
+ passStruct16BytesHomogeneousFloatx5_a4 = a4;
+
+ final result = passStruct16BytesHomogeneousFloatx5CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct16BytesHomogeneousFloatx5AfterCallback() {
+ final result = passStruct16BytesHomogeneousFloatx5CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(10.0, result);
+}
+
+typedef PassStruct16BytesMixedx10Type = Double Function(
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed);
+
+// Global variables to be able to test inputs after callback returned.
+Struct16BytesMixed passStruct16BytesMixedx10_a0 = Struct16BytesMixed();
+Struct16BytesMixed passStruct16BytesMixedx10_a1 = Struct16BytesMixed();
+Struct16BytesMixed passStruct16BytesMixedx10_a2 = Struct16BytesMixed();
+Struct16BytesMixed passStruct16BytesMixedx10_a3 = Struct16BytesMixed();
+Struct16BytesMixed passStruct16BytesMixedx10_a4 = Struct16BytesMixed();
+Struct16BytesMixed passStruct16BytesMixedx10_a5 = Struct16BytesMixed();
+Struct16BytesMixed passStruct16BytesMixedx10_a6 = Struct16BytesMixed();
+Struct16BytesMixed passStruct16BytesMixedx10_a7 = Struct16BytesMixed();
+Struct16BytesMixed passStruct16BytesMixedx10_a8 = Struct16BytesMixed();
+Struct16BytesMixed passStruct16BytesMixedx10_a9 = Struct16BytesMixed();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct16BytesMixedx10Result = 0.0;
+
+double passStruct16BytesMixedx10CalculateResult() {
+ double result = 0;
+
+ result += passStruct16BytesMixedx10_a0.a0;
+ result += passStruct16BytesMixedx10_a0.a1;
+ result += passStruct16BytesMixedx10_a1.a0;
+ result += passStruct16BytesMixedx10_a1.a1;
+ result += passStruct16BytesMixedx10_a2.a0;
+ result += passStruct16BytesMixedx10_a2.a1;
+ result += passStruct16BytesMixedx10_a3.a0;
+ result += passStruct16BytesMixedx10_a3.a1;
+ result += passStruct16BytesMixedx10_a4.a0;
+ result += passStruct16BytesMixedx10_a4.a1;
+ result += passStruct16BytesMixedx10_a5.a0;
+ result += passStruct16BytesMixedx10_a5.a1;
+ result += passStruct16BytesMixedx10_a6.a0;
+ result += passStruct16BytesMixedx10_a6.a1;
+ result += passStruct16BytesMixedx10_a7.a0;
+ result += passStruct16BytesMixedx10_a7.a1;
+ result += passStruct16BytesMixedx10_a8.a0;
+ result += passStruct16BytesMixedx10_a8.a1;
+ result += passStruct16BytesMixedx10_a9.a0;
+ result += passStruct16BytesMixedx10_a9.a1;
+
+ passStruct16BytesMixedx10Result = result;
+
+ return result;
+}
+
+/// On x64, arguments are split over FP and int registers.
+/// On x64, it will exhaust the integer registers with the 6th argument.
+/// The rest goes on the stack.
+/// On arm, arguments are 8 byte aligned.
+double passStruct16BytesMixedx10(
+ Struct16BytesMixed a0,
+ Struct16BytesMixed a1,
+ Struct16BytesMixed a2,
+ Struct16BytesMixed a3,
+ Struct16BytesMixed a4,
+ Struct16BytesMixed a5,
+ Struct16BytesMixed a6,
+ Struct16BytesMixed a7,
+ Struct16BytesMixed a8,
+ Struct16BytesMixed a9) {
+ print(
+ "passStruct16BytesMixedx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct16BytesMixedx10 throwing on purpuse!");
+ }
+
+ passStruct16BytesMixedx10_a0 = a0;
+ passStruct16BytesMixedx10_a1 = a1;
+ passStruct16BytesMixedx10_a2 = a2;
+ passStruct16BytesMixedx10_a3 = a3;
+ passStruct16BytesMixedx10_a4 = a4;
+ passStruct16BytesMixedx10_a5 = a5;
+ passStruct16BytesMixedx10_a6 = a6;
+ passStruct16BytesMixedx10_a7 = a7;
+ passStruct16BytesMixedx10_a8 = a8;
+ passStruct16BytesMixedx10_a9 = a9;
+
+ final result = passStruct16BytesMixedx10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct16BytesMixedx10AfterCallback() {
+ final result = passStruct16BytesMixedx10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(10.0, result);
+}
+
+typedef PassStruct16BytesMixed2x10Type = Float Function(
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2);
+
+// Global variables to be able to test inputs after callback returned.
+Struct16BytesMixed2 passStruct16BytesMixed2x10_a0 = Struct16BytesMixed2();
+Struct16BytesMixed2 passStruct16BytesMixed2x10_a1 = Struct16BytesMixed2();
+Struct16BytesMixed2 passStruct16BytesMixed2x10_a2 = Struct16BytesMixed2();
+Struct16BytesMixed2 passStruct16BytesMixed2x10_a3 = Struct16BytesMixed2();
+Struct16BytesMixed2 passStruct16BytesMixed2x10_a4 = Struct16BytesMixed2();
+Struct16BytesMixed2 passStruct16BytesMixed2x10_a5 = Struct16BytesMixed2();
+Struct16BytesMixed2 passStruct16BytesMixed2x10_a6 = Struct16BytesMixed2();
+Struct16BytesMixed2 passStruct16BytesMixed2x10_a7 = Struct16BytesMixed2();
+Struct16BytesMixed2 passStruct16BytesMixed2x10_a8 = Struct16BytesMixed2();
+Struct16BytesMixed2 passStruct16BytesMixed2x10_a9 = Struct16BytesMixed2();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct16BytesMixed2x10Result = 0.0;
+
+double passStruct16BytesMixed2x10CalculateResult() {
+ double result = 0;
+
+ result += passStruct16BytesMixed2x10_a0.a0;
+ result += passStruct16BytesMixed2x10_a0.a1;
+ result += passStruct16BytesMixed2x10_a0.a2;
+ result += passStruct16BytesMixed2x10_a0.a3;
+ result += passStruct16BytesMixed2x10_a1.a0;
+ result += passStruct16BytesMixed2x10_a1.a1;
+ result += passStruct16BytesMixed2x10_a1.a2;
+ result += passStruct16BytesMixed2x10_a1.a3;
+ result += passStruct16BytesMixed2x10_a2.a0;
+ result += passStruct16BytesMixed2x10_a2.a1;
+ result += passStruct16BytesMixed2x10_a2.a2;
+ result += passStruct16BytesMixed2x10_a2.a3;
+ result += passStruct16BytesMixed2x10_a3.a0;
+ result += passStruct16BytesMixed2x10_a3.a1;
+ result += passStruct16BytesMixed2x10_a3.a2;
+ result += passStruct16BytesMixed2x10_a3.a3;
+ result += passStruct16BytesMixed2x10_a4.a0;
+ result += passStruct16BytesMixed2x10_a4.a1;
+ result += passStruct16BytesMixed2x10_a4.a2;
+ result += passStruct16BytesMixed2x10_a4.a3;
+ result += passStruct16BytesMixed2x10_a5.a0;
+ result += passStruct16BytesMixed2x10_a5.a1;
+ result += passStruct16BytesMixed2x10_a5.a2;
+ result += passStruct16BytesMixed2x10_a5.a3;
+ result += passStruct16BytesMixed2x10_a6.a0;
+ result += passStruct16BytesMixed2x10_a6.a1;
+ result += passStruct16BytesMixed2x10_a6.a2;
+ result += passStruct16BytesMixed2x10_a6.a3;
+ result += passStruct16BytesMixed2x10_a7.a0;
+ result += passStruct16BytesMixed2x10_a7.a1;
+ result += passStruct16BytesMixed2x10_a7.a2;
+ result += passStruct16BytesMixed2x10_a7.a3;
+ result += passStruct16BytesMixed2x10_a8.a0;
+ result += passStruct16BytesMixed2x10_a8.a1;
+ result += passStruct16BytesMixed2x10_a8.a2;
+ result += passStruct16BytesMixed2x10_a8.a3;
+ result += passStruct16BytesMixed2x10_a9.a0;
+ result += passStruct16BytesMixed2x10_a9.a1;
+ result += passStruct16BytesMixed2x10_a9.a2;
+ result += passStruct16BytesMixed2x10_a9.a3;
+
+ passStruct16BytesMixed2x10Result = result;
+
+ return result;
+}
+
+/// On x64, arguments are split over FP and int registers.
+/// On x64, it will exhaust the integer registers with the 6th argument.
+/// The rest goes on the stack.
+/// On arm, arguments are 4 byte aligned.
+double passStruct16BytesMixed2x10(
+ Struct16BytesMixed2 a0,
+ Struct16BytesMixed2 a1,
+ Struct16BytesMixed2 a2,
+ Struct16BytesMixed2 a3,
+ Struct16BytesMixed2 a4,
+ Struct16BytesMixed2 a5,
+ Struct16BytesMixed2 a6,
+ Struct16BytesMixed2 a7,
+ Struct16BytesMixed2 a8,
+ Struct16BytesMixed2 a9) {
+ print(
+ "passStruct16BytesMixed2x10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct16BytesMixed2x10 throwing on purpuse!");
+ }
+
+ passStruct16BytesMixed2x10_a0 = a0;
+ passStruct16BytesMixed2x10_a1 = a1;
+ passStruct16BytesMixed2x10_a2 = a2;
+ passStruct16BytesMixed2x10_a3 = a3;
+ passStruct16BytesMixed2x10_a4 = a4;
+ passStruct16BytesMixed2x10_a5 = a5;
+ passStruct16BytesMixed2x10_a6 = a6;
+ passStruct16BytesMixed2x10_a7 = a7;
+ passStruct16BytesMixed2x10_a8 = a8;
+ passStruct16BytesMixed2x10_a9 = a9;
+
+ final result = passStruct16BytesMixed2x10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct16BytesMixed2x10AfterCallback() {
+ final result = passStruct16BytesMixed2x10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(20.0, result);
+}
+
+typedef PassStruct17BytesIntx10Type = Int64 Function(
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct17BytesInt passStruct17BytesIntx10_a0 = Struct17BytesInt();
+Struct17BytesInt passStruct17BytesIntx10_a1 = Struct17BytesInt();
+Struct17BytesInt passStruct17BytesIntx10_a2 = Struct17BytesInt();
+Struct17BytesInt passStruct17BytesIntx10_a3 = Struct17BytesInt();
+Struct17BytesInt passStruct17BytesIntx10_a4 = Struct17BytesInt();
+Struct17BytesInt passStruct17BytesIntx10_a5 = Struct17BytesInt();
+Struct17BytesInt passStruct17BytesIntx10_a6 = Struct17BytesInt();
+Struct17BytesInt passStruct17BytesIntx10_a7 = Struct17BytesInt();
+Struct17BytesInt passStruct17BytesIntx10_a8 = Struct17BytesInt();
+Struct17BytesInt passStruct17BytesIntx10_a9 = Struct17BytesInt();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct17BytesIntx10Result = 0;
+
+int passStruct17BytesIntx10CalculateResult() {
+ int result = 0;
+
+ result += passStruct17BytesIntx10_a0.a0;
+ result += passStruct17BytesIntx10_a0.a1;
+ result += passStruct17BytesIntx10_a0.a2;
+ result += passStruct17BytesIntx10_a1.a0;
+ result += passStruct17BytesIntx10_a1.a1;
+ result += passStruct17BytesIntx10_a1.a2;
+ result += passStruct17BytesIntx10_a2.a0;
+ result += passStruct17BytesIntx10_a2.a1;
+ result += passStruct17BytesIntx10_a2.a2;
+ result += passStruct17BytesIntx10_a3.a0;
+ result += passStruct17BytesIntx10_a3.a1;
+ result += passStruct17BytesIntx10_a3.a2;
+ result += passStruct17BytesIntx10_a4.a0;
+ result += passStruct17BytesIntx10_a4.a1;
+ result += passStruct17BytesIntx10_a4.a2;
+ result += passStruct17BytesIntx10_a5.a0;
+ result += passStruct17BytesIntx10_a5.a1;
+ result += passStruct17BytesIntx10_a5.a2;
+ result += passStruct17BytesIntx10_a6.a0;
+ result += passStruct17BytesIntx10_a6.a1;
+ result += passStruct17BytesIntx10_a6.a2;
+ result += passStruct17BytesIntx10_a7.a0;
+ result += passStruct17BytesIntx10_a7.a1;
+ result += passStruct17BytesIntx10_a7.a2;
+ result += passStruct17BytesIntx10_a8.a0;
+ result += passStruct17BytesIntx10_a8.a1;
+ result += passStruct17BytesIntx10_a8.a2;
+ result += passStruct17BytesIntx10_a9.a0;
+ result += passStruct17BytesIntx10_a9.a1;
+ result += passStruct17BytesIntx10_a9.a2;
+
+ passStruct17BytesIntx10Result = result;
+
+ return result;
+}
+
+/// Arguments are passed as pointer to copy on arm64.
+/// Tests that the memory allocated for copies are rounded up to word size.
+int passStruct17BytesIntx10(
+ Struct17BytesInt a0,
+ Struct17BytesInt a1,
+ Struct17BytesInt a2,
+ Struct17BytesInt a3,
+ Struct17BytesInt a4,
+ Struct17BytesInt a5,
+ Struct17BytesInt a6,
+ Struct17BytesInt a7,
+ Struct17BytesInt a8,
+ Struct17BytesInt a9) {
+ print(
+ "passStruct17BytesIntx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct17BytesIntx10 throwing on purpuse!");
+ }
+
+ passStruct17BytesIntx10_a0 = a0;
+ passStruct17BytesIntx10_a1 = a1;
+ passStruct17BytesIntx10_a2 = a2;
+ passStruct17BytesIntx10_a3 = a3;
+ passStruct17BytesIntx10_a4 = a4;
+ passStruct17BytesIntx10_a5 = a5;
+ passStruct17BytesIntx10_a6 = a6;
+ passStruct17BytesIntx10_a7 = a7;
+ passStruct17BytesIntx10_a8 = a8;
+ passStruct17BytesIntx10_a9 = a9;
+
+ final result = passStruct17BytesIntx10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct17BytesIntx10AfterCallback() {
+ final result = passStruct17BytesIntx10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(15, result);
+}
+
+typedef PassStruct19BytesHomogeneousUint8x10Type = Int64 Function(
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8);
+
+// Global variables to be able to test inputs after callback returned.
+Struct19BytesHomogeneousUint8 passStruct19BytesHomogeneousUint8x10_a0 =
+ Struct19BytesHomogeneousUint8();
+Struct19BytesHomogeneousUint8 passStruct19BytesHomogeneousUint8x10_a1 =
+ Struct19BytesHomogeneousUint8();
+Struct19BytesHomogeneousUint8 passStruct19BytesHomogeneousUint8x10_a2 =
+ Struct19BytesHomogeneousUint8();
+Struct19BytesHomogeneousUint8 passStruct19BytesHomogeneousUint8x10_a3 =
+ Struct19BytesHomogeneousUint8();
+Struct19BytesHomogeneousUint8 passStruct19BytesHomogeneousUint8x10_a4 =
+ Struct19BytesHomogeneousUint8();
+Struct19BytesHomogeneousUint8 passStruct19BytesHomogeneousUint8x10_a5 =
+ Struct19BytesHomogeneousUint8();
+Struct19BytesHomogeneousUint8 passStruct19BytesHomogeneousUint8x10_a6 =
+ Struct19BytesHomogeneousUint8();
+Struct19BytesHomogeneousUint8 passStruct19BytesHomogeneousUint8x10_a7 =
+ Struct19BytesHomogeneousUint8();
+Struct19BytesHomogeneousUint8 passStruct19BytesHomogeneousUint8x10_a8 =
+ Struct19BytesHomogeneousUint8();
+Struct19BytesHomogeneousUint8 passStruct19BytesHomogeneousUint8x10_a9 =
+ Struct19BytesHomogeneousUint8();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct19BytesHomogeneousUint8x10Result = 0;
+
+int passStruct19BytesHomogeneousUint8x10CalculateResult() {
+ int result = 0;
+
+ result += passStruct19BytesHomogeneousUint8x10_a0.a0;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a1;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a2;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a3;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a4;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a5;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a6;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a7;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a8;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a9;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a10;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a11;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a12;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a13;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a14;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a15;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a16;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a17;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a18;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a0;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a1;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a2;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a3;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a4;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a5;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a6;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a7;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a8;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a9;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a10;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a11;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a12;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a13;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a14;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a15;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a16;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a17;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a18;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a0;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a1;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a2;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a3;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a4;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a5;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a6;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a7;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a8;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a9;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a10;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a11;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a12;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a13;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a14;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a15;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a16;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a17;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a18;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a0;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a1;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a2;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a3;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a4;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a5;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a6;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a7;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a8;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a9;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a10;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a11;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a12;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a13;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a14;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a15;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a16;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a17;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a18;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a0;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a1;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a2;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a3;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a4;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a5;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a6;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a7;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a8;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a9;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a10;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a11;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a12;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a13;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a14;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a15;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a16;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a17;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a18;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a0;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a1;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a2;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a3;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a4;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a5;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a6;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a7;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a8;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a9;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a10;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a11;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a12;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a13;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a14;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a15;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a16;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a17;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a18;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a0;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a1;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a2;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a3;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a4;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a5;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a6;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a7;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a8;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a9;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a10;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a11;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a12;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a13;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a14;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a15;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a16;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a17;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a18;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a0;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a1;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a2;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a3;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a4;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a5;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a6;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a7;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a8;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a9;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a10;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a11;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a12;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a13;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a14;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a15;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a16;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a17;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a18;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a0;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a1;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a2;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a3;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a4;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a5;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a6;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a7;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a8;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a9;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a10;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a11;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a12;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a13;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a14;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a15;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a16;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a17;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a18;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a0;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a1;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a2;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a3;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a4;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a5;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a6;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a7;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a8;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a9;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a10;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a11;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a12;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a13;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a14;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a15;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a16;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a17;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a18;
+
+ passStruct19BytesHomogeneousUint8x10Result = result;
+
+ return result;
+}
+
+/// The minimum alignment of this struct is only 1 byte based on its fields.
+/// Test that the memory backing these structs is extended to the right size.
+///
+int passStruct19BytesHomogeneousUint8x10(
+ Struct19BytesHomogeneousUint8 a0,
+ Struct19BytesHomogeneousUint8 a1,
+ Struct19BytesHomogeneousUint8 a2,
+ Struct19BytesHomogeneousUint8 a3,
+ Struct19BytesHomogeneousUint8 a4,
+ Struct19BytesHomogeneousUint8 a5,
+ Struct19BytesHomogeneousUint8 a6,
+ Struct19BytesHomogeneousUint8 a7,
+ Struct19BytesHomogeneousUint8 a8,
+ Struct19BytesHomogeneousUint8 a9) {
+ print(
+ "passStruct19BytesHomogeneousUint8x10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassStruct19BytesHomogeneousUint8x10 throwing on purpuse!");
+ }
+
+ passStruct19BytesHomogeneousUint8x10_a0 = a0;
+ passStruct19BytesHomogeneousUint8x10_a1 = a1;
+ passStruct19BytesHomogeneousUint8x10_a2 = a2;
+ passStruct19BytesHomogeneousUint8x10_a3 = a3;
+ passStruct19BytesHomogeneousUint8x10_a4 = a4;
+ passStruct19BytesHomogeneousUint8x10_a5 = a5;
+ passStruct19BytesHomogeneousUint8x10_a6 = a6;
+ passStruct19BytesHomogeneousUint8x10_a7 = a7;
+ passStruct19BytesHomogeneousUint8x10_a8 = a8;
+ passStruct19BytesHomogeneousUint8x10_a9 = a9;
+
+ final result = passStruct19BytesHomogeneousUint8x10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct19BytesHomogeneousUint8x10AfterCallback() {
+ final result = passStruct19BytesHomogeneousUint8x10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(18145, result);
+}
+
+typedef PassStruct20BytesHomogeneousInt32x10Type = Int32 Function(
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32);
+
+// Global variables to be able to test inputs after callback returned.
+Struct20BytesHomogeneousInt32 passStruct20BytesHomogeneousInt32x10_a0 =
+ Struct20BytesHomogeneousInt32();
+Struct20BytesHomogeneousInt32 passStruct20BytesHomogeneousInt32x10_a1 =
+ Struct20BytesHomogeneousInt32();
+Struct20BytesHomogeneousInt32 passStruct20BytesHomogeneousInt32x10_a2 =
+ Struct20BytesHomogeneousInt32();
+Struct20BytesHomogeneousInt32 passStruct20BytesHomogeneousInt32x10_a3 =
+ Struct20BytesHomogeneousInt32();
+Struct20BytesHomogeneousInt32 passStruct20BytesHomogeneousInt32x10_a4 =
+ Struct20BytesHomogeneousInt32();
+Struct20BytesHomogeneousInt32 passStruct20BytesHomogeneousInt32x10_a5 =
+ Struct20BytesHomogeneousInt32();
+Struct20BytesHomogeneousInt32 passStruct20BytesHomogeneousInt32x10_a6 =
+ Struct20BytesHomogeneousInt32();
+Struct20BytesHomogeneousInt32 passStruct20BytesHomogeneousInt32x10_a7 =
+ Struct20BytesHomogeneousInt32();
+Struct20BytesHomogeneousInt32 passStruct20BytesHomogeneousInt32x10_a8 =
+ Struct20BytesHomogeneousInt32();
+Struct20BytesHomogeneousInt32 passStruct20BytesHomogeneousInt32x10_a9 =
+ Struct20BytesHomogeneousInt32();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct20BytesHomogeneousInt32x10Result = 0;
+
+int passStruct20BytesHomogeneousInt32x10CalculateResult() {
+ int result = 0;
+
+ result += passStruct20BytesHomogeneousInt32x10_a0.a0;
+ result += passStruct20BytesHomogeneousInt32x10_a0.a1;
+ result += passStruct20BytesHomogeneousInt32x10_a0.a2;
+ result += passStruct20BytesHomogeneousInt32x10_a0.a3;
+ result += passStruct20BytesHomogeneousInt32x10_a0.a4;
+ result += passStruct20BytesHomogeneousInt32x10_a1.a0;
+ result += passStruct20BytesHomogeneousInt32x10_a1.a1;
+ result += passStruct20BytesHomogeneousInt32x10_a1.a2;
+ result += passStruct20BytesHomogeneousInt32x10_a1.a3;
+ result += passStruct20BytesHomogeneousInt32x10_a1.a4;
+ result += passStruct20BytesHomogeneousInt32x10_a2.a0;
+ result += passStruct20BytesHomogeneousInt32x10_a2.a1;
+ result += passStruct20BytesHomogeneousInt32x10_a2.a2;
+ result += passStruct20BytesHomogeneousInt32x10_a2.a3;
+ result += passStruct20BytesHomogeneousInt32x10_a2.a4;
+ result += passStruct20BytesHomogeneousInt32x10_a3.a0;
+ result += passStruct20BytesHomogeneousInt32x10_a3.a1;
+ result += passStruct20BytesHomogeneousInt32x10_a3.a2;
+ result += passStruct20BytesHomogeneousInt32x10_a3.a3;
+ result += passStruct20BytesHomogeneousInt32x10_a3.a4;
+ result += passStruct20BytesHomogeneousInt32x10_a4.a0;
+ result += passStruct20BytesHomogeneousInt32x10_a4.a1;
+ result += passStruct20BytesHomogeneousInt32x10_a4.a2;
+ result += passStruct20BytesHomogeneousInt32x10_a4.a3;
+ result += passStruct20BytesHomogeneousInt32x10_a4.a4;
+ result += passStruct20BytesHomogeneousInt32x10_a5.a0;
+ result += passStruct20BytesHomogeneousInt32x10_a5.a1;
+ result += passStruct20BytesHomogeneousInt32x10_a5.a2;
+ result += passStruct20BytesHomogeneousInt32x10_a5.a3;
+ result += passStruct20BytesHomogeneousInt32x10_a5.a4;
+ result += passStruct20BytesHomogeneousInt32x10_a6.a0;
+ result += passStruct20BytesHomogeneousInt32x10_a6.a1;
+ result += passStruct20BytesHomogeneousInt32x10_a6.a2;
+ result += passStruct20BytesHomogeneousInt32x10_a6.a3;
+ result += passStruct20BytesHomogeneousInt32x10_a6.a4;
+ result += passStruct20BytesHomogeneousInt32x10_a7.a0;
+ result += passStruct20BytesHomogeneousInt32x10_a7.a1;
+ result += passStruct20BytesHomogeneousInt32x10_a7.a2;
+ result += passStruct20BytesHomogeneousInt32x10_a7.a3;
+ result += passStruct20BytesHomogeneousInt32x10_a7.a4;
+ result += passStruct20BytesHomogeneousInt32x10_a8.a0;
+ result += passStruct20BytesHomogeneousInt32x10_a8.a1;
+ result += passStruct20BytesHomogeneousInt32x10_a8.a2;
+ result += passStruct20BytesHomogeneousInt32x10_a8.a3;
+ result += passStruct20BytesHomogeneousInt32x10_a8.a4;
+ result += passStruct20BytesHomogeneousInt32x10_a9.a0;
+ result += passStruct20BytesHomogeneousInt32x10_a9.a1;
+ result += passStruct20BytesHomogeneousInt32x10_a9.a2;
+ result += passStruct20BytesHomogeneousInt32x10_a9.a3;
+ result += passStruct20BytesHomogeneousInt32x10_a9.a4;
+
+ passStruct20BytesHomogeneousInt32x10Result = result;
+
+ return result;
+}
+
+/// Argument too big to go into integer registers on arm64.
+/// The arguments are passed as pointers to copies.
+/// The amount of arguments exhausts the number of integer registers, such that
+/// pointers to copies are also passed on the stack.
+int passStruct20BytesHomogeneousInt32x10(
+ Struct20BytesHomogeneousInt32 a0,
+ Struct20BytesHomogeneousInt32 a1,
+ Struct20BytesHomogeneousInt32 a2,
+ Struct20BytesHomogeneousInt32 a3,
+ Struct20BytesHomogeneousInt32 a4,
+ Struct20BytesHomogeneousInt32 a5,
+ Struct20BytesHomogeneousInt32 a6,
+ Struct20BytesHomogeneousInt32 a7,
+ Struct20BytesHomogeneousInt32 a8,
+ Struct20BytesHomogeneousInt32 a9) {
+ print(
+ "passStruct20BytesHomogeneousInt32x10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassStruct20BytesHomogeneousInt32x10 throwing on purpuse!");
+ }
+
+ passStruct20BytesHomogeneousInt32x10_a0 = a0;
+ passStruct20BytesHomogeneousInt32x10_a1 = a1;
+ passStruct20BytesHomogeneousInt32x10_a2 = a2;
+ passStruct20BytesHomogeneousInt32x10_a3 = a3;
+ passStruct20BytesHomogeneousInt32x10_a4 = a4;
+ passStruct20BytesHomogeneousInt32x10_a5 = a5;
+ passStruct20BytesHomogeneousInt32x10_a6 = a6;
+ passStruct20BytesHomogeneousInt32x10_a7 = a7;
+ passStruct20BytesHomogeneousInt32x10_a8 = a8;
+ passStruct20BytesHomogeneousInt32x10_a9 = a9;
+
+ final result = passStruct20BytesHomogeneousInt32x10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct20BytesHomogeneousInt32x10AfterCallback() {
+ final result = passStruct20BytesHomogeneousInt32x10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(25, result);
+}
+
+typedef PassStruct20BytesHomogeneousFloatType = Float Function(
+ Struct20BytesHomogeneousFloat);
+
+// Global variables to be able to test inputs after callback returned.
+Struct20BytesHomogeneousFloat passStruct20BytesHomogeneousFloat_a0 =
+ Struct20BytesHomogeneousFloat();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct20BytesHomogeneousFloatResult = 0.0;
+
+double passStruct20BytesHomogeneousFloatCalculateResult() {
+ double result = 0;
+
+ result += passStruct20BytesHomogeneousFloat_a0.a0;
+ result += passStruct20BytesHomogeneousFloat_a0.a1;
+ result += passStruct20BytesHomogeneousFloat_a0.a2;
+ result += passStruct20BytesHomogeneousFloat_a0.a3;
+ result += passStruct20BytesHomogeneousFloat_a0.a4;
+
+ passStruct20BytesHomogeneousFloatResult = result;
+
+ return result;
+}
+
+/// Argument too big to go into FPU registers in hardfp and arm64.
+double passStruct20BytesHomogeneousFloat(Struct20BytesHomogeneousFloat a0) {
+ print("passStruct20BytesHomogeneousFloat(${a0})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct20BytesHomogeneousFloat throwing on purpuse!");
+ }
+
+ passStruct20BytesHomogeneousFloat_a0 = a0;
+
+ final result = passStruct20BytesHomogeneousFloatCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct20BytesHomogeneousFloatAfterCallback() {
+ final result = passStruct20BytesHomogeneousFloatCalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(-3.0, result);
+}
+
+typedef PassStruct32BytesHomogeneousDoublex5Type = Double Function(
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble);
+
+// Global variables to be able to test inputs after callback returned.
+Struct32BytesHomogeneousDouble passStruct32BytesHomogeneousDoublex5_a0 =
+ Struct32BytesHomogeneousDouble();
+Struct32BytesHomogeneousDouble passStruct32BytesHomogeneousDoublex5_a1 =
+ Struct32BytesHomogeneousDouble();
+Struct32BytesHomogeneousDouble passStruct32BytesHomogeneousDoublex5_a2 =
+ Struct32BytesHomogeneousDouble();
+Struct32BytesHomogeneousDouble passStruct32BytesHomogeneousDoublex5_a3 =
+ Struct32BytesHomogeneousDouble();
+Struct32BytesHomogeneousDouble passStruct32BytesHomogeneousDoublex5_a4 =
+ Struct32BytesHomogeneousDouble();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct32BytesHomogeneousDoublex5Result = 0.0;
+
+double passStruct32BytesHomogeneousDoublex5CalculateResult() {
+ double result = 0;
+
+ result += passStruct32BytesHomogeneousDoublex5_a0.a0;
+ result += passStruct32BytesHomogeneousDoublex5_a0.a1;
+ result += passStruct32BytesHomogeneousDoublex5_a0.a2;
+ result += passStruct32BytesHomogeneousDoublex5_a0.a3;
+ result += passStruct32BytesHomogeneousDoublex5_a1.a0;
+ result += passStruct32BytesHomogeneousDoublex5_a1.a1;
+ result += passStruct32BytesHomogeneousDoublex5_a1.a2;
+ result += passStruct32BytesHomogeneousDoublex5_a1.a3;
+ result += passStruct32BytesHomogeneousDoublex5_a2.a0;
+ result += passStruct32BytesHomogeneousDoublex5_a2.a1;
+ result += passStruct32BytesHomogeneousDoublex5_a2.a2;
+ result += passStruct32BytesHomogeneousDoublex5_a2.a3;
+ result += passStruct32BytesHomogeneousDoublex5_a3.a0;
+ result += passStruct32BytesHomogeneousDoublex5_a3.a1;
+ result += passStruct32BytesHomogeneousDoublex5_a3.a2;
+ result += passStruct32BytesHomogeneousDoublex5_a3.a3;
+ result += passStruct32BytesHomogeneousDoublex5_a4.a0;
+ result += passStruct32BytesHomogeneousDoublex5_a4.a1;
+ result += passStruct32BytesHomogeneousDoublex5_a4.a2;
+ result += passStruct32BytesHomogeneousDoublex5_a4.a3;
+
+ passStruct32BytesHomogeneousDoublex5Result = result;
+
+ return result;
+}
+
+/// Arguments in FPU registers on arm64.
+/// 5 struct arguments will exhaust available registers.
+double passStruct32BytesHomogeneousDoublex5(
+ Struct32BytesHomogeneousDouble a0,
+ Struct32BytesHomogeneousDouble a1,
+ Struct32BytesHomogeneousDouble a2,
+ Struct32BytesHomogeneousDouble a3,
+ Struct32BytesHomogeneousDouble a4) {
+ print(
+ "passStruct32BytesHomogeneousDoublex5(${a0}, ${a1}, ${a2}, ${a3}, ${a4})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassStruct32BytesHomogeneousDoublex5 throwing on purpuse!");
+ }
+
+ passStruct32BytesHomogeneousDoublex5_a0 = a0;
+ passStruct32BytesHomogeneousDoublex5_a1 = a1;
+ passStruct32BytesHomogeneousDoublex5_a2 = a2;
+ passStruct32BytesHomogeneousDoublex5_a3 = a3;
+ passStruct32BytesHomogeneousDoublex5_a4 = a4;
+
+ final result = passStruct32BytesHomogeneousDoublex5CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct32BytesHomogeneousDoublex5AfterCallback() {
+ final result = passStruct32BytesHomogeneousDoublex5CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(10.0, result);
+}
+
+typedef PassStruct40BytesHomogeneousDoubleType = Double Function(
+ Struct40BytesHomogeneousDouble);
+
+// Global variables to be able to test inputs after callback returned.
+Struct40BytesHomogeneousDouble passStruct40BytesHomogeneousDouble_a0 =
+ Struct40BytesHomogeneousDouble();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct40BytesHomogeneousDoubleResult = 0.0;
+
+double passStruct40BytesHomogeneousDoubleCalculateResult() {
+ double result = 0;
+
+ result += passStruct40BytesHomogeneousDouble_a0.a0;
+ result += passStruct40BytesHomogeneousDouble_a0.a1;
+ result += passStruct40BytesHomogeneousDouble_a0.a2;
+ result += passStruct40BytesHomogeneousDouble_a0.a3;
+ result += passStruct40BytesHomogeneousDouble_a0.a4;
+
+ passStruct40BytesHomogeneousDoubleResult = result;
+
+ return result;
+}
+
+/// Argument too big to go into FPU registers in arm64.
+double passStruct40BytesHomogeneousDouble(Struct40BytesHomogeneousDouble a0) {
+ print("passStruct40BytesHomogeneousDouble(${a0})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct40BytesHomogeneousDouble throwing on purpuse!");
+ }
+
+ passStruct40BytesHomogeneousDouble_a0 = a0;
+
+ final result = passStruct40BytesHomogeneousDoubleCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct40BytesHomogeneousDoubleAfterCallback() {
+ final result = passStruct40BytesHomogeneousDoubleCalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(-3.0, result);
+}
+
+typedef PassStruct1024BytesHomogeneousUint64Type = Uint64 Function(
+ Struct1024BytesHomogeneousUint64);
+
+// Global variables to be able to test inputs after callback returned.
+Struct1024BytesHomogeneousUint64 passStruct1024BytesHomogeneousUint64_a0 =
+ Struct1024BytesHomogeneousUint64();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct1024BytesHomogeneousUint64Result = 0;
+
+int passStruct1024BytesHomogeneousUint64CalculateResult() {
+ int result = 0;
+
+ result += passStruct1024BytesHomogeneousUint64_a0.a0;
+ result += passStruct1024BytesHomogeneousUint64_a0.a1;
+ result += passStruct1024BytesHomogeneousUint64_a0.a2;
+ result += passStruct1024BytesHomogeneousUint64_a0.a3;
+ result += passStruct1024BytesHomogeneousUint64_a0.a4;
+ result += passStruct1024BytesHomogeneousUint64_a0.a5;
+ result += passStruct1024BytesHomogeneousUint64_a0.a6;
+ result += passStruct1024BytesHomogeneousUint64_a0.a7;
+ result += passStruct1024BytesHomogeneousUint64_a0.a8;
+ result += passStruct1024BytesHomogeneousUint64_a0.a9;
+ result += passStruct1024BytesHomogeneousUint64_a0.a10;
+ result += passStruct1024BytesHomogeneousUint64_a0.a11;
+ result += passStruct1024BytesHomogeneousUint64_a0.a12;
+ result += passStruct1024BytesHomogeneousUint64_a0.a13;
+ result += passStruct1024BytesHomogeneousUint64_a0.a14;
+ result += passStruct1024BytesHomogeneousUint64_a0.a15;
+ result += passStruct1024BytesHomogeneousUint64_a0.a16;
+ result += passStruct1024BytesHomogeneousUint64_a0.a17;
+ result += passStruct1024BytesHomogeneousUint64_a0.a18;
+ result += passStruct1024BytesHomogeneousUint64_a0.a19;
+ result += passStruct1024BytesHomogeneousUint64_a0.a20;
+ result += passStruct1024BytesHomogeneousUint64_a0.a21;
+ result += passStruct1024BytesHomogeneousUint64_a0.a22;
+ result += passStruct1024BytesHomogeneousUint64_a0.a23;
+ result += passStruct1024BytesHomogeneousUint64_a0.a24;
+ result += passStruct1024BytesHomogeneousUint64_a0.a25;
+ result += passStruct1024BytesHomogeneousUint64_a0.a26;
+ result += passStruct1024BytesHomogeneousUint64_a0.a27;
+ result += passStruct1024BytesHomogeneousUint64_a0.a28;
+ result += passStruct1024BytesHomogeneousUint64_a0.a29;
+ result += passStruct1024BytesHomogeneousUint64_a0.a30;
+ result += passStruct1024BytesHomogeneousUint64_a0.a31;
+ result += passStruct1024BytesHomogeneousUint64_a0.a32;
+ result += passStruct1024BytesHomogeneousUint64_a0.a33;
+ result += passStruct1024BytesHomogeneousUint64_a0.a34;
+ result += passStruct1024BytesHomogeneousUint64_a0.a35;
+ result += passStruct1024BytesHomogeneousUint64_a0.a36;
+ result += passStruct1024BytesHomogeneousUint64_a0.a37;
+ result += passStruct1024BytesHomogeneousUint64_a0.a38;
+ result += passStruct1024BytesHomogeneousUint64_a0.a39;
+ result += passStruct1024BytesHomogeneousUint64_a0.a40;
+ result += passStruct1024BytesHomogeneousUint64_a0.a41;
+ result += passStruct1024BytesHomogeneousUint64_a0.a42;
+ result += passStruct1024BytesHomogeneousUint64_a0.a43;
+ result += passStruct1024BytesHomogeneousUint64_a0.a44;
+ result += passStruct1024BytesHomogeneousUint64_a0.a45;
+ result += passStruct1024BytesHomogeneousUint64_a0.a46;
+ result += passStruct1024BytesHomogeneousUint64_a0.a47;
+ result += passStruct1024BytesHomogeneousUint64_a0.a48;
+ result += passStruct1024BytesHomogeneousUint64_a0.a49;
+ result += passStruct1024BytesHomogeneousUint64_a0.a50;
+ result += passStruct1024BytesHomogeneousUint64_a0.a51;
+ result += passStruct1024BytesHomogeneousUint64_a0.a52;
+ result += passStruct1024BytesHomogeneousUint64_a0.a53;
+ result += passStruct1024BytesHomogeneousUint64_a0.a54;
+ result += passStruct1024BytesHomogeneousUint64_a0.a55;
+ result += passStruct1024BytesHomogeneousUint64_a0.a56;
+ result += passStruct1024BytesHomogeneousUint64_a0.a57;
+ result += passStruct1024BytesHomogeneousUint64_a0.a58;
+ result += passStruct1024BytesHomogeneousUint64_a0.a59;
+ result += passStruct1024BytesHomogeneousUint64_a0.a60;
+ result += passStruct1024BytesHomogeneousUint64_a0.a61;
+ result += passStruct1024BytesHomogeneousUint64_a0.a62;
+ result += passStruct1024BytesHomogeneousUint64_a0.a63;
+ result += passStruct1024BytesHomogeneousUint64_a0.a64;
+ result += passStruct1024BytesHomogeneousUint64_a0.a65;
+ result += passStruct1024BytesHomogeneousUint64_a0.a66;
+ result += passStruct1024BytesHomogeneousUint64_a0.a67;
+ result += passStruct1024BytesHomogeneousUint64_a0.a68;
+ result += passStruct1024BytesHomogeneousUint64_a0.a69;
+ result += passStruct1024BytesHomogeneousUint64_a0.a70;
+ result += passStruct1024BytesHomogeneousUint64_a0.a71;
+ result += passStruct1024BytesHomogeneousUint64_a0.a72;
+ result += passStruct1024BytesHomogeneousUint64_a0.a73;
+ result += passStruct1024BytesHomogeneousUint64_a0.a74;
+ result += passStruct1024BytesHomogeneousUint64_a0.a75;
+ result += passStruct1024BytesHomogeneousUint64_a0.a76;
+ result += passStruct1024BytesHomogeneousUint64_a0.a77;
+ result += passStruct1024BytesHomogeneousUint64_a0.a78;
+ result += passStruct1024BytesHomogeneousUint64_a0.a79;
+ result += passStruct1024BytesHomogeneousUint64_a0.a80;
+ result += passStruct1024BytesHomogeneousUint64_a0.a81;
+ result += passStruct1024BytesHomogeneousUint64_a0.a82;
+ result += passStruct1024BytesHomogeneousUint64_a0.a83;
+ result += passStruct1024BytesHomogeneousUint64_a0.a84;
+ result += passStruct1024BytesHomogeneousUint64_a0.a85;
+ result += passStruct1024BytesHomogeneousUint64_a0.a86;
+ result += passStruct1024BytesHomogeneousUint64_a0.a87;
+ result += passStruct1024BytesHomogeneousUint64_a0.a88;
+ result += passStruct1024BytesHomogeneousUint64_a0.a89;
+ result += passStruct1024BytesHomogeneousUint64_a0.a90;
+ result += passStruct1024BytesHomogeneousUint64_a0.a91;
+ result += passStruct1024BytesHomogeneousUint64_a0.a92;
+ result += passStruct1024BytesHomogeneousUint64_a0.a93;
+ result += passStruct1024BytesHomogeneousUint64_a0.a94;
+ result += passStruct1024BytesHomogeneousUint64_a0.a95;
+ result += passStruct1024BytesHomogeneousUint64_a0.a96;
+ result += passStruct1024BytesHomogeneousUint64_a0.a97;
+ result += passStruct1024BytesHomogeneousUint64_a0.a98;
+ result += passStruct1024BytesHomogeneousUint64_a0.a99;
+ result += passStruct1024BytesHomogeneousUint64_a0.a100;
+ result += passStruct1024BytesHomogeneousUint64_a0.a101;
+ result += passStruct1024BytesHomogeneousUint64_a0.a102;
+ result += passStruct1024BytesHomogeneousUint64_a0.a103;
+ result += passStruct1024BytesHomogeneousUint64_a0.a104;
+ result += passStruct1024BytesHomogeneousUint64_a0.a105;
+ result += passStruct1024BytesHomogeneousUint64_a0.a106;
+ result += passStruct1024BytesHomogeneousUint64_a0.a107;
+ result += passStruct1024BytesHomogeneousUint64_a0.a108;
+ result += passStruct1024BytesHomogeneousUint64_a0.a109;
+ result += passStruct1024BytesHomogeneousUint64_a0.a110;
+ result += passStruct1024BytesHomogeneousUint64_a0.a111;
+ result += passStruct1024BytesHomogeneousUint64_a0.a112;
+ result += passStruct1024BytesHomogeneousUint64_a0.a113;
+ result += passStruct1024BytesHomogeneousUint64_a0.a114;
+ result += passStruct1024BytesHomogeneousUint64_a0.a115;
+ result += passStruct1024BytesHomogeneousUint64_a0.a116;
+ result += passStruct1024BytesHomogeneousUint64_a0.a117;
+ result += passStruct1024BytesHomogeneousUint64_a0.a118;
+ result += passStruct1024BytesHomogeneousUint64_a0.a119;
+ result += passStruct1024BytesHomogeneousUint64_a0.a120;
+ result += passStruct1024BytesHomogeneousUint64_a0.a121;
+ result += passStruct1024BytesHomogeneousUint64_a0.a122;
+ result += passStruct1024BytesHomogeneousUint64_a0.a123;
+ result += passStruct1024BytesHomogeneousUint64_a0.a124;
+ result += passStruct1024BytesHomogeneousUint64_a0.a125;
+ result += passStruct1024BytesHomogeneousUint64_a0.a126;
+ result += passStruct1024BytesHomogeneousUint64_a0.a127;
+
+ passStruct1024BytesHomogeneousUint64Result = result;
+
+ return result;
+}
+
+/// Test 1kb struct.
+int passStruct1024BytesHomogeneousUint64(Struct1024BytesHomogeneousUint64 a0) {
+ print("passStruct1024BytesHomogeneousUint64(${a0})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassStruct1024BytesHomogeneousUint64 throwing on purpuse!");
+ }
+
+ passStruct1024BytesHomogeneousUint64_a0 = a0;
+
+ final result = passStruct1024BytesHomogeneousUint64CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct1024BytesHomogeneousUint64AfterCallback() {
+ final result = passStruct1024BytesHomogeneousUint64CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(8256, result);
+}
+
+typedef PassFloatStruct16BytesHomogeneousFloatFloatStruct1Type = Float Function(
+ Float,
+ Struct16BytesHomogeneousFloat,
+ Float,
+ Struct16BytesHomogeneousFloat,
+ Float,
+ Struct16BytesHomogeneousFloat,
+ Float,
+ Struct16BytesHomogeneousFloat,
+ Float);
+
+// Global variables to be able to test inputs after callback returned.
+double passFloatStruct16BytesHomogeneousFloatFloatStruct1_a0 = 0.0;
+Struct16BytesHomogeneousFloat
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a1 =
+ Struct16BytesHomogeneousFloat();
+double passFloatStruct16BytesHomogeneousFloatFloatStruct1_a2 = 0.0;
+Struct16BytesHomogeneousFloat
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a3 =
+ Struct16BytesHomogeneousFloat();
+double passFloatStruct16BytesHomogeneousFloatFloatStruct1_a4 = 0.0;
+Struct16BytesHomogeneousFloat
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a5 =
+ Struct16BytesHomogeneousFloat();
+double passFloatStruct16BytesHomogeneousFloatFloatStruct1_a6 = 0.0;
+Struct16BytesHomogeneousFloat
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a7 =
+ Struct16BytesHomogeneousFloat();
+double passFloatStruct16BytesHomogeneousFloatFloatStruct1_a8 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+double passFloatStruct16BytesHomogeneousFloatFloatStruct1Result = 0.0;
+
+double passFloatStruct16BytesHomogeneousFloatFloatStruct1CalculateResult() {
+ double result = 0;
+
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a0;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a1.a0;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a1.a1;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a1.a2;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a1.a3;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a2;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a3.a0;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a3.a1;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a3.a2;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a3.a3;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a4;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a5.a0;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a5.a1;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a5.a2;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a5.a3;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a6;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a7.a0;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a7.a1;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a7.a2;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a7.a3;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a8;
+
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1Result = result;
+
+ return result;
+}
+
+/// Tests the alignment of structs in FPU registers and backfilling.
+double passFloatStruct16BytesHomogeneousFloatFloatStruct1(
+ double a0,
+ Struct16BytesHomogeneousFloat a1,
+ double a2,
+ Struct16BytesHomogeneousFloat a3,
+ double a4,
+ Struct16BytesHomogeneousFloat a5,
+ double a6,
+ Struct16BytesHomogeneousFloat a7,
+ double a8) {
+ print(
+ "passFloatStruct16BytesHomogeneousFloatFloatStruct1(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassFloatStruct16BytesHomogeneousFloatFloatStruct1 throwing on purpuse!");
+ }
+
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a0 = a0;
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a1 = a1;
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a2 = a2;
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a3 = a3;
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a4 = a4;
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a5 = a5;
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a6 = a6;
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a7 = a7;
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a8 = a8;
+
+ final result =
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passFloatStruct16BytesHomogeneousFloatFloatStruct1AfterCallback() {
+ final result =
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(-11.0, result);
+}
+
+typedef PassFloatStruct32BytesHomogeneousDoubleFloatStructType
+ = Double Function(
+ Float,
+ Struct32BytesHomogeneousDouble,
+ Float,
+ Struct32BytesHomogeneousDouble,
+ Float,
+ Struct32BytesHomogeneousDouble,
+ Float,
+ Struct32BytesHomogeneousDouble,
+ Float);
+
+// Global variables to be able to test inputs after callback returned.
+double passFloatStruct32BytesHomogeneousDoubleFloatStruct_a0 = 0.0;
+Struct32BytesHomogeneousDouble
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a1 =
+ Struct32BytesHomogeneousDouble();
+double passFloatStruct32BytesHomogeneousDoubleFloatStruct_a2 = 0.0;
+Struct32BytesHomogeneousDouble
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a3 =
+ Struct32BytesHomogeneousDouble();
+double passFloatStruct32BytesHomogeneousDoubleFloatStruct_a4 = 0.0;
+Struct32BytesHomogeneousDouble
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a5 =
+ Struct32BytesHomogeneousDouble();
+double passFloatStruct32BytesHomogeneousDoubleFloatStruct_a6 = 0.0;
+Struct32BytesHomogeneousDouble
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a7 =
+ Struct32BytesHomogeneousDouble();
+double passFloatStruct32BytesHomogeneousDoubleFloatStruct_a8 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+double passFloatStruct32BytesHomogeneousDoubleFloatStructResult = 0.0;
+
+double passFloatStruct32BytesHomogeneousDoubleFloatStructCalculateResult() {
+ double result = 0;
+
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a0;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a1.a0;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a1.a1;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a1.a2;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a1.a3;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a2;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a3.a0;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a3.a1;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a3.a2;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a3.a3;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a4;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a5.a0;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a5.a1;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a5.a2;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a5.a3;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a6;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a7.a0;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a7.a1;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a7.a2;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a7.a3;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a8;
+
+ passFloatStruct32BytesHomogeneousDoubleFloatStructResult = result;
+
+ return result;
+}
+
+/// Tests the alignment of structs in FPU registers and backfilling.
+double passFloatStruct32BytesHomogeneousDoubleFloatStruct(
+ double a0,
+ Struct32BytesHomogeneousDouble a1,
+ double a2,
+ Struct32BytesHomogeneousDouble a3,
+ double a4,
+ Struct32BytesHomogeneousDouble a5,
+ double a6,
+ Struct32BytesHomogeneousDouble a7,
+ double a8) {
+ print(
+ "passFloatStruct32BytesHomogeneousDoubleFloatStruct(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassFloatStruct32BytesHomogeneousDoubleFloatStruct throwing on purpuse!");
+ }
+
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a0 = a0;
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a1 = a1;
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a2 = a2;
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a3 = a3;
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a4 = a4;
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a5 = a5;
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a6 = a6;
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a7 = a7;
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a8 = a8;
+
+ final result =
+ passFloatStruct32BytesHomogeneousDoubleFloatStructCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passFloatStruct32BytesHomogeneousDoubleFloatStructAfterCallback() {
+ final result =
+ passFloatStruct32BytesHomogeneousDoubleFloatStructCalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(-11.0, result);
+}
+
+typedef PassInt8Struct16BytesMixedInt8Struct16BytesMixedInType
+ = Double Function(Int8, Struct16BytesMixed, Int8, Struct16BytesMixed, Int8,
+ Struct16BytesMixed, Int8, Struct16BytesMixed, Int8);
+
+// Global variables to be able to test inputs after callback returned.
+int passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a0 = 0;
+Struct16BytesMixed passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a1 =
+ Struct16BytesMixed();
+int passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a2 = 0;
+Struct16BytesMixed passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a3 =
+ Struct16BytesMixed();
+int passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a4 = 0;
+Struct16BytesMixed passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a5 =
+ Struct16BytesMixed();
+int passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a6 = 0;
+Struct16BytesMixed passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a7 =
+ Struct16BytesMixed();
+int passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a8 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+double passInt8Struct16BytesMixedInt8Struct16BytesMixedInResult = 0.0;
+
+double passInt8Struct16BytesMixedInt8Struct16BytesMixedInCalculateResult() {
+ double result = 0;
+
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a0;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a1.a0;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a1.a1;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a2;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a3.a0;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a3.a1;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a4;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a5.a0;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a5.a1;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a6;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a7.a0;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a7.a1;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a8;
+
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedInResult = result;
+
+ return result;
+}
+
+/// Tests the alignment of structs in integers registers and on the stack.
+/// Arm32 aligns this struct at 8.
+/// Also, arm32 allocates the second struct partially in registers, partially
+/// on stack.
+/// Test backfilling of integer registers.
+double passInt8Struct16BytesMixedInt8Struct16BytesMixedIn(
+ int a0,
+ Struct16BytesMixed a1,
+ int a2,
+ Struct16BytesMixed a3,
+ int a4,
+ Struct16BytesMixed a5,
+ int a6,
+ Struct16BytesMixed a7,
+ int a8) {
+ print(
+ "passInt8Struct16BytesMixedInt8Struct16BytesMixedIn(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassInt8Struct16BytesMixedInt8Struct16BytesMixedIn throwing on purpuse!");
+ }
+
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a0 = a0;
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a1 = a1;
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a2 = a2;
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a3 = a3;
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a4 = a4;
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a5 = a5;
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a6 = a6;
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a7 = a7;
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a8 = a8;
+
+ final result =
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedInCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passInt8Struct16BytesMixedInt8Struct16BytesMixedInAfterCallback() {
+ final result =
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedInCalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(-7.0, result);
+}
+
+typedef PassDoublex6Struct16BytesMixedx4Int32Type = Double Function(
+ Double,
+ Double,
+ Double,
+ Double,
+ Double,
+ Double,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Int32);
+
+// Global variables to be able to test inputs after callback returned.
+double passDoublex6Struct16BytesMixedx4Int32_a0 = 0.0;
+double passDoublex6Struct16BytesMixedx4Int32_a1 = 0.0;
+double passDoublex6Struct16BytesMixedx4Int32_a2 = 0.0;
+double passDoublex6Struct16BytesMixedx4Int32_a3 = 0.0;
+double passDoublex6Struct16BytesMixedx4Int32_a4 = 0.0;
+double passDoublex6Struct16BytesMixedx4Int32_a5 = 0.0;
+Struct16BytesMixed passDoublex6Struct16BytesMixedx4Int32_a6 =
+ Struct16BytesMixed();
+Struct16BytesMixed passDoublex6Struct16BytesMixedx4Int32_a7 =
+ Struct16BytesMixed();
+Struct16BytesMixed passDoublex6Struct16BytesMixedx4Int32_a8 =
+ Struct16BytesMixed();
+Struct16BytesMixed passDoublex6Struct16BytesMixedx4Int32_a9 =
+ Struct16BytesMixed();
+int passDoublex6Struct16BytesMixedx4Int32_a10 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+double passDoublex6Struct16BytesMixedx4Int32Result = 0.0;
+
+double passDoublex6Struct16BytesMixedx4Int32CalculateResult() {
+ double result = 0;
+
+ result += passDoublex6Struct16BytesMixedx4Int32_a0;
+ result += passDoublex6Struct16BytesMixedx4Int32_a1;
+ result += passDoublex6Struct16BytesMixedx4Int32_a2;
+ result += passDoublex6Struct16BytesMixedx4Int32_a3;
+ result += passDoublex6Struct16BytesMixedx4Int32_a4;
+ result += passDoublex6Struct16BytesMixedx4Int32_a5;
+ result += passDoublex6Struct16BytesMixedx4Int32_a6.a0;
+ result += passDoublex6Struct16BytesMixedx4Int32_a6.a1;
+ result += passDoublex6Struct16BytesMixedx4Int32_a7.a0;
+ result += passDoublex6Struct16BytesMixedx4Int32_a7.a1;
+ result += passDoublex6Struct16BytesMixedx4Int32_a8.a0;
+ result += passDoublex6Struct16BytesMixedx4Int32_a8.a1;
+ result += passDoublex6Struct16BytesMixedx4Int32_a9.a0;
+ result += passDoublex6Struct16BytesMixedx4Int32_a9.a1;
+ result += passDoublex6Struct16BytesMixedx4Int32_a10;
+
+ passDoublex6Struct16BytesMixedx4Int32Result = result;
+
+ return result;
+}
+
+/// On Linux x64, it will exhaust xmm registers first, after 6 doubles and 2
+/// structs. The rest of the structs will go on the stack.
+/// The int will be backfilled into the int register.
+double passDoublex6Struct16BytesMixedx4Int32(
+ double a0,
+ double a1,
+ double a2,
+ double a3,
+ double a4,
+ double a5,
+ Struct16BytesMixed a6,
+ Struct16BytesMixed a7,
+ Struct16BytesMixed a8,
+ Struct16BytesMixed a9,
+ int a10) {
+ print(
+ "passDoublex6Struct16BytesMixedx4Int32(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9}, ${a10})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassDoublex6Struct16BytesMixedx4Int32 throwing on purpuse!");
+ }
+
+ passDoublex6Struct16BytesMixedx4Int32_a0 = a0;
+ passDoublex6Struct16BytesMixedx4Int32_a1 = a1;
+ passDoublex6Struct16BytesMixedx4Int32_a2 = a2;
+ passDoublex6Struct16BytesMixedx4Int32_a3 = a3;
+ passDoublex6Struct16BytesMixedx4Int32_a4 = a4;
+ passDoublex6Struct16BytesMixedx4Int32_a5 = a5;
+ passDoublex6Struct16BytesMixedx4Int32_a6 = a6;
+ passDoublex6Struct16BytesMixedx4Int32_a7 = a7;
+ passDoublex6Struct16BytesMixedx4Int32_a8 = a8;
+ passDoublex6Struct16BytesMixedx4Int32_a9 = a9;
+ passDoublex6Struct16BytesMixedx4Int32_a10 = a10;
+
+ final result = passDoublex6Struct16BytesMixedx4Int32CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passDoublex6Struct16BytesMixedx4Int32AfterCallback() {
+ final result = passDoublex6Struct16BytesMixedx4Int32CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(-8.0, result);
+}
+
+typedef PassInt32x4Struct16BytesMixedx4DoubleType = Double Function(
+ Int32,
+ Int32,
+ Int32,
+ Int32,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Double);
+
+// Global variables to be able to test inputs after callback returned.
+int passInt32x4Struct16BytesMixedx4Double_a0 = 0;
+int passInt32x4Struct16BytesMixedx4Double_a1 = 0;
+int passInt32x4Struct16BytesMixedx4Double_a2 = 0;
+int passInt32x4Struct16BytesMixedx4Double_a3 = 0;
+Struct16BytesMixed passInt32x4Struct16BytesMixedx4Double_a4 =
+ Struct16BytesMixed();
+Struct16BytesMixed passInt32x4Struct16BytesMixedx4Double_a5 =
+ Struct16BytesMixed();
+Struct16BytesMixed passInt32x4Struct16BytesMixedx4Double_a6 =
+ Struct16BytesMixed();
+Struct16BytesMixed passInt32x4Struct16BytesMixedx4Double_a7 =
+ Struct16BytesMixed();
+double passInt32x4Struct16BytesMixedx4Double_a8 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+double passInt32x4Struct16BytesMixedx4DoubleResult = 0.0;
+
+double passInt32x4Struct16BytesMixedx4DoubleCalculateResult() {
+ double result = 0;
+
+ result += passInt32x4Struct16BytesMixedx4Double_a0;
+ result += passInt32x4Struct16BytesMixedx4Double_a1;
+ result += passInt32x4Struct16BytesMixedx4Double_a2;
+ result += passInt32x4Struct16BytesMixedx4Double_a3;
+ result += passInt32x4Struct16BytesMixedx4Double_a4.a0;
+ result += passInt32x4Struct16BytesMixedx4Double_a4.a1;
+ result += passInt32x4Struct16BytesMixedx4Double_a5.a0;
+ result += passInt32x4Struct16BytesMixedx4Double_a5.a1;
+ result += passInt32x4Struct16BytesMixedx4Double_a6.a0;
+ result += passInt32x4Struct16BytesMixedx4Double_a6.a1;
+ result += passInt32x4Struct16BytesMixedx4Double_a7.a0;
+ result += passInt32x4Struct16BytesMixedx4Double_a7.a1;
+ result += passInt32x4Struct16BytesMixedx4Double_a8;
+
+ passInt32x4Struct16BytesMixedx4DoubleResult = result;
+
+ return result;
+}
+
+/// On Linux x64, it will exhaust int registers first.
+/// The rest of the structs will go on the stack.
+/// The double will be backfilled into the xmm register.
+double passInt32x4Struct16BytesMixedx4Double(
+ int a0,
+ int a1,
+ int a2,
+ int a3,
+ Struct16BytesMixed a4,
+ Struct16BytesMixed a5,
+ Struct16BytesMixed a6,
+ Struct16BytesMixed a7,
+ double a8) {
+ print(
+ "passInt32x4Struct16BytesMixedx4Double(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassInt32x4Struct16BytesMixedx4Double throwing on purpuse!");
+ }
+
+ passInt32x4Struct16BytesMixedx4Double_a0 = a0;
+ passInt32x4Struct16BytesMixedx4Double_a1 = a1;
+ passInt32x4Struct16BytesMixedx4Double_a2 = a2;
+ passInt32x4Struct16BytesMixedx4Double_a3 = a3;
+ passInt32x4Struct16BytesMixedx4Double_a4 = a4;
+ passInt32x4Struct16BytesMixedx4Double_a5 = a5;
+ passInt32x4Struct16BytesMixedx4Double_a6 = a6;
+ passInt32x4Struct16BytesMixedx4Double_a7 = a7;
+ passInt32x4Struct16BytesMixedx4Double_a8 = a8;
+
+ final result = passInt32x4Struct16BytesMixedx4DoubleCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passInt32x4Struct16BytesMixedx4DoubleAfterCallback() {
+ final result = passInt32x4Struct16BytesMixedx4DoubleCalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(-7.0, result);
+}
+
+typedef PassStruct40BytesHomogeneousDoubleStruct4BytesHomoType
+ = Double Function(Struct40BytesHomogeneousDouble,
+ Struct4BytesHomogeneousInt16, Struct8BytesHomogeneousFloat);
+
+// Global variables to be able to test inputs after callback returned.
+Struct40BytesHomogeneousDouble
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a0 =
+ Struct40BytesHomogeneousDouble();
+Struct4BytesHomogeneousInt16
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a1 =
+ Struct4BytesHomogeneousInt16();
+Struct8BytesHomogeneousFloat
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a2 =
+ Struct8BytesHomogeneousFloat();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct40BytesHomogeneousDoubleStruct4BytesHomoResult = 0.0;
+
+double passStruct40BytesHomogeneousDoubleStruct4BytesHomoCalculateResult() {
+ double result = 0;
+
+ result += passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a0.a0;
+ result += passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a0.a1;
+ result += passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a0.a2;
+ result += passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a0.a3;
+ result += passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a0.a4;
+ result += passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a1.a0;
+ result += passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a1.a1;
+ result += passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a2.a0;
+ result += passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a2.a1;
+
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomoResult = result;
+
+ return result;
+}
+
+/// On various architectures, first struct is allocated on stack.
+/// Check that the other two arguments are allocated on registers.
+double passStruct40BytesHomogeneousDoubleStruct4BytesHomo(
+ Struct40BytesHomogeneousDouble a0,
+ Struct4BytesHomogeneousInt16 a1,
+ Struct8BytesHomogeneousFloat a2) {
+ print(
+ "passStruct40BytesHomogeneousDoubleStruct4BytesHomo(${a0}, ${a1}, ${a2})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassStruct40BytesHomogeneousDoubleStruct4BytesHomo throwing on purpuse!");
+ }
+
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a0 = a0;
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a1 = a1;
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a2 = a2;
+
+ final result =
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomoCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct40BytesHomogeneousDoubleStruct4BytesHomoAfterCallback() {
+ final result =
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomoCalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(-5.0, result);
+}
+
+typedef PassStructAlignmentInt16Type = Int64 Function(StructAlignmentInt16);
+
+// Global variables to be able to test inputs after callback returned.
+StructAlignmentInt16 passStructAlignmentInt16_a0 = StructAlignmentInt16();
+
+// Result variable also global, so we can delete it after the callback.
+int passStructAlignmentInt16Result = 0;
+
+int passStructAlignmentInt16CalculateResult() {
+ int result = 0;
+
+ result += passStructAlignmentInt16_a0.a0;
+ result += passStructAlignmentInt16_a0.a1;
+ result += passStructAlignmentInt16_a0.a2;
+
+ passStructAlignmentInt16Result = result;
+
+ return result;
+}
+
+/// Test alignment and padding of 16 byte int within struct.
+int passStructAlignmentInt16(StructAlignmentInt16 a0) {
+ print("passStructAlignmentInt16(${a0})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStructAlignmentInt16 throwing on purpuse!");
+ }
+
+ passStructAlignmentInt16_a0 = a0;
+
+ final result = passStructAlignmentInt16CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStructAlignmentInt16AfterCallback() {
+ final result = passStructAlignmentInt16CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(-2, result);
+}
+
+typedef PassStructAlignmentInt32Type = Int64 Function(StructAlignmentInt32);
+
+// Global variables to be able to test inputs after callback returned.
+StructAlignmentInt32 passStructAlignmentInt32_a0 = StructAlignmentInt32();
+
+// Result variable also global, so we can delete it after the callback.
+int passStructAlignmentInt32Result = 0;
+
+int passStructAlignmentInt32CalculateResult() {
+ int result = 0;
+
+ result += passStructAlignmentInt32_a0.a0;
+ result += passStructAlignmentInt32_a0.a1;
+ result += passStructAlignmentInt32_a0.a2;
+
+ passStructAlignmentInt32Result = result;
+
+ return result;
+}
+
+/// Test alignment and padding of 32 byte int within struct.
+int passStructAlignmentInt32(StructAlignmentInt32 a0) {
+ print("passStructAlignmentInt32(${a0})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStructAlignmentInt32 throwing on purpuse!");
+ }
+
+ passStructAlignmentInt32_a0 = a0;
+
+ final result = passStructAlignmentInt32CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStructAlignmentInt32AfterCallback() {
+ final result = passStructAlignmentInt32CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(-2, result);
+}
+
+typedef PassStructAlignmentInt64Type = Int64 Function(StructAlignmentInt64);
+
+// Global variables to be able to test inputs after callback returned.
+StructAlignmentInt64 passStructAlignmentInt64_a0 = StructAlignmentInt64();
+
+// Result variable also global, so we can delete it after the callback.
+int passStructAlignmentInt64Result = 0;
+
+int passStructAlignmentInt64CalculateResult() {
+ int result = 0;
+
+ result += passStructAlignmentInt64_a0.a0;
+ result += passStructAlignmentInt64_a0.a1;
+ result += passStructAlignmentInt64_a0.a2;
+
+ passStructAlignmentInt64Result = result;
+
+ return result;
+}
+
+/// Test alignment and padding of 64 byte int within struct.
+int passStructAlignmentInt64(StructAlignmentInt64 a0) {
+ print("passStructAlignmentInt64(${a0})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStructAlignmentInt64 throwing on purpuse!");
+ }
+
+ passStructAlignmentInt64_a0 = a0;
+
+ final result = passStructAlignmentInt64CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStructAlignmentInt64AfterCallback() {
+ final result = passStructAlignmentInt64CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(-2, result);
+}
+
+typedef ReturnStruct1ByteIntType = Struct1ByteInt Function(Int8);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct1ByteInt_a0 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct1ByteInt returnStruct1ByteIntResult = Struct1ByteInt();
+
+Struct1ByteInt returnStruct1ByteIntCalculateResult() {
+ Struct1ByteInt result = allocate<Struct1ByteInt>().ref;
+
+ result.a0 = returnStruct1ByteInt_a0;
+
+ returnStruct1ByteIntResult = result;
+
+ return result;
+}
+
+/// Smallest struct with data.
+Struct1ByteInt returnStruct1ByteInt(int a0) {
+ print("returnStruct1ByteInt(${a0})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct1ByteInt throwing on purpuse!");
+ }
+
+ returnStruct1ByteInt_a0 = a0;
+
+ final result = returnStruct1ByteIntCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct1ByteIntAfterCallback() {
+ free(returnStruct1ByteIntResult.addressOf);
+
+ final result = returnStruct1ByteIntCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct1ByteIntResult.addressOf);
+}
+
+typedef ReturnStruct3BytesIntType = Struct3BytesInt Function(Int16, Int8);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct3BytesInt_a0 = 0;
+int returnStruct3BytesInt_a1 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct3BytesInt returnStruct3BytesIntResult = Struct3BytesInt();
+
+Struct3BytesInt returnStruct3BytesIntCalculateResult() {
+ Struct3BytesInt result = allocate<Struct3BytesInt>().ref;
+
+ result.a0 = returnStruct3BytesInt_a0;
+ result.a1 = returnStruct3BytesInt_a1;
+
+ returnStruct3BytesIntResult = result;
+
+ return result;
+}
+
+/// Smaller than word size return value on all architectures.
+Struct3BytesInt returnStruct3BytesInt(int a0, int a1) {
+ print("returnStruct3BytesInt(${a0}, ${a1})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct3BytesInt throwing on purpuse!");
+ }
+
+ returnStruct3BytesInt_a0 = a0;
+ returnStruct3BytesInt_a1 = a1;
+
+ final result = returnStruct3BytesIntCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct3BytesIntAfterCallback() {
+ free(returnStruct3BytesIntResult.addressOf);
+
+ final result = returnStruct3BytesIntCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct3BytesIntResult.addressOf);
+}
+
+typedef ReturnStruct4BytesHomogeneousInt16Type = Struct4BytesHomogeneousInt16
+ Function(Int16, Int16);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct4BytesHomogeneousInt16_a0 = 0;
+int returnStruct4BytesHomogeneousInt16_a1 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct4BytesHomogeneousInt16 returnStruct4BytesHomogeneousInt16Result =
+ Struct4BytesHomogeneousInt16();
+
+Struct4BytesHomogeneousInt16
+ returnStruct4BytesHomogeneousInt16CalculateResult() {
+ Struct4BytesHomogeneousInt16 result =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+
+ result.a0 = returnStruct4BytesHomogeneousInt16_a0;
+ result.a1 = returnStruct4BytesHomogeneousInt16_a1;
+
+ returnStruct4BytesHomogeneousInt16Result = result;
+
+ return result;
+}
+
+/// Word size return value on 32 bit architectures..
+Struct4BytesHomogeneousInt16 returnStruct4BytesHomogeneousInt16(
+ int a0, int a1) {
+ print("returnStruct4BytesHomogeneousInt16(${a0}, ${a1})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct4BytesHomogeneousInt16 throwing on purpuse!");
+ }
+
+ returnStruct4BytesHomogeneousInt16_a0 = a0;
+ returnStruct4BytesHomogeneousInt16_a1 = a1;
+
+ final result = returnStruct4BytesHomogeneousInt16CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct4BytesHomogeneousInt16AfterCallback() {
+ free(returnStruct4BytesHomogeneousInt16Result.addressOf);
+
+ final result = returnStruct4BytesHomogeneousInt16CalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct4BytesHomogeneousInt16Result.addressOf);
+}
+
+typedef ReturnStruct7BytesIntType = Struct7BytesInt Function(
+ Int32, Int16, Int8);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct7BytesInt_a0 = 0;
+int returnStruct7BytesInt_a1 = 0;
+int returnStruct7BytesInt_a2 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct7BytesInt returnStruct7BytesIntResult = Struct7BytesInt();
+
+Struct7BytesInt returnStruct7BytesIntCalculateResult() {
+ Struct7BytesInt result = allocate<Struct7BytesInt>().ref;
+
+ result.a0 = returnStruct7BytesInt_a0;
+ result.a1 = returnStruct7BytesInt_a1;
+ result.a2 = returnStruct7BytesInt_a2;
+
+ returnStruct7BytesIntResult = result;
+
+ return result;
+}
+
+/// Non-wordsize return value.
+Struct7BytesInt returnStruct7BytesInt(int a0, int a1, int a2) {
+ print("returnStruct7BytesInt(${a0}, ${a1}, ${a2})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct7BytesInt throwing on purpuse!");
+ }
+
+ returnStruct7BytesInt_a0 = a0;
+ returnStruct7BytesInt_a1 = a1;
+ returnStruct7BytesInt_a2 = a2;
+
+ final result = returnStruct7BytesIntCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct7BytesIntAfterCallback() {
+ free(returnStruct7BytesIntResult.addressOf);
+
+ final result = returnStruct7BytesIntCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct7BytesIntResult.addressOf);
+}
+
+typedef ReturnStruct8BytesIntType = Struct8BytesInt Function(
+ Int16, Int16, Int32);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct8BytesInt_a0 = 0;
+int returnStruct8BytesInt_a1 = 0;
+int returnStruct8BytesInt_a2 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct8BytesInt returnStruct8BytesIntResult = Struct8BytesInt();
+
+Struct8BytesInt returnStruct8BytesIntCalculateResult() {
+ Struct8BytesInt result = allocate<Struct8BytesInt>().ref;
+
+ result.a0 = returnStruct8BytesInt_a0;
+ result.a1 = returnStruct8BytesInt_a1;
+ result.a2 = returnStruct8BytesInt_a2;
+
+ returnStruct8BytesIntResult = result;
+
+ return result;
+}
+
+/// Return value in integer registers on many architectures.
+Struct8BytesInt returnStruct8BytesInt(int a0, int a1, int a2) {
+ print("returnStruct8BytesInt(${a0}, ${a1}, ${a2})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct8BytesInt throwing on purpuse!");
+ }
+
+ returnStruct8BytesInt_a0 = a0;
+ returnStruct8BytesInt_a1 = a1;
+ returnStruct8BytesInt_a2 = a2;
+
+ final result = returnStruct8BytesIntCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct8BytesIntAfterCallback() {
+ free(returnStruct8BytesIntResult.addressOf);
+
+ final result = returnStruct8BytesIntCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct8BytesIntResult.addressOf);
+}
+
+typedef ReturnStruct8BytesHomogeneousFloatType = Struct8BytesHomogeneousFloat
+ Function(Float, Float);
+
+// Global variables to be able to test inputs after callback returned.
+double returnStruct8BytesHomogeneousFloat_a0 = 0.0;
+double returnStruct8BytesHomogeneousFloat_a1 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct8BytesHomogeneousFloat returnStruct8BytesHomogeneousFloatResult =
+ Struct8BytesHomogeneousFloat();
+
+Struct8BytesHomogeneousFloat
+ returnStruct8BytesHomogeneousFloatCalculateResult() {
+ Struct8BytesHomogeneousFloat result =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+
+ result.a0 = returnStruct8BytesHomogeneousFloat_a0;
+ result.a1 = returnStruct8BytesHomogeneousFloat_a1;
+
+ returnStruct8BytesHomogeneousFloatResult = result;
+
+ return result;
+}
+
+/// Return value in FP registers on many architectures.
+Struct8BytesHomogeneousFloat returnStruct8BytesHomogeneousFloat(
+ double a0, double a1) {
+ print("returnStruct8BytesHomogeneousFloat(${a0}, ${a1})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct8BytesHomogeneousFloat throwing on purpuse!");
+ }
+
+ returnStruct8BytesHomogeneousFloat_a0 = a0;
+ returnStruct8BytesHomogeneousFloat_a1 = a1;
+
+ final result = returnStruct8BytesHomogeneousFloatCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct8BytesHomogeneousFloatAfterCallback() {
+ free(returnStruct8BytesHomogeneousFloatResult.addressOf);
+
+ final result = returnStruct8BytesHomogeneousFloatCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct8BytesHomogeneousFloatResult.addressOf);
+}
+
+typedef ReturnStruct8BytesMixedType = Struct8BytesMixed Function(
+ Float, Int16, Int16);
+
+// Global variables to be able to test inputs after callback returned.
+double returnStruct8BytesMixed_a0 = 0.0;
+int returnStruct8BytesMixed_a1 = 0;
+int returnStruct8BytesMixed_a2 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct8BytesMixed returnStruct8BytesMixedResult = Struct8BytesMixed();
+
+Struct8BytesMixed returnStruct8BytesMixedCalculateResult() {
+ Struct8BytesMixed result = allocate<Struct8BytesMixed>().ref;
+
+ result.a0 = returnStruct8BytesMixed_a0;
+ result.a1 = returnStruct8BytesMixed_a1;
+ result.a2 = returnStruct8BytesMixed_a2;
+
+ returnStruct8BytesMixedResult = result;
+
+ return result;
+}
+
+/// Return value split over FP and integer register in x64.
+Struct8BytesMixed returnStruct8BytesMixed(double a0, int a1, int a2) {
+ print("returnStruct8BytesMixed(${a0}, ${a1}, ${a2})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct8BytesMixed throwing on purpuse!");
+ }
+
+ returnStruct8BytesMixed_a0 = a0;
+ returnStruct8BytesMixed_a1 = a1;
+ returnStruct8BytesMixed_a2 = a2;
+
+ final result = returnStruct8BytesMixedCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct8BytesMixedAfterCallback() {
+ free(returnStruct8BytesMixedResult.addressOf);
+
+ final result = returnStruct8BytesMixedCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct8BytesMixedResult.addressOf);
+}
+
+typedef ReturnStruct9BytesIntType = Struct9BytesInt Function(Int64, Int8);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct9BytesInt_a0 = 0;
+int returnStruct9BytesInt_a1 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct9BytesInt returnStruct9BytesIntResult = Struct9BytesInt();
+
+Struct9BytesInt returnStruct9BytesIntCalculateResult() {
+ Struct9BytesInt result = allocate<Struct9BytesInt>().ref;
+
+ result.a0 = returnStruct9BytesInt_a0;
+ result.a1 = returnStruct9BytesInt_a1;
+
+ returnStruct9BytesIntResult = result;
+
+ return result;
+}
+
+/// Return value in two integer registers on x64.
+/// The second register only contains a single byte.
+Struct9BytesInt returnStruct9BytesInt(int a0, int a1) {
+ print("returnStruct9BytesInt(${a0}, ${a1})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct9BytesInt throwing on purpuse!");
+ }
+
+ returnStruct9BytesInt_a0 = a0;
+ returnStruct9BytesInt_a1 = a1;
+
+ final result = returnStruct9BytesIntCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct9BytesIntAfterCallback() {
+ free(returnStruct9BytesIntResult.addressOf);
+
+ final result = returnStruct9BytesIntCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct9BytesIntResult.addressOf);
+}
+
+typedef ReturnStruct9BytesHomogeneousUint82Type = Struct9BytesHomogeneousUint82
+ Function(Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct9BytesHomogeneousUint82_a0 = 0;
+int returnStruct9BytesHomogeneousUint82_a1 = 0;
+int returnStruct9BytesHomogeneousUint82_a2 = 0;
+int returnStruct9BytesHomogeneousUint82_a3 = 0;
+int returnStruct9BytesHomogeneousUint82_a4 = 0;
+int returnStruct9BytesHomogeneousUint82_a5 = 0;
+int returnStruct9BytesHomogeneousUint82_a6 = 0;
+int returnStruct9BytesHomogeneousUint82_a7 = 0;
+int returnStruct9BytesHomogeneousUint82_a8 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct9BytesHomogeneousUint82 returnStruct9BytesHomogeneousUint82Result =
+ Struct9BytesHomogeneousUint82();
+
+Struct9BytesHomogeneousUint82
+ returnStruct9BytesHomogeneousUint82CalculateResult() {
+ Struct9BytesHomogeneousUint82 result =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+
+ result.a0 = returnStruct9BytesHomogeneousUint82_a0;
+ result.a1 = returnStruct9BytesHomogeneousUint82_a1;
+ result.a2 = returnStruct9BytesHomogeneousUint82_a2;
+ result.a3 = returnStruct9BytesHomogeneousUint82_a3;
+ result.a4 = returnStruct9BytesHomogeneousUint82_a4;
+ result.a5 = returnStruct9BytesHomogeneousUint82_a5;
+ result.a6 = returnStruct9BytesHomogeneousUint82_a6;
+ result.a7 = returnStruct9BytesHomogeneousUint82_a7;
+ result.a8 = returnStruct9BytesHomogeneousUint82_a8;
+
+ returnStruct9BytesHomogeneousUint82Result = result;
+
+ return result;
+}
+
+/// The minimum alignment of this struct is only 1 byte based on its fields.
+/// Test that the memory backing these structs is the right size and that
+/// dart:ffi trampolines do not write outside this size.
+Struct9BytesHomogeneousUint82 returnStruct9BytesHomogeneousUint82(
+ int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) {
+ print(
+ "returnStruct9BytesHomogeneousUint82(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct9BytesHomogeneousUint82 throwing on purpuse!");
+ }
+
+ returnStruct9BytesHomogeneousUint82_a0 = a0;
+ returnStruct9BytesHomogeneousUint82_a1 = a1;
+ returnStruct9BytesHomogeneousUint82_a2 = a2;
+ returnStruct9BytesHomogeneousUint82_a3 = a3;
+ returnStruct9BytesHomogeneousUint82_a4 = a4;
+ returnStruct9BytesHomogeneousUint82_a5 = a5;
+ returnStruct9BytesHomogeneousUint82_a6 = a6;
+ returnStruct9BytesHomogeneousUint82_a7 = a7;
+ returnStruct9BytesHomogeneousUint82_a8 = a8;
+
+ final result = returnStruct9BytesHomogeneousUint82CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct9BytesHomogeneousUint82AfterCallback() {
+ free(returnStruct9BytesHomogeneousUint82Result.addressOf);
+
+ final result = returnStruct9BytesHomogeneousUint82CalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct9BytesHomogeneousUint82Result.addressOf);
+}
+
+typedef ReturnStruct12BytesHomogeneousFloatType = Struct12BytesHomogeneousFloat
+ Function(Float, Float, Float);
+
+// Global variables to be able to test inputs after callback returned.
+double returnStruct12BytesHomogeneousFloat_a0 = 0.0;
+double returnStruct12BytesHomogeneousFloat_a1 = 0.0;
+double returnStruct12BytesHomogeneousFloat_a2 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct12BytesHomogeneousFloat returnStruct12BytesHomogeneousFloatResult =
+ Struct12BytesHomogeneousFloat();
+
+Struct12BytesHomogeneousFloat
+ returnStruct12BytesHomogeneousFloatCalculateResult() {
+ Struct12BytesHomogeneousFloat result =
+ allocate<Struct12BytesHomogeneousFloat>().ref;
+
+ result.a0 = returnStruct12BytesHomogeneousFloat_a0;
+ result.a1 = returnStruct12BytesHomogeneousFloat_a1;
+ result.a2 = returnStruct12BytesHomogeneousFloat_a2;
+
+ returnStruct12BytesHomogeneousFloatResult = result;
+
+ return result;
+}
+
+/// Return value in FPU registers, but does not use all registers on arm hardfp
+/// and arm64.
+Struct12BytesHomogeneousFloat returnStruct12BytesHomogeneousFloat(
+ double a0, double a1, double a2) {
+ print("returnStruct12BytesHomogeneousFloat(${a0}, ${a1}, ${a2})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct12BytesHomogeneousFloat throwing on purpuse!");
+ }
+
+ returnStruct12BytesHomogeneousFloat_a0 = a0;
+ returnStruct12BytesHomogeneousFloat_a1 = a1;
+ returnStruct12BytesHomogeneousFloat_a2 = a2;
+
+ final result = returnStruct12BytesHomogeneousFloatCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct12BytesHomogeneousFloatAfterCallback() {
+ free(returnStruct12BytesHomogeneousFloatResult.addressOf);
+
+ final result = returnStruct12BytesHomogeneousFloatCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct12BytesHomogeneousFloatResult.addressOf);
+}
+
+typedef ReturnStruct16BytesHomogeneousFloatType = Struct16BytesHomogeneousFloat
+ Function(Float, Float, Float, Float);
+
+// Global variables to be able to test inputs after callback returned.
+double returnStruct16BytesHomogeneousFloat_a0 = 0.0;
+double returnStruct16BytesHomogeneousFloat_a1 = 0.0;
+double returnStruct16BytesHomogeneousFloat_a2 = 0.0;
+double returnStruct16BytesHomogeneousFloat_a3 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct16BytesHomogeneousFloat returnStruct16BytesHomogeneousFloatResult =
+ Struct16BytesHomogeneousFloat();
+
+Struct16BytesHomogeneousFloat
+ returnStruct16BytesHomogeneousFloatCalculateResult() {
+ Struct16BytesHomogeneousFloat result =
+ allocate<Struct16BytesHomogeneousFloat>().ref;
+
+ result.a0 = returnStruct16BytesHomogeneousFloat_a0;
+ result.a1 = returnStruct16BytesHomogeneousFloat_a1;
+ result.a2 = returnStruct16BytesHomogeneousFloat_a2;
+ result.a3 = returnStruct16BytesHomogeneousFloat_a3;
+
+ returnStruct16BytesHomogeneousFloatResult = result;
+
+ return result;
+}
+
+/// Return value in FPU registers on arm hardfp and arm64.
+Struct16BytesHomogeneousFloat returnStruct16BytesHomogeneousFloat(
+ double a0, double a1, double a2, double a3) {
+ print("returnStruct16BytesHomogeneousFloat(${a0}, ${a1}, ${a2}, ${a3})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct16BytesHomogeneousFloat throwing on purpuse!");
+ }
+
+ returnStruct16BytesHomogeneousFloat_a0 = a0;
+ returnStruct16BytesHomogeneousFloat_a1 = a1;
+ returnStruct16BytesHomogeneousFloat_a2 = a2;
+ returnStruct16BytesHomogeneousFloat_a3 = a3;
+
+ final result = returnStruct16BytesHomogeneousFloatCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct16BytesHomogeneousFloatAfterCallback() {
+ free(returnStruct16BytesHomogeneousFloatResult.addressOf);
+
+ final result = returnStruct16BytesHomogeneousFloatCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct16BytesHomogeneousFloatResult.addressOf);
+}
+
+typedef ReturnStruct16BytesMixedType = Struct16BytesMixed Function(
+ Double, Int64);
+
+// Global variables to be able to test inputs after callback returned.
+double returnStruct16BytesMixed_a0 = 0.0;
+int returnStruct16BytesMixed_a1 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct16BytesMixed returnStruct16BytesMixedResult = Struct16BytesMixed();
+
+Struct16BytesMixed returnStruct16BytesMixedCalculateResult() {
+ Struct16BytesMixed result = allocate<Struct16BytesMixed>().ref;
+
+ result.a0 = returnStruct16BytesMixed_a0;
+ result.a1 = returnStruct16BytesMixed_a1;
+
+ returnStruct16BytesMixedResult = result;
+
+ return result;
+}
+
+/// Return value split over FP and integer register in x64.
+Struct16BytesMixed returnStruct16BytesMixed(double a0, int a1) {
+ print("returnStruct16BytesMixed(${a0}, ${a1})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct16BytesMixed throwing on purpuse!");
+ }
+
+ returnStruct16BytesMixed_a0 = a0;
+ returnStruct16BytesMixed_a1 = a1;
+
+ final result = returnStruct16BytesMixedCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct16BytesMixedAfterCallback() {
+ free(returnStruct16BytesMixedResult.addressOf);
+
+ final result = returnStruct16BytesMixedCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct16BytesMixedResult.addressOf);
+}
+
+typedef ReturnStruct16BytesMixed2Type = Struct16BytesMixed2 Function(
+ Float, Float, Float, Int32);
+
+// Global variables to be able to test inputs after callback returned.
+double returnStruct16BytesMixed2_a0 = 0.0;
+double returnStruct16BytesMixed2_a1 = 0.0;
+double returnStruct16BytesMixed2_a2 = 0.0;
+int returnStruct16BytesMixed2_a3 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct16BytesMixed2 returnStruct16BytesMixed2Result = Struct16BytesMixed2();
+
+Struct16BytesMixed2 returnStruct16BytesMixed2CalculateResult() {
+ Struct16BytesMixed2 result = allocate<Struct16BytesMixed2>().ref;
+
+ result.a0 = returnStruct16BytesMixed2_a0;
+ result.a1 = returnStruct16BytesMixed2_a1;
+ result.a2 = returnStruct16BytesMixed2_a2;
+ result.a3 = returnStruct16BytesMixed2_a3;
+
+ returnStruct16BytesMixed2Result = result;
+
+ return result;
+}
+
+/// Return value split over FP and integer register in x64.
+/// The integer register contains half float half int.
+Struct16BytesMixed2 returnStruct16BytesMixed2(
+ double a0, double a1, double a2, int a3) {
+ print("returnStruct16BytesMixed2(${a0}, ${a1}, ${a2}, ${a3})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct16BytesMixed2 throwing on purpuse!");
+ }
+
+ returnStruct16BytesMixed2_a0 = a0;
+ returnStruct16BytesMixed2_a1 = a1;
+ returnStruct16BytesMixed2_a2 = a2;
+ returnStruct16BytesMixed2_a3 = a3;
+
+ final result = returnStruct16BytesMixed2CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct16BytesMixed2AfterCallback() {
+ free(returnStruct16BytesMixed2Result.addressOf);
+
+ final result = returnStruct16BytesMixed2CalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct16BytesMixed2Result.addressOf);
+}
+
+typedef ReturnStruct17BytesIntType = Struct17BytesInt Function(
+ Int64, Int64, Int8);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct17BytesInt_a0 = 0;
+int returnStruct17BytesInt_a1 = 0;
+int returnStruct17BytesInt_a2 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct17BytesInt returnStruct17BytesIntResult = Struct17BytesInt();
+
+Struct17BytesInt returnStruct17BytesIntCalculateResult() {
+ Struct17BytesInt result = allocate<Struct17BytesInt>().ref;
+
+ result.a0 = returnStruct17BytesInt_a0;
+ result.a1 = returnStruct17BytesInt_a1;
+ result.a2 = returnStruct17BytesInt_a2;
+
+ returnStruct17BytesIntResult = result;
+
+ return result;
+}
+
+/// Rerturn value returned in preallocated space passed by pointer on most ABIs.
+/// Is non word size on purpose, to test that structs are rounded up to word size
+/// on all ABIs.
+Struct17BytesInt returnStruct17BytesInt(int a0, int a1, int a2) {
+ print("returnStruct17BytesInt(${a0}, ${a1}, ${a2})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct17BytesInt throwing on purpuse!");
+ }
+
+ returnStruct17BytesInt_a0 = a0;
+ returnStruct17BytesInt_a1 = a1;
+ returnStruct17BytesInt_a2 = a2;
+
+ final result = returnStruct17BytesIntCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct17BytesIntAfterCallback() {
+ free(returnStruct17BytesIntResult.addressOf);
+
+ final result = returnStruct17BytesIntCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct17BytesIntResult.addressOf);
+}
+
+typedef ReturnStruct19BytesHomogeneousUint8Type
+ = Struct19BytesHomogeneousUint8 Function(
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct19BytesHomogeneousUint8_a0 = 0;
+int returnStruct19BytesHomogeneousUint8_a1 = 0;
+int returnStruct19BytesHomogeneousUint8_a2 = 0;
+int returnStruct19BytesHomogeneousUint8_a3 = 0;
+int returnStruct19BytesHomogeneousUint8_a4 = 0;
+int returnStruct19BytesHomogeneousUint8_a5 = 0;
+int returnStruct19BytesHomogeneousUint8_a6 = 0;
+int returnStruct19BytesHomogeneousUint8_a7 = 0;
+int returnStruct19BytesHomogeneousUint8_a8 = 0;
+int returnStruct19BytesHomogeneousUint8_a9 = 0;
+int returnStruct19BytesHomogeneousUint8_a10 = 0;
+int returnStruct19BytesHomogeneousUint8_a11 = 0;
+int returnStruct19BytesHomogeneousUint8_a12 = 0;
+int returnStruct19BytesHomogeneousUint8_a13 = 0;
+int returnStruct19BytesHomogeneousUint8_a14 = 0;
+int returnStruct19BytesHomogeneousUint8_a15 = 0;
+int returnStruct19BytesHomogeneousUint8_a16 = 0;
+int returnStruct19BytesHomogeneousUint8_a17 = 0;
+int returnStruct19BytesHomogeneousUint8_a18 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct19BytesHomogeneousUint8 returnStruct19BytesHomogeneousUint8Result =
+ Struct19BytesHomogeneousUint8();
+
+Struct19BytesHomogeneousUint8
+ returnStruct19BytesHomogeneousUint8CalculateResult() {
+ Struct19BytesHomogeneousUint8 result =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+
+ result.a0 = returnStruct19BytesHomogeneousUint8_a0;
+ result.a1 = returnStruct19BytesHomogeneousUint8_a1;
+ result.a2 = returnStruct19BytesHomogeneousUint8_a2;
+ result.a3 = returnStruct19BytesHomogeneousUint8_a3;
+ result.a4 = returnStruct19BytesHomogeneousUint8_a4;
+ result.a5 = returnStruct19BytesHomogeneousUint8_a5;
+ result.a6 = returnStruct19BytesHomogeneousUint8_a6;
+ result.a7 = returnStruct19BytesHomogeneousUint8_a7;
+ result.a8 = returnStruct19BytesHomogeneousUint8_a8;
+ result.a9 = returnStruct19BytesHomogeneousUint8_a9;
+ result.a10 = returnStruct19BytesHomogeneousUint8_a10;
+ result.a11 = returnStruct19BytesHomogeneousUint8_a11;
+ result.a12 = returnStruct19BytesHomogeneousUint8_a12;
+ result.a13 = returnStruct19BytesHomogeneousUint8_a13;
+ result.a14 = returnStruct19BytesHomogeneousUint8_a14;
+ result.a15 = returnStruct19BytesHomogeneousUint8_a15;
+ result.a16 = returnStruct19BytesHomogeneousUint8_a16;
+ result.a17 = returnStruct19BytesHomogeneousUint8_a17;
+ result.a18 = returnStruct19BytesHomogeneousUint8_a18;
+
+ returnStruct19BytesHomogeneousUint8Result = result;
+
+ return result;
+}
+
+/// The minimum alignment of this struct is only 1 byte based on its fields.
+/// Test that the memory backing these structs is the right size and that
+/// dart:ffi trampolines do not write outside this size.
+Struct19BytesHomogeneousUint8 returnStruct19BytesHomogeneousUint8(
+ int a0,
+ int a1,
+ int a2,
+ int a3,
+ int a4,
+ int a5,
+ int a6,
+ int a7,
+ int a8,
+ int a9,
+ int a10,
+ int a11,
+ int a12,
+ int a13,
+ int a14,
+ int a15,
+ int a16,
+ int a17,
+ int a18) {
+ print(
+ "returnStruct19BytesHomogeneousUint8(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9}, ${a10}, ${a11}, ${a12}, ${a13}, ${a14}, ${a15}, ${a16}, ${a17}, ${a18})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct19BytesHomogeneousUint8 throwing on purpuse!");
+ }
+
+ returnStruct19BytesHomogeneousUint8_a0 = a0;
+ returnStruct19BytesHomogeneousUint8_a1 = a1;
+ returnStruct19BytesHomogeneousUint8_a2 = a2;
+ returnStruct19BytesHomogeneousUint8_a3 = a3;
+ returnStruct19BytesHomogeneousUint8_a4 = a4;
+ returnStruct19BytesHomogeneousUint8_a5 = a5;
+ returnStruct19BytesHomogeneousUint8_a6 = a6;
+ returnStruct19BytesHomogeneousUint8_a7 = a7;
+ returnStruct19BytesHomogeneousUint8_a8 = a8;
+ returnStruct19BytesHomogeneousUint8_a9 = a9;
+ returnStruct19BytesHomogeneousUint8_a10 = a10;
+ returnStruct19BytesHomogeneousUint8_a11 = a11;
+ returnStruct19BytesHomogeneousUint8_a12 = a12;
+ returnStruct19BytesHomogeneousUint8_a13 = a13;
+ returnStruct19BytesHomogeneousUint8_a14 = a14;
+ returnStruct19BytesHomogeneousUint8_a15 = a15;
+ returnStruct19BytesHomogeneousUint8_a16 = a16;
+ returnStruct19BytesHomogeneousUint8_a17 = a17;
+ returnStruct19BytesHomogeneousUint8_a18 = a18;
+
+ final result = returnStruct19BytesHomogeneousUint8CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct19BytesHomogeneousUint8AfterCallback() {
+ free(returnStruct19BytesHomogeneousUint8Result.addressOf);
+
+ final result = returnStruct19BytesHomogeneousUint8CalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct19BytesHomogeneousUint8Result.addressOf);
+}
+
+typedef ReturnStruct20BytesHomogeneousInt32Type = Struct20BytesHomogeneousInt32
+ Function(Int32, Int32, Int32, Int32, Int32);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct20BytesHomogeneousInt32_a0 = 0;
+int returnStruct20BytesHomogeneousInt32_a1 = 0;
+int returnStruct20BytesHomogeneousInt32_a2 = 0;
+int returnStruct20BytesHomogeneousInt32_a3 = 0;
+int returnStruct20BytesHomogeneousInt32_a4 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct20BytesHomogeneousInt32 returnStruct20BytesHomogeneousInt32Result =
+ Struct20BytesHomogeneousInt32();
+
+Struct20BytesHomogeneousInt32
+ returnStruct20BytesHomogeneousInt32CalculateResult() {
+ Struct20BytesHomogeneousInt32 result =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+
+ result.a0 = returnStruct20BytesHomogeneousInt32_a0;
+ result.a1 = returnStruct20BytesHomogeneousInt32_a1;
+ result.a2 = returnStruct20BytesHomogeneousInt32_a2;
+ result.a3 = returnStruct20BytesHomogeneousInt32_a3;
+ result.a4 = returnStruct20BytesHomogeneousInt32_a4;
+
+ returnStruct20BytesHomogeneousInt32Result = result;
+
+ return result;
+}
+
+/// Return value too big to go in cpu registers on arm64.
+Struct20BytesHomogeneousInt32 returnStruct20BytesHomogeneousInt32(
+ int a0, int a1, int a2, int a3, int a4) {
+ print(
+ "returnStruct20BytesHomogeneousInt32(${a0}, ${a1}, ${a2}, ${a3}, ${a4})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct20BytesHomogeneousInt32 throwing on purpuse!");
+ }
+
+ returnStruct20BytesHomogeneousInt32_a0 = a0;
+ returnStruct20BytesHomogeneousInt32_a1 = a1;
+ returnStruct20BytesHomogeneousInt32_a2 = a2;
+ returnStruct20BytesHomogeneousInt32_a3 = a3;
+ returnStruct20BytesHomogeneousInt32_a4 = a4;
+
+ final result = returnStruct20BytesHomogeneousInt32CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct20BytesHomogeneousInt32AfterCallback() {
+ free(returnStruct20BytesHomogeneousInt32Result.addressOf);
+
+ final result = returnStruct20BytesHomogeneousInt32CalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct20BytesHomogeneousInt32Result.addressOf);
+}
+
+typedef ReturnStruct20BytesHomogeneousFloatType = Struct20BytesHomogeneousFloat
+ Function(Float, Float, Float, Float, Float);
+
+// Global variables to be able to test inputs after callback returned.
+double returnStruct20BytesHomogeneousFloat_a0 = 0.0;
+double returnStruct20BytesHomogeneousFloat_a1 = 0.0;
+double returnStruct20BytesHomogeneousFloat_a2 = 0.0;
+double returnStruct20BytesHomogeneousFloat_a3 = 0.0;
+double returnStruct20BytesHomogeneousFloat_a4 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct20BytesHomogeneousFloat returnStruct20BytesHomogeneousFloatResult =
+ Struct20BytesHomogeneousFloat();
+
+Struct20BytesHomogeneousFloat
+ returnStruct20BytesHomogeneousFloatCalculateResult() {
+ Struct20BytesHomogeneousFloat result =
+ allocate<Struct20BytesHomogeneousFloat>().ref;
+
+ result.a0 = returnStruct20BytesHomogeneousFloat_a0;
+ result.a1 = returnStruct20BytesHomogeneousFloat_a1;
+ result.a2 = returnStruct20BytesHomogeneousFloat_a2;
+ result.a3 = returnStruct20BytesHomogeneousFloat_a3;
+ result.a4 = returnStruct20BytesHomogeneousFloat_a4;
+
+ returnStruct20BytesHomogeneousFloatResult = result;
+
+ return result;
+}
+
+/// Return value too big to go in FPU registers on x64, arm hardfp and arm64.
+Struct20BytesHomogeneousFloat returnStruct20BytesHomogeneousFloat(
+ double a0, double a1, double a2, double a3, double a4) {
+ print(
+ "returnStruct20BytesHomogeneousFloat(${a0}, ${a1}, ${a2}, ${a3}, ${a4})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct20BytesHomogeneousFloat throwing on purpuse!");
+ }
+
+ returnStruct20BytesHomogeneousFloat_a0 = a0;
+ returnStruct20BytesHomogeneousFloat_a1 = a1;
+ returnStruct20BytesHomogeneousFloat_a2 = a2;
+ returnStruct20BytesHomogeneousFloat_a3 = a3;
+ returnStruct20BytesHomogeneousFloat_a4 = a4;
+
+ final result = returnStruct20BytesHomogeneousFloatCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct20BytesHomogeneousFloatAfterCallback() {
+ free(returnStruct20BytesHomogeneousFloatResult.addressOf);
+
+ final result = returnStruct20BytesHomogeneousFloatCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct20BytesHomogeneousFloatResult.addressOf);
+}
+
+typedef ReturnStruct32BytesHomogeneousDoubleType
+ = Struct32BytesHomogeneousDouble Function(Double, Double, Double, Double);
+
+// Global variables to be able to test inputs after callback returned.
+double returnStruct32BytesHomogeneousDouble_a0 = 0.0;
+double returnStruct32BytesHomogeneousDouble_a1 = 0.0;
+double returnStruct32BytesHomogeneousDouble_a2 = 0.0;
+double returnStruct32BytesHomogeneousDouble_a3 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct32BytesHomogeneousDouble returnStruct32BytesHomogeneousDoubleResult =
+ Struct32BytesHomogeneousDouble();
+
+Struct32BytesHomogeneousDouble
+ returnStruct32BytesHomogeneousDoubleCalculateResult() {
+ Struct32BytesHomogeneousDouble result =
+ allocate<Struct32BytesHomogeneousDouble>().ref;
+
+ result.a0 = returnStruct32BytesHomogeneousDouble_a0;
+ result.a1 = returnStruct32BytesHomogeneousDouble_a1;
+ result.a2 = returnStruct32BytesHomogeneousDouble_a2;
+ result.a3 = returnStruct32BytesHomogeneousDouble_a3;
+
+ returnStruct32BytesHomogeneousDoubleResult = result;
+
+ return result;
+}
+
+/// Return value in FPU registers on arm64.
+Struct32BytesHomogeneousDouble returnStruct32BytesHomogeneousDouble(
+ double a0, double a1, double a2, double a3) {
+ print("returnStruct32BytesHomogeneousDouble(${a0}, ${a1}, ${a2}, ${a3})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "ReturnStruct32BytesHomogeneousDouble throwing on purpuse!");
+ }
+
+ returnStruct32BytesHomogeneousDouble_a0 = a0;
+ returnStruct32BytesHomogeneousDouble_a1 = a1;
+ returnStruct32BytesHomogeneousDouble_a2 = a2;
+ returnStruct32BytesHomogeneousDouble_a3 = a3;
+
+ final result = returnStruct32BytesHomogeneousDoubleCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct32BytesHomogeneousDoubleAfterCallback() {
+ free(returnStruct32BytesHomogeneousDoubleResult.addressOf);
+
+ final result = returnStruct32BytesHomogeneousDoubleCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct32BytesHomogeneousDoubleResult.addressOf);
+}
+
+typedef ReturnStruct40BytesHomogeneousDoubleType
+ = Struct40BytesHomogeneousDouble Function(
+ Double, Double, Double, Double, Double);
+
+// Global variables to be able to test inputs after callback returned.
+double returnStruct40BytesHomogeneousDouble_a0 = 0.0;
+double returnStruct40BytesHomogeneousDouble_a1 = 0.0;
+double returnStruct40BytesHomogeneousDouble_a2 = 0.0;
+double returnStruct40BytesHomogeneousDouble_a3 = 0.0;
+double returnStruct40BytesHomogeneousDouble_a4 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct40BytesHomogeneousDouble returnStruct40BytesHomogeneousDoubleResult =
+ Struct40BytesHomogeneousDouble();
+
+Struct40BytesHomogeneousDouble
+ returnStruct40BytesHomogeneousDoubleCalculateResult() {
+ Struct40BytesHomogeneousDouble result =
+ allocate<Struct40BytesHomogeneousDouble>().ref;
+
+ result.a0 = returnStruct40BytesHomogeneousDouble_a0;
+ result.a1 = returnStruct40BytesHomogeneousDouble_a1;
+ result.a2 = returnStruct40BytesHomogeneousDouble_a2;
+ result.a3 = returnStruct40BytesHomogeneousDouble_a3;
+ result.a4 = returnStruct40BytesHomogeneousDouble_a4;
+
+ returnStruct40BytesHomogeneousDoubleResult = result;
+
+ return result;
+}
+
+/// Return value too big to go in FPU registers on arm64.
+Struct40BytesHomogeneousDouble returnStruct40BytesHomogeneousDouble(
+ double a0, double a1, double a2, double a3, double a4) {
+ print(
+ "returnStruct40BytesHomogeneousDouble(${a0}, ${a1}, ${a2}, ${a3}, ${a4})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "ReturnStruct40BytesHomogeneousDouble throwing on purpuse!");
+ }
+
+ returnStruct40BytesHomogeneousDouble_a0 = a0;
+ returnStruct40BytesHomogeneousDouble_a1 = a1;
+ returnStruct40BytesHomogeneousDouble_a2 = a2;
+ returnStruct40BytesHomogeneousDouble_a3 = a3;
+ returnStruct40BytesHomogeneousDouble_a4 = a4;
+
+ final result = returnStruct40BytesHomogeneousDoubleCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct40BytesHomogeneousDoubleAfterCallback() {
+ free(returnStruct40BytesHomogeneousDoubleResult.addressOf);
+
+ final result = returnStruct40BytesHomogeneousDoubleCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct40BytesHomogeneousDoubleResult.addressOf);
+}
+
+typedef ReturnStruct1024BytesHomogeneousUint64Type
+ = Struct1024BytesHomogeneousUint64 Function(
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct1024BytesHomogeneousUint64_a0 = 0;
+int returnStruct1024BytesHomogeneousUint64_a1 = 0;
+int returnStruct1024BytesHomogeneousUint64_a2 = 0;
+int returnStruct1024BytesHomogeneousUint64_a3 = 0;
+int returnStruct1024BytesHomogeneousUint64_a4 = 0;
+int returnStruct1024BytesHomogeneousUint64_a5 = 0;
+int returnStruct1024BytesHomogeneousUint64_a6 = 0;
+int returnStruct1024BytesHomogeneousUint64_a7 = 0;
+int returnStruct1024BytesHomogeneousUint64_a8 = 0;
+int returnStruct1024BytesHomogeneousUint64_a9 = 0;
+int returnStruct1024BytesHomogeneousUint64_a10 = 0;
+int returnStruct1024BytesHomogeneousUint64_a11 = 0;
+int returnStruct1024BytesHomogeneousUint64_a12 = 0;
+int returnStruct1024BytesHomogeneousUint64_a13 = 0;
+int returnStruct1024BytesHomogeneousUint64_a14 = 0;
+int returnStruct1024BytesHomogeneousUint64_a15 = 0;
+int returnStruct1024BytesHomogeneousUint64_a16 = 0;
+int returnStruct1024BytesHomogeneousUint64_a17 = 0;
+int returnStruct1024BytesHomogeneousUint64_a18 = 0;
+int returnStruct1024BytesHomogeneousUint64_a19 = 0;
+int returnStruct1024BytesHomogeneousUint64_a20 = 0;
+int returnStruct1024BytesHomogeneousUint64_a21 = 0;
+int returnStruct1024BytesHomogeneousUint64_a22 = 0;
+int returnStruct1024BytesHomogeneousUint64_a23 = 0;
+int returnStruct1024BytesHomogeneousUint64_a24 = 0;
+int returnStruct1024BytesHomogeneousUint64_a25 = 0;
+int returnStruct1024BytesHomogeneousUint64_a26 = 0;
+int returnStruct1024BytesHomogeneousUint64_a27 = 0;
+int returnStruct1024BytesHomogeneousUint64_a28 = 0;
+int returnStruct1024BytesHomogeneousUint64_a29 = 0;
+int returnStruct1024BytesHomogeneousUint64_a30 = 0;
+int returnStruct1024BytesHomogeneousUint64_a31 = 0;
+int returnStruct1024BytesHomogeneousUint64_a32 = 0;
+int returnStruct1024BytesHomogeneousUint64_a33 = 0;
+int returnStruct1024BytesHomogeneousUint64_a34 = 0;
+int returnStruct1024BytesHomogeneousUint64_a35 = 0;
+int returnStruct1024BytesHomogeneousUint64_a36 = 0;
+int returnStruct1024BytesHomogeneousUint64_a37 = 0;
+int returnStruct1024BytesHomogeneousUint64_a38 = 0;
+int returnStruct1024BytesHomogeneousUint64_a39 = 0;
+int returnStruct1024BytesHomogeneousUint64_a40 = 0;
+int returnStruct1024BytesHomogeneousUint64_a41 = 0;
+int returnStruct1024BytesHomogeneousUint64_a42 = 0;
+int returnStruct1024BytesHomogeneousUint64_a43 = 0;
+int returnStruct1024BytesHomogeneousUint64_a44 = 0;
+int returnStruct1024BytesHomogeneousUint64_a45 = 0;
+int returnStruct1024BytesHomogeneousUint64_a46 = 0;
+int returnStruct1024BytesHomogeneousUint64_a47 = 0;
+int returnStruct1024BytesHomogeneousUint64_a48 = 0;
+int returnStruct1024BytesHomogeneousUint64_a49 = 0;
+int returnStruct1024BytesHomogeneousUint64_a50 = 0;
+int returnStruct1024BytesHomogeneousUint64_a51 = 0;
+int returnStruct1024BytesHomogeneousUint64_a52 = 0;
+int returnStruct1024BytesHomogeneousUint64_a53 = 0;
+int returnStruct1024BytesHomogeneousUint64_a54 = 0;
+int returnStruct1024BytesHomogeneousUint64_a55 = 0;
+int returnStruct1024BytesHomogeneousUint64_a56 = 0;
+int returnStruct1024BytesHomogeneousUint64_a57 = 0;
+int returnStruct1024BytesHomogeneousUint64_a58 = 0;
+int returnStruct1024BytesHomogeneousUint64_a59 = 0;
+int returnStruct1024BytesHomogeneousUint64_a60 = 0;
+int returnStruct1024BytesHomogeneousUint64_a61 = 0;
+int returnStruct1024BytesHomogeneousUint64_a62 = 0;
+int returnStruct1024BytesHomogeneousUint64_a63 = 0;
+int returnStruct1024BytesHomogeneousUint64_a64 = 0;
+int returnStruct1024BytesHomogeneousUint64_a65 = 0;
+int returnStruct1024BytesHomogeneousUint64_a66 = 0;
+int returnStruct1024BytesHomogeneousUint64_a67 = 0;
+int returnStruct1024BytesHomogeneousUint64_a68 = 0;
+int returnStruct1024BytesHomogeneousUint64_a69 = 0;
+int returnStruct1024BytesHomogeneousUint64_a70 = 0;
+int returnStruct1024BytesHomogeneousUint64_a71 = 0;
+int returnStruct1024BytesHomogeneousUint64_a72 = 0;
+int returnStruct1024BytesHomogeneousUint64_a73 = 0;
+int returnStruct1024BytesHomogeneousUint64_a74 = 0;
+int returnStruct1024BytesHomogeneousUint64_a75 = 0;
+int returnStruct1024BytesHomogeneousUint64_a76 = 0;
+int returnStruct1024BytesHomogeneousUint64_a77 = 0;
+int returnStruct1024BytesHomogeneousUint64_a78 = 0;
+int returnStruct1024BytesHomogeneousUint64_a79 = 0;
+int returnStruct1024BytesHomogeneousUint64_a80 = 0;
+int returnStruct1024BytesHomogeneousUint64_a81 = 0;
+int returnStruct1024BytesHomogeneousUint64_a82 = 0;
+int returnStruct1024BytesHomogeneousUint64_a83 = 0;
+int returnStruct1024BytesHomogeneousUint64_a84 = 0;
+int returnStruct1024BytesHomogeneousUint64_a85 = 0;
+int returnStruct1024BytesHomogeneousUint64_a86 = 0;
+int returnStruct1024BytesHomogeneousUint64_a87 = 0;
+int returnStruct1024BytesHomogeneousUint64_a88 = 0;
+int returnStruct1024BytesHomogeneousUint64_a89 = 0;
+int returnStruct1024BytesHomogeneousUint64_a90 = 0;
+int returnStruct1024BytesHomogeneousUint64_a91 = 0;
+int returnStruct1024BytesHomogeneousUint64_a92 = 0;
+int returnStruct1024BytesHomogeneousUint64_a93 = 0;
+int returnStruct1024BytesHomogeneousUint64_a94 = 0;
+int returnStruct1024BytesHomogeneousUint64_a95 = 0;
+int returnStruct1024BytesHomogeneousUint64_a96 = 0;
+int returnStruct1024BytesHomogeneousUint64_a97 = 0;
+int returnStruct1024BytesHomogeneousUint64_a98 = 0;
+int returnStruct1024BytesHomogeneousUint64_a99 = 0;
+int returnStruct1024BytesHomogeneousUint64_a100 = 0;
+int returnStruct1024BytesHomogeneousUint64_a101 = 0;
+int returnStruct1024BytesHomogeneousUint64_a102 = 0;
+int returnStruct1024BytesHomogeneousUint64_a103 = 0;
+int returnStruct1024BytesHomogeneousUint64_a104 = 0;
+int returnStruct1024BytesHomogeneousUint64_a105 = 0;
+int returnStruct1024BytesHomogeneousUint64_a106 = 0;
+int returnStruct1024BytesHomogeneousUint64_a107 = 0;
+int returnStruct1024BytesHomogeneousUint64_a108 = 0;
+int returnStruct1024BytesHomogeneousUint64_a109 = 0;
+int returnStruct1024BytesHomogeneousUint64_a110 = 0;
+int returnStruct1024BytesHomogeneousUint64_a111 = 0;
+int returnStruct1024BytesHomogeneousUint64_a112 = 0;
+int returnStruct1024BytesHomogeneousUint64_a113 = 0;
+int returnStruct1024BytesHomogeneousUint64_a114 = 0;
+int returnStruct1024BytesHomogeneousUint64_a115 = 0;
+int returnStruct1024BytesHomogeneousUint64_a116 = 0;
+int returnStruct1024BytesHomogeneousUint64_a117 = 0;
+int returnStruct1024BytesHomogeneousUint64_a118 = 0;
+int returnStruct1024BytesHomogeneousUint64_a119 = 0;
+int returnStruct1024BytesHomogeneousUint64_a120 = 0;
+int returnStruct1024BytesHomogeneousUint64_a121 = 0;
+int returnStruct1024BytesHomogeneousUint64_a122 = 0;
+int returnStruct1024BytesHomogeneousUint64_a123 = 0;
+int returnStruct1024BytesHomogeneousUint64_a124 = 0;
+int returnStruct1024BytesHomogeneousUint64_a125 = 0;
+int returnStruct1024BytesHomogeneousUint64_a126 = 0;
+int returnStruct1024BytesHomogeneousUint64_a127 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct1024BytesHomogeneousUint64 returnStruct1024BytesHomogeneousUint64Result =
+ Struct1024BytesHomogeneousUint64();
+
+Struct1024BytesHomogeneousUint64
+ returnStruct1024BytesHomogeneousUint64CalculateResult() {
+ Struct1024BytesHomogeneousUint64 result =
+ allocate<Struct1024BytesHomogeneousUint64>().ref;
+
+ result.a0 = returnStruct1024BytesHomogeneousUint64_a0;
+ result.a1 = returnStruct1024BytesHomogeneousUint64_a1;
+ result.a2 = returnStruct1024BytesHomogeneousUint64_a2;
+ result.a3 = returnStruct1024BytesHomogeneousUint64_a3;
+ result.a4 = returnStruct1024BytesHomogeneousUint64_a4;
+ result.a5 = returnStruct1024BytesHomogeneousUint64_a5;
+ result.a6 = returnStruct1024BytesHomogeneousUint64_a6;
+ result.a7 = returnStruct1024BytesHomogeneousUint64_a7;
+ result.a8 = returnStruct1024BytesHomogeneousUint64_a8;
+ result.a9 = returnStruct1024BytesHomogeneousUint64_a9;
+ result.a10 = returnStruct1024BytesHomogeneousUint64_a10;
+ result.a11 = returnStruct1024BytesHomogeneousUint64_a11;
+ result.a12 = returnStruct1024BytesHomogeneousUint64_a12;
+ result.a13 = returnStruct1024BytesHomogeneousUint64_a13;
+ result.a14 = returnStruct1024BytesHomogeneousUint64_a14;
+ result.a15 = returnStruct1024BytesHomogeneousUint64_a15;
+ result.a16 = returnStruct1024BytesHomogeneousUint64_a16;
+ result.a17 = returnStruct1024BytesHomogeneousUint64_a17;
+ result.a18 = returnStruct1024BytesHomogeneousUint64_a18;
+ result.a19 = returnStruct1024BytesHomogeneousUint64_a19;
+ result.a20 = returnStruct1024BytesHomogeneousUint64_a20;
+ result.a21 = returnStruct1024BytesHomogeneousUint64_a21;
+ result.a22 = returnStruct1024BytesHomogeneousUint64_a22;
+ result.a23 = returnStruct1024BytesHomogeneousUint64_a23;
+ result.a24 = returnStruct1024BytesHomogeneousUint64_a24;
+ result.a25 = returnStruct1024BytesHomogeneousUint64_a25;
+ result.a26 = returnStruct1024BytesHomogeneousUint64_a26;
+ result.a27 = returnStruct1024BytesHomogeneousUint64_a27;
+ result.a28 = returnStruct1024BytesHomogeneousUint64_a28;
+ result.a29 = returnStruct1024BytesHomogeneousUint64_a29;
+ result.a30 = returnStruct1024BytesHomogeneousUint64_a30;
+ result.a31 = returnStruct1024BytesHomogeneousUint64_a31;
+ result.a32 = returnStruct1024BytesHomogeneousUint64_a32;
+ result.a33 = returnStruct1024BytesHomogeneousUint64_a33;
+ result.a34 = returnStruct1024BytesHomogeneousUint64_a34;
+ result.a35 = returnStruct1024BytesHomogeneousUint64_a35;
+ result.a36 = returnStruct1024BytesHomogeneousUint64_a36;
+ result.a37 = returnStruct1024BytesHomogeneousUint64_a37;
+ result.a38 = returnStruct1024BytesHomogeneousUint64_a38;
+ result.a39 = returnStruct1024BytesHomogeneousUint64_a39;
+ result.a40 = returnStruct1024BytesHomogeneousUint64_a40;
+ result.a41 = returnStruct1024BytesHomogeneousUint64_a41;
+ result.a42 = returnStruct1024BytesHomogeneousUint64_a42;
+ result.a43 = returnStruct1024BytesHomogeneousUint64_a43;
+ result.a44 = returnStruct1024BytesHomogeneousUint64_a44;
+ result.a45 = returnStruct1024BytesHomogeneousUint64_a45;
+ result.a46 = returnStruct1024BytesHomogeneousUint64_a46;
+ result.a47 = returnStruct1024BytesHomogeneousUint64_a47;
+ result.a48 = returnStruct1024BytesHomogeneousUint64_a48;
+ result.a49 = returnStruct1024BytesHomogeneousUint64_a49;
+ result.a50 = returnStruct1024BytesHomogeneousUint64_a50;
+ result.a51 = returnStruct1024BytesHomogeneousUint64_a51;
+ result.a52 = returnStruct1024BytesHomogeneousUint64_a52;
+ result.a53 = returnStruct1024BytesHomogeneousUint64_a53;
+ result.a54 = returnStruct1024BytesHomogeneousUint64_a54;
+ result.a55 = returnStruct1024BytesHomogeneousUint64_a55;
+ result.a56 = returnStruct1024BytesHomogeneousUint64_a56;
+ result.a57 = returnStruct1024BytesHomogeneousUint64_a57;
+ result.a58 = returnStruct1024BytesHomogeneousUint64_a58;
+ result.a59 = returnStruct1024BytesHomogeneousUint64_a59;
+ result.a60 = returnStruct1024BytesHomogeneousUint64_a60;
+ result.a61 = returnStruct1024BytesHomogeneousUint64_a61;
+ result.a62 = returnStruct1024BytesHomogeneousUint64_a62;
+ result.a63 = returnStruct1024BytesHomogeneousUint64_a63;
+ result.a64 = returnStruct1024BytesHomogeneousUint64_a64;
+ result.a65 = returnStruct1024BytesHomogeneousUint64_a65;
+ result.a66 = returnStruct1024BytesHomogeneousUint64_a66;
+ result.a67 = returnStruct1024BytesHomogeneousUint64_a67;
+ result.a68 = returnStruct1024BytesHomogeneousUint64_a68;
+ result.a69 = returnStruct1024BytesHomogeneousUint64_a69;
+ result.a70 = returnStruct1024BytesHomogeneousUint64_a70;
+ result.a71 = returnStruct1024BytesHomogeneousUint64_a71;
+ result.a72 = returnStruct1024BytesHomogeneousUint64_a72;
+ result.a73 = returnStruct1024BytesHomogeneousUint64_a73;
+ result.a74 = returnStruct1024BytesHomogeneousUint64_a74;
+ result.a75 = returnStruct1024BytesHomogeneousUint64_a75;
+ result.a76 = returnStruct1024BytesHomogeneousUint64_a76;
+ result.a77 = returnStruct1024BytesHomogeneousUint64_a77;
+ result.a78 = returnStruct1024BytesHomogeneousUint64_a78;
+ result.a79 = returnStruct1024BytesHomogeneousUint64_a79;
+ result.a80 = returnStruct1024BytesHomogeneousUint64_a80;
+ result.a81 = returnStruct1024BytesHomogeneousUint64_a81;
+ result.a82 = returnStruct1024BytesHomogeneousUint64_a82;
+ result.a83 = returnStruct1024BytesHomogeneousUint64_a83;
+ result.a84 = returnStruct1024BytesHomogeneousUint64_a84;
+ result.a85 = returnStruct1024BytesHomogeneousUint64_a85;
+ result.a86 = returnStruct1024BytesHomogeneousUint64_a86;
+ result.a87 = returnStruct1024BytesHomogeneousUint64_a87;
+ result.a88 = returnStruct1024BytesHomogeneousUint64_a88;
+ result.a89 = returnStruct1024BytesHomogeneousUint64_a89;
+ result.a90 = returnStruct1024BytesHomogeneousUint64_a90;
+ result.a91 = returnStruct1024BytesHomogeneousUint64_a91;
+ result.a92 = returnStruct1024BytesHomogeneousUint64_a92;
+ result.a93 = returnStruct1024BytesHomogeneousUint64_a93;
+ result.a94 = returnStruct1024BytesHomogeneousUint64_a94;
+ result.a95 = returnStruct1024BytesHomogeneousUint64_a95;
+ result.a96 = returnStruct1024BytesHomogeneousUint64_a96;
+ result.a97 = returnStruct1024BytesHomogeneousUint64_a97;
+ result.a98 = returnStruct1024BytesHomogeneousUint64_a98;
+ result.a99 = returnStruct1024BytesHomogeneousUint64_a99;
+ result.a100 = returnStruct1024BytesHomogeneousUint64_a100;
+ result.a101 = returnStruct1024BytesHomogeneousUint64_a101;
+ result.a102 = returnStruct1024BytesHomogeneousUint64_a102;
+ result.a103 = returnStruct1024BytesHomogeneousUint64_a103;
+ result.a104 = returnStruct1024BytesHomogeneousUint64_a104;
+ result.a105 = returnStruct1024BytesHomogeneousUint64_a105;
+ result.a106 = returnStruct1024BytesHomogeneousUint64_a106;
+ result.a107 = returnStruct1024BytesHomogeneousUint64_a107;
+ result.a108 = returnStruct1024BytesHomogeneousUint64_a108;
+ result.a109 = returnStruct1024BytesHomogeneousUint64_a109;
+ result.a110 = returnStruct1024BytesHomogeneousUint64_a110;
+ result.a111 = returnStruct1024BytesHomogeneousUint64_a111;
+ result.a112 = returnStruct1024BytesHomogeneousUint64_a112;
+ result.a113 = returnStruct1024BytesHomogeneousUint64_a113;
+ result.a114 = returnStruct1024BytesHomogeneousUint64_a114;
+ result.a115 = returnStruct1024BytesHomogeneousUint64_a115;
+ result.a116 = returnStruct1024BytesHomogeneousUint64_a116;
+ result.a117 = returnStruct1024BytesHomogeneousUint64_a117;
+ result.a118 = returnStruct1024BytesHomogeneousUint64_a118;
+ result.a119 = returnStruct1024BytesHomogeneousUint64_a119;
+ result.a120 = returnStruct1024BytesHomogeneousUint64_a120;
+ result.a121 = returnStruct1024BytesHomogeneousUint64_a121;
+ result.a122 = returnStruct1024BytesHomogeneousUint64_a122;
+ result.a123 = returnStruct1024BytesHomogeneousUint64_a123;
+ result.a124 = returnStruct1024BytesHomogeneousUint64_a124;
+ result.a125 = returnStruct1024BytesHomogeneousUint64_a125;
+ result.a126 = returnStruct1024BytesHomogeneousUint64_a126;
+ result.a127 = returnStruct1024BytesHomogeneousUint64_a127;
+
+ returnStruct1024BytesHomogeneousUint64Result = result;
+
+ return result;
+}
+
+/// Test 1kb struct.
+Struct1024BytesHomogeneousUint64 returnStruct1024BytesHomogeneousUint64(
+ int a0,
+ int a1,
+ int a2,
+ int a3,
+ int a4,
+ int a5,
+ int a6,
+ int a7,
+ int a8,
+ int a9,
+ int a10,
+ int a11,
+ int a12,
+ int a13,
+ int a14,
+ int a15,
+ int a16,
+ int a17,
+ int a18,
+ int a19,
+ int a20,
+ int a21,
+ int a22,
+ int a23,
+ int a24,
+ int a25,
+ int a26,
+ int a27,
+ int a28,
+ int a29,
+ int a30,
+ int a31,
+ int a32,
+ int a33,
+ int a34,
+ int a35,
+ int a36,
+ int a37,
+ int a38,
+ int a39,
+ int a40,
+ int a41,
+ int a42,
+ int a43,
+ int a44,
+ int a45,
+ int a46,
+ int a47,
+ int a48,
+ int a49,
+ int a50,
+ int a51,
+ int a52,
+ int a53,
+ int a54,
+ int a55,
+ int a56,
+ int a57,
+ int a58,
+ int a59,
+ int a60,
+ int a61,
+ int a62,
+ int a63,
+ int a64,
+ int a65,
+ int a66,
+ int a67,
+ int a68,
+ int a69,
+ int a70,
+ int a71,
+ int a72,
+ int a73,
+ int a74,
+ int a75,
+ int a76,
+ int a77,
+ int a78,
+ int a79,
+ int a80,
+ int a81,
+ int a82,
+ int a83,
+ int a84,
+ int a85,
+ int a86,
+ int a87,
+ int a88,
+ int a89,
+ int a90,
+ int a91,
+ int a92,
+ int a93,
+ int a94,
+ int a95,
+ int a96,
+ int a97,
+ int a98,
+ int a99,
+ int a100,
+ int a101,
+ int a102,
+ int a103,
+ int a104,
+ int a105,
+ int a106,
+ int a107,
+ int a108,
+ int a109,
+ int a110,
+ int a111,
+ int a112,
+ int a113,
+ int a114,
+ int a115,
+ int a116,
+ int a117,
+ int a118,
+ int a119,
+ int a120,
+ int a121,
+ int a122,
+ int a123,
+ int a124,
+ int a125,
+ int a126,
+ int a127) {
+ print(
+ "returnStruct1024BytesHomogeneousUint64(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9}, ${a10}, ${a11}, ${a12}, ${a13}, ${a14}, ${a15}, ${a16}, ${a17}, ${a18}, ${a19}, ${a20}, ${a21}, ${a22}, ${a23}, ${a24}, ${a25}, ${a26}, ${a27}, ${a28}, ${a29}, ${a30}, ${a31}, ${a32}, ${a33}, ${a34}, ${a35}, ${a36}, ${a37}, ${a38}, ${a39}, ${a40}, ${a41}, ${a42}, ${a43}, ${a44}, ${a45}, ${a46}, ${a47}, ${a48}, ${a49}, ${a50}, ${a51}, ${a52}, ${a53}, ${a54}, ${a55}, ${a56}, ${a57}, ${a58}, ${a59}, ${a60}, ${a61}, ${a62}, ${a63}, ${a64}, ${a65}, ${a66}, ${a67}, ${a68}, ${a69}, ${a70}, ${a71}, ${a72}, ${a73}, ${a74}, ${a75}, ${a76}, ${a77}, ${a78}, ${a79}, ${a80}, ${a81}, ${a82}, ${a83}, ${a84}, ${a85}, ${a86}, ${a87}, ${a88}, ${a89}, ${a90}, ${a91}, ${a92}, ${a93}, ${a94}, ${a95}, ${a96}, ${a97}, ${a98}, ${a99}, ${a100}, ${a101}, ${a102}, ${a103}, ${a104}, ${a105}, ${a106}, ${a107}, ${a108}, ${a109}, ${a110}, ${a111}, ${a112}, ${a113}, ${a114}, ${a115}, ${a116}, ${a117}, ${a118}, ${a119}, ${a120}, ${a121}, ${a122}, ${a123}, ${a124}, ${a125}, ${a126}, ${a127})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "ReturnStruct1024BytesHomogeneousUint64 throwing on purpuse!");
+ }
+
+ returnStruct1024BytesHomogeneousUint64_a0 = a0;
+ returnStruct1024BytesHomogeneousUint64_a1 = a1;
+ returnStruct1024BytesHomogeneousUint64_a2 = a2;
+ returnStruct1024BytesHomogeneousUint64_a3 = a3;
+ returnStruct1024BytesHomogeneousUint64_a4 = a4;
+ returnStruct1024BytesHomogeneousUint64_a5 = a5;
+ returnStruct1024BytesHomogeneousUint64_a6 = a6;
+ returnStruct1024BytesHomogeneousUint64_a7 = a7;
+ returnStruct1024BytesHomogeneousUint64_a8 = a8;
+ returnStruct1024BytesHomogeneousUint64_a9 = a9;
+ returnStruct1024BytesHomogeneousUint64_a10 = a10;
+ returnStruct1024BytesHomogeneousUint64_a11 = a11;
+ returnStruct1024BytesHomogeneousUint64_a12 = a12;
+ returnStruct1024BytesHomogeneousUint64_a13 = a13;
+ returnStruct1024BytesHomogeneousUint64_a14 = a14;
+ returnStruct1024BytesHomogeneousUint64_a15 = a15;
+ returnStruct1024BytesHomogeneousUint64_a16 = a16;
+ returnStruct1024BytesHomogeneousUint64_a17 = a17;
+ returnStruct1024BytesHomogeneousUint64_a18 = a18;
+ returnStruct1024BytesHomogeneousUint64_a19 = a19;
+ returnStruct1024BytesHomogeneousUint64_a20 = a20;
+ returnStruct1024BytesHomogeneousUint64_a21 = a21;
+ returnStruct1024BytesHomogeneousUint64_a22 = a22;
+ returnStruct1024BytesHomogeneousUint64_a23 = a23;
+ returnStruct1024BytesHomogeneousUint64_a24 = a24;
+ returnStruct1024BytesHomogeneousUint64_a25 = a25;
+ returnStruct1024BytesHomogeneousUint64_a26 = a26;
+ returnStruct1024BytesHomogeneousUint64_a27 = a27;
+ returnStruct1024BytesHomogeneousUint64_a28 = a28;
+ returnStruct1024BytesHomogeneousUint64_a29 = a29;
+ returnStruct1024BytesHomogeneousUint64_a30 = a30;
+ returnStruct1024BytesHomogeneousUint64_a31 = a31;
+ returnStruct1024BytesHomogeneousUint64_a32 = a32;
+ returnStruct1024BytesHomogeneousUint64_a33 = a33;
+ returnStruct1024BytesHomogeneousUint64_a34 = a34;
+ returnStruct1024BytesHomogeneousUint64_a35 = a35;
+ returnStruct1024BytesHomogeneousUint64_a36 = a36;
+ returnStruct1024BytesHomogeneousUint64_a37 = a37;
+ returnStruct1024BytesHomogeneousUint64_a38 = a38;
+ returnStruct1024BytesHomogeneousUint64_a39 = a39;
+ returnStruct1024BytesHomogeneousUint64_a40 = a40;
+ returnStruct1024BytesHomogeneousUint64_a41 = a41;
+ returnStruct1024BytesHomogeneousUint64_a42 = a42;
+ returnStruct1024BytesHomogeneousUint64_a43 = a43;
+ returnStruct1024BytesHomogeneousUint64_a44 = a44;
+ returnStruct1024BytesHomogeneousUint64_a45 = a45;
+ returnStruct1024BytesHomogeneousUint64_a46 = a46;
+ returnStruct1024BytesHomogeneousUint64_a47 = a47;
+ returnStruct1024BytesHomogeneousUint64_a48 = a48;
+ returnStruct1024BytesHomogeneousUint64_a49 = a49;
+ returnStruct1024BytesHomogeneousUint64_a50 = a50;
+ returnStruct1024BytesHomogeneousUint64_a51 = a51;
+ returnStruct1024BytesHomogeneousUint64_a52 = a52;
+ returnStruct1024BytesHomogeneousUint64_a53 = a53;
+ returnStruct1024BytesHomogeneousUint64_a54 = a54;
+ returnStruct1024BytesHomogeneousUint64_a55 = a55;
+ returnStruct1024BytesHomogeneousUint64_a56 = a56;
+ returnStruct1024BytesHomogeneousUint64_a57 = a57;
+ returnStruct1024BytesHomogeneousUint64_a58 = a58;
+ returnStruct1024BytesHomogeneousUint64_a59 = a59;
+ returnStruct1024BytesHomogeneousUint64_a60 = a60;
+ returnStruct1024BytesHomogeneousUint64_a61 = a61;
+ returnStruct1024BytesHomogeneousUint64_a62 = a62;
+ returnStruct1024BytesHomogeneousUint64_a63 = a63;
+ returnStruct1024BytesHomogeneousUint64_a64 = a64;
+ returnStruct1024BytesHomogeneousUint64_a65 = a65;
+ returnStruct1024BytesHomogeneousUint64_a66 = a66;
+ returnStruct1024BytesHomogeneousUint64_a67 = a67;
+ returnStruct1024BytesHomogeneousUint64_a68 = a68;
+ returnStruct1024BytesHomogeneousUint64_a69 = a69;
+ returnStruct1024BytesHomogeneousUint64_a70 = a70;
+ returnStruct1024BytesHomogeneousUint64_a71 = a71;
+ returnStruct1024BytesHomogeneousUint64_a72 = a72;
+ returnStruct1024BytesHomogeneousUint64_a73 = a73;
+ returnStruct1024BytesHomogeneousUint64_a74 = a74;
+ returnStruct1024BytesHomogeneousUint64_a75 = a75;
+ returnStruct1024BytesHomogeneousUint64_a76 = a76;
+ returnStruct1024BytesHomogeneousUint64_a77 = a77;
+ returnStruct1024BytesHomogeneousUint64_a78 = a78;
+ returnStruct1024BytesHomogeneousUint64_a79 = a79;
+ returnStruct1024BytesHomogeneousUint64_a80 = a80;
+ returnStruct1024BytesHomogeneousUint64_a81 = a81;
+ returnStruct1024BytesHomogeneousUint64_a82 = a82;
+ returnStruct1024BytesHomogeneousUint64_a83 = a83;
+ returnStruct1024BytesHomogeneousUint64_a84 = a84;
+ returnStruct1024BytesHomogeneousUint64_a85 = a85;
+ returnStruct1024BytesHomogeneousUint64_a86 = a86;
+ returnStruct1024BytesHomogeneousUint64_a87 = a87;
+ returnStruct1024BytesHomogeneousUint64_a88 = a88;
+ returnStruct1024BytesHomogeneousUint64_a89 = a89;
+ returnStruct1024BytesHomogeneousUint64_a90 = a90;
+ returnStruct1024BytesHomogeneousUint64_a91 = a91;
+ returnStruct1024BytesHomogeneousUint64_a92 = a92;
+ returnStruct1024BytesHomogeneousUint64_a93 = a93;
+ returnStruct1024BytesHomogeneousUint64_a94 = a94;
+ returnStruct1024BytesHomogeneousUint64_a95 = a95;
+ returnStruct1024BytesHomogeneousUint64_a96 = a96;
+ returnStruct1024BytesHomogeneousUint64_a97 = a97;
+ returnStruct1024BytesHomogeneousUint64_a98 = a98;
+ returnStruct1024BytesHomogeneousUint64_a99 = a99;
+ returnStruct1024BytesHomogeneousUint64_a100 = a100;
+ returnStruct1024BytesHomogeneousUint64_a101 = a101;
+ returnStruct1024BytesHomogeneousUint64_a102 = a102;
+ returnStruct1024BytesHomogeneousUint64_a103 = a103;
+ returnStruct1024BytesHomogeneousUint64_a104 = a104;
+ returnStruct1024BytesHomogeneousUint64_a105 = a105;
+ returnStruct1024BytesHomogeneousUint64_a106 = a106;
+ returnStruct1024BytesHomogeneousUint64_a107 = a107;
+ returnStruct1024BytesHomogeneousUint64_a108 = a108;
+ returnStruct1024BytesHomogeneousUint64_a109 = a109;
+ returnStruct1024BytesHomogeneousUint64_a110 = a110;
+ returnStruct1024BytesHomogeneousUint64_a111 = a111;
+ returnStruct1024BytesHomogeneousUint64_a112 = a112;
+ returnStruct1024BytesHomogeneousUint64_a113 = a113;
+ returnStruct1024BytesHomogeneousUint64_a114 = a114;
+ returnStruct1024BytesHomogeneousUint64_a115 = a115;
+ returnStruct1024BytesHomogeneousUint64_a116 = a116;
+ returnStruct1024BytesHomogeneousUint64_a117 = a117;
+ returnStruct1024BytesHomogeneousUint64_a118 = a118;
+ returnStruct1024BytesHomogeneousUint64_a119 = a119;
+ returnStruct1024BytesHomogeneousUint64_a120 = a120;
+ returnStruct1024BytesHomogeneousUint64_a121 = a121;
+ returnStruct1024BytesHomogeneousUint64_a122 = a122;
+ returnStruct1024BytesHomogeneousUint64_a123 = a123;
+ returnStruct1024BytesHomogeneousUint64_a124 = a124;
+ returnStruct1024BytesHomogeneousUint64_a125 = a125;
+ returnStruct1024BytesHomogeneousUint64_a126 = a126;
+ returnStruct1024BytesHomogeneousUint64_a127 = a127;
+
+ final result = returnStruct1024BytesHomogeneousUint64CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct1024BytesHomogeneousUint64AfterCallback() {
+ free(returnStruct1024BytesHomogeneousUint64Result.addressOf);
+
+ final result = returnStruct1024BytesHomogeneousUint64CalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct1024BytesHomogeneousUint64Result.addressOf);
+}
+
+typedef ReturnStructArgumentStruct1ByteIntType = Struct1ByteInt Function(
+ Struct1ByteInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct1ByteInt returnStructArgumentStruct1ByteInt_a0 = Struct1ByteInt();
+
+// Result variable also global, so we can delete it after the callback.
+Struct1ByteInt returnStructArgumentStruct1ByteIntResult = Struct1ByteInt();
+
+Struct1ByteInt returnStructArgumentStruct1ByteIntCalculateResult() {
+ Struct1ByteInt result = returnStructArgumentStruct1ByteInt_a0;
+
+ returnStructArgumentStruct1ByteIntResult = result;
+
+ return result;
+}
+
+/// Test that a struct passed in as argument can be returned.
+/// Especially for ffi callbacks.
+/// Struct is passed in int registers in most ABIs.
+Struct1ByteInt returnStructArgumentStruct1ByteInt(Struct1ByteInt a0) {
+ print("returnStructArgumentStruct1ByteInt(${a0})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStructArgumentStruct1ByteInt throwing on purpuse!");
+ }
+
+ returnStructArgumentStruct1ByteInt_a0 = a0;
+
+ final result = returnStructArgumentStruct1ByteIntCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStructArgumentStruct1ByteIntAfterCallback() {
+ final result = returnStructArgumentStruct1ByteIntCalculateResult();
+
+ print("after callback result = $result");
+}
+
+typedef ReturnStructArgumentInt32x8Struct1ByteIntType = Struct1ByteInt Function(
+ Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32, Struct1ByteInt);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStructArgumentInt32x8Struct1ByteInt_a0 = 0;
+int returnStructArgumentInt32x8Struct1ByteInt_a1 = 0;
+int returnStructArgumentInt32x8Struct1ByteInt_a2 = 0;
+int returnStructArgumentInt32x8Struct1ByteInt_a3 = 0;
+int returnStructArgumentInt32x8Struct1ByteInt_a4 = 0;
+int returnStructArgumentInt32x8Struct1ByteInt_a5 = 0;
+int returnStructArgumentInt32x8Struct1ByteInt_a6 = 0;
+int returnStructArgumentInt32x8Struct1ByteInt_a7 = 0;
+Struct1ByteInt returnStructArgumentInt32x8Struct1ByteInt_a8 = Struct1ByteInt();
+
+// Result variable also global, so we can delete it after the callback.
+Struct1ByteInt returnStructArgumentInt32x8Struct1ByteIntResult =
+ Struct1ByteInt();
+
+Struct1ByteInt returnStructArgumentInt32x8Struct1ByteIntCalculateResult() {
+ Struct1ByteInt result = returnStructArgumentInt32x8Struct1ByteInt_a8;
+
+ returnStructArgumentInt32x8Struct1ByteIntResult = result;
+
+ return result;
+}
+
+/// Test that a struct passed in as argument can be returned.
+/// Especially for ffi callbacks.
+/// Struct is passed on stack on all ABIs.
+Struct1ByteInt returnStructArgumentInt32x8Struct1ByteInt(int a0, int a1, int a2,
+ int a3, int a4, int a5, int a6, int a7, Struct1ByteInt a8) {
+ print(
+ "returnStructArgumentInt32x8Struct1ByteInt(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "ReturnStructArgumentInt32x8Struct1ByteInt throwing on purpuse!");
+ }
+
+ returnStructArgumentInt32x8Struct1ByteInt_a0 = a0;
+ returnStructArgumentInt32x8Struct1ByteInt_a1 = a1;
+ returnStructArgumentInt32x8Struct1ByteInt_a2 = a2;
+ returnStructArgumentInt32x8Struct1ByteInt_a3 = a3;
+ returnStructArgumentInt32x8Struct1ByteInt_a4 = a4;
+ returnStructArgumentInt32x8Struct1ByteInt_a5 = a5;
+ returnStructArgumentInt32x8Struct1ByteInt_a6 = a6;
+ returnStructArgumentInt32x8Struct1ByteInt_a7 = a7;
+ returnStructArgumentInt32x8Struct1ByteInt_a8 = a8;
+
+ final result = returnStructArgumentInt32x8Struct1ByteIntCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStructArgumentInt32x8Struct1ByteIntAfterCallback() {
+ final result = returnStructArgumentInt32x8Struct1ByteIntCalculateResult();
+
+ print("after callback result = $result");
+}
+
+typedef ReturnStructArgumentStruct8BytesHomogeneousFloatType
+ = Struct8BytesHomogeneousFloat Function(Struct8BytesHomogeneousFloat);
+
+// Global variables to be able to test inputs after callback returned.
+Struct8BytesHomogeneousFloat
+ returnStructArgumentStruct8BytesHomogeneousFloat_a0 =
+ Struct8BytesHomogeneousFloat();
+
+// Result variable also global, so we can delete it after the callback.
+Struct8BytesHomogeneousFloat
+ returnStructArgumentStruct8BytesHomogeneousFloatResult =
+ Struct8BytesHomogeneousFloat();
+
+Struct8BytesHomogeneousFloat
+ returnStructArgumentStruct8BytesHomogeneousFloatCalculateResult() {
+ Struct8BytesHomogeneousFloat result =
+ returnStructArgumentStruct8BytesHomogeneousFloat_a0;
+
+ returnStructArgumentStruct8BytesHomogeneousFloatResult = result;
+
+ return result;
+}
+
+/// Test that a struct passed in as argument can be returned.
+/// Especially for ffi callbacks.
+/// Struct is passed in float registers in most ABIs.
+Struct8BytesHomogeneousFloat returnStructArgumentStruct8BytesHomogeneousFloat(
+ Struct8BytesHomogeneousFloat a0) {
+ print("returnStructArgumentStruct8BytesHomogeneousFloat(${a0})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "ReturnStructArgumentStruct8BytesHomogeneousFloat throwing on purpuse!");
+ }
+
+ returnStructArgumentStruct8BytesHomogeneousFloat_a0 = a0;
+
+ final result =
+ returnStructArgumentStruct8BytesHomogeneousFloatCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStructArgumentStruct8BytesHomogeneousFloatAfterCallback() {
+ final result =
+ returnStructArgumentStruct8BytesHomogeneousFloatCalculateResult();
+
+ print("after callback result = $result");
+}
+
+typedef ReturnStructArgumentStruct20BytesHomogeneousInt32Type
+ = Struct20BytesHomogeneousInt32 Function(Struct20BytesHomogeneousInt32);
+
+// Global variables to be able to test inputs after callback returned.
+Struct20BytesHomogeneousInt32
+ returnStructArgumentStruct20BytesHomogeneousInt32_a0 =
+ Struct20BytesHomogeneousInt32();
+
+// Result variable also global, so we can delete it after the callback.
+Struct20BytesHomogeneousInt32
+ returnStructArgumentStruct20BytesHomogeneousInt32Result =
+ Struct20BytesHomogeneousInt32();
+
+Struct20BytesHomogeneousInt32
+ returnStructArgumentStruct20BytesHomogeneousInt32CalculateResult() {
+ Struct20BytesHomogeneousInt32 result =
+ returnStructArgumentStruct20BytesHomogeneousInt32_a0;
+
+ returnStructArgumentStruct20BytesHomogeneousInt32Result = result;
+
+ return result;
+}
+
+/// On arm64, both argument and return value are passed in by pointer.
+Struct20BytesHomogeneousInt32 returnStructArgumentStruct20BytesHomogeneousInt32(
+ Struct20BytesHomogeneousInt32 a0) {
+ print("returnStructArgumentStruct20BytesHomogeneousInt32(${a0})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "ReturnStructArgumentStruct20BytesHomogeneousInt32 throwing on purpuse!");
+ }
+
+ returnStructArgumentStruct20BytesHomogeneousInt32_a0 = a0;
+
+ final result =
+ returnStructArgumentStruct20BytesHomogeneousInt32CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStructArgumentStruct20BytesHomogeneousInt32AfterCallback() {
+ final result =
+ returnStructArgumentStruct20BytesHomogeneousInt32CalculateResult();
+
+ print("after callback result = $result");
+}
+
+typedef ReturnStructArgumentInt32x8Struct20BytesHomogeneouType
+ = Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32, Int32,
+ Int32, Int32, Int32, Struct20BytesHomogeneousInt32);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStructArgumentInt32x8Struct20BytesHomogeneou_a0 = 0;
+int returnStructArgumentInt32x8Struct20BytesHomogeneou_a1 = 0;
+int returnStructArgumentInt32x8Struct20BytesHomogeneou_a2 = 0;
+int returnStructArgumentInt32x8Struct20BytesHomogeneou_a3 = 0;
+int returnStructArgumentInt32x8Struct20BytesHomogeneou_a4 = 0;
+int returnStructArgumentInt32x8Struct20BytesHomogeneou_a5 = 0;
+int returnStructArgumentInt32x8Struct20BytesHomogeneou_a6 = 0;
+int returnStructArgumentInt32x8Struct20BytesHomogeneou_a7 = 0;
+Struct20BytesHomogeneousInt32
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a8 =
+ Struct20BytesHomogeneousInt32();
+
+// Result variable also global, so we can delete it after the callback.
+Struct20BytesHomogeneousInt32
+ returnStructArgumentInt32x8Struct20BytesHomogeneouResult =
+ Struct20BytesHomogeneousInt32();
+
+Struct20BytesHomogeneousInt32
+ returnStructArgumentInt32x8Struct20BytesHomogeneouCalculateResult() {
+ Struct20BytesHomogeneousInt32 result =
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a8;
+
+ returnStructArgumentInt32x8Struct20BytesHomogeneouResult = result;
+
+ return result;
+}
+
+/// On arm64, both argument and return value are passed in by pointer.
+/// Ints exhaust registers, so that pointer is passed on stack.
+Struct20BytesHomogeneousInt32
+ returnStructArgumentInt32x8Struct20BytesHomogeneou(
+ int a0,
+ int a1,
+ int a2,
+ int a3,
+ int a4,
+ int a5,
+ int a6,
+ int a7,
+ Struct20BytesHomogeneousInt32 a8) {
+ print(
+ "returnStructArgumentInt32x8Struct20BytesHomogeneou(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "ReturnStructArgumentInt32x8Struct20BytesHomogeneou throwing on purpuse!");
+ }
+
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a0 = a0;
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a1 = a1;
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a2 = a2;
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a3 = a3;
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a4 = a4;
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a5 = a5;
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a6 = a6;
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a7 = a7;
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a8 = a8;
+
+ final result =
+ returnStructArgumentInt32x8Struct20BytesHomogeneouCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStructArgumentInt32x8Struct20BytesHomogeneouAfterCallback() {
+ final result =
+ returnStructArgumentInt32x8Struct20BytesHomogeneouCalculateResult();
+
+ print("after callback result = $result");
+}
+
+typedef ReturnStructAlignmentInt16Type = StructAlignmentInt16 Function(
+ Int8, Int16, Int8);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStructAlignmentInt16_a0 = 0;
+int returnStructAlignmentInt16_a1 = 0;
+int returnStructAlignmentInt16_a2 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+StructAlignmentInt16 returnStructAlignmentInt16Result = StructAlignmentInt16();
+
+StructAlignmentInt16 returnStructAlignmentInt16CalculateResult() {
+ StructAlignmentInt16 result = allocate<StructAlignmentInt16>().ref;
+
+ result.a0 = returnStructAlignmentInt16_a0;
+ result.a1 = returnStructAlignmentInt16_a1;
+ result.a2 = returnStructAlignmentInt16_a2;
+
+ returnStructAlignmentInt16Result = result;
+
+ return result;
+}
+
+/// Test alignment and padding of 16 byte int within struct.
+StructAlignmentInt16 returnStructAlignmentInt16(int a0, int a1, int a2) {
+ print("returnStructAlignmentInt16(${a0}, ${a1}, ${a2})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStructAlignmentInt16 throwing on purpuse!");
+ }
+
+ returnStructAlignmentInt16_a0 = a0;
+ returnStructAlignmentInt16_a1 = a1;
+ returnStructAlignmentInt16_a2 = a2;
+
+ final result = returnStructAlignmentInt16CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStructAlignmentInt16AfterCallback() {
+ free(returnStructAlignmentInt16Result.addressOf);
+
+ final result = returnStructAlignmentInt16CalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStructAlignmentInt16Result.addressOf);
+}
+
+typedef ReturnStructAlignmentInt32Type = StructAlignmentInt32 Function(
+ Int8, Int32, Int8);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStructAlignmentInt32_a0 = 0;
+int returnStructAlignmentInt32_a1 = 0;
+int returnStructAlignmentInt32_a2 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+StructAlignmentInt32 returnStructAlignmentInt32Result = StructAlignmentInt32();
+
+StructAlignmentInt32 returnStructAlignmentInt32CalculateResult() {
+ StructAlignmentInt32 result = allocate<StructAlignmentInt32>().ref;
+
+ result.a0 = returnStructAlignmentInt32_a0;
+ result.a1 = returnStructAlignmentInt32_a1;
+ result.a2 = returnStructAlignmentInt32_a2;
+
+ returnStructAlignmentInt32Result = result;
+
+ return result;
+}
+
+/// Test alignment and padding of 32 byte int within struct.
+StructAlignmentInt32 returnStructAlignmentInt32(int a0, int a1, int a2) {
+ print("returnStructAlignmentInt32(${a0}, ${a1}, ${a2})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStructAlignmentInt32 throwing on purpuse!");
+ }
+
+ returnStructAlignmentInt32_a0 = a0;
+ returnStructAlignmentInt32_a1 = a1;
+ returnStructAlignmentInt32_a2 = a2;
+
+ final result = returnStructAlignmentInt32CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStructAlignmentInt32AfterCallback() {
+ free(returnStructAlignmentInt32Result.addressOf);
+
+ final result = returnStructAlignmentInt32CalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStructAlignmentInt32Result.addressOf);
+}
+
+typedef ReturnStructAlignmentInt64Type = StructAlignmentInt64 Function(
+ Int8, Int64, Int8);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStructAlignmentInt64_a0 = 0;
+int returnStructAlignmentInt64_a1 = 0;
+int returnStructAlignmentInt64_a2 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+StructAlignmentInt64 returnStructAlignmentInt64Result = StructAlignmentInt64();
+
+StructAlignmentInt64 returnStructAlignmentInt64CalculateResult() {
+ StructAlignmentInt64 result = allocate<StructAlignmentInt64>().ref;
+
+ result.a0 = returnStructAlignmentInt64_a0;
+ result.a1 = returnStructAlignmentInt64_a1;
+ result.a2 = returnStructAlignmentInt64_a2;
+
+ returnStructAlignmentInt64Result = result;
+
+ return result;
+}
+
+/// Test alignment and padding of 64 byte int within struct.
+StructAlignmentInt64 returnStructAlignmentInt64(int a0, int a1, int a2) {
+ print("returnStructAlignmentInt64(${a0}, ${a1}, ${a2})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStructAlignmentInt64 throwing on purpuse!");
+ }
+
+ returnStructAlignmentInt64_a0 = a0;
+ returnStructAlignmentInt64_a1 = a1;
+ returnStructAlignmentInt64_a2 = a2;
+
+ final result = returnStructAlignmentInt64CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStructAlignmentInt64AfterCallback() {
+ free(returnStructAlignmentInt64Result.addressOf);
+
+ final result = returnStructAlignmentInt64CalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStructAlignmentInt64Result.addressOf);
+}
diff --git a/tests/ffi/function_callbacks_structs_by_value_test.dart b/tests/ffi/function_callbacks_structs_by_value_test.dart
new file mode 100644
index 0000000..98ab518
--- /dev/null
+++ b/tests/ffi/function_callbacks_structs_by_value_test.dart
@@ -0,0 +1,71 @@
+// Copyright (c) 2020, 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.
+//
+// SharedObjects=ffi_test_functions
+//
+// VMOptions=--deterministic --optimization-counter-threshold=5 --use-slow-path --stacktrace-every=100
+
+import 'dart:ffi';
+
+import "package:expect/expect.dart";
+import "package:ffi/ffi.dart";
+
+// Reuse the struct classes.
+import 'function_structs_by_value_generated_test.dart';
+
+void main() {
+ for (int i = 0; i < 10; i++) {
+ recursiveTest(10);
+ recursiveTest(11);
+ }
+}
+
+void recursiveTest(int recursionCounter) {
+ final struct = allocate<Struct20BytesHomogeneousInt32>().ref;
+ struct.a0 = 1;
+ struct.a1 = 2;
+ struct.a2 = 3;
+ struct.a3 = 4;
+ struct.a4 = 5;
+ final result = dartPassStructRecursive(recursionCounter, struct);
+ Expect.equals(struct.a0 + recursionCounter * 2, result.a0);
+ Expect.equals(struct.a1, result.a1);
+ Expect.equals(struct.a2, result.a2);
+ Expect.equals(struct.a3, result.a3);
+ Expect.equals(struct.a4, result.a4);
+ free(struct.addressOf);
+}
+
+Struct20BytesHomogeneousInt32 dartPassStructRecursive(
+ int recursionCounter, Struct20BytesHomogeneousInt32 struct) {
+ print("callbackPassStructRecurisive($recursionCounter, $struct)");
+ struct.a0++;
+ final structA0Saved = struct.a0;
+ if (recursionCounter <= 0) {
+ print("returning");
+ return struct;
+ }
+
+ final result =
+ cPassStructRecursive(recursionCounter - 1, struct, functionPointer);
+ result.a0++;
+
+ // Check struct.a0 is not modified by Dart->C call.
+ Expect.equals(structA0Saved, struct.a0);
+
+ // Check struct.a0 is not modified by C->Dart callback, if so struct.a4 == 0.
+ Expect.notEquals(0, struct.a4);
+
+ return result;
+}
+
+final functionPointer = Pointer.fromFunction<
+ Struct20BytesHomogeneousInt32 Function(
+ Int64, Struct20BytesHomogeneousInt32)>(dartPassStructRecursive);
+
+final cPassStructRecursive = ffiTestFunctions.lookupFunction<
+ Struct20BytesHomogeneousInt32 Function(Int64 recursionCounter,
+ Struct20BytesHomogeneousInt32 struct, Pointer callbackAddress),
+ Struct20BytesHomogeneousInt32 Function(int recursionCounter,
+ Struct20BytesHomogeneousInt32, Pointer)>("PassStructRecursive");
diff --git a/tests/ffi/function_structs_by_value_generated_test.dart b/tests/ffi/function_structs_by_value_generated_test.dart
new file mode 100644
index 0000000..3cbdf98
--- /dev/null
+++ b/tests/ffi/function_structs_by_value_generated_test.dart
@@ -0,0 +1,4720 @@
+// Copyright (c) 2020, 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.
+//
+// This file has been automatically generated. Please do not edit it manually.
+//
+// SharedObjects=ffi_test_functions
+// VMOptions=
+// VMOptions=--deterministic --optimization-counter-threshold=5
+// VMOptions=--use-slow-path
+// VMOptions=--use-slow-path --stacktrace-every=100
+
+import 'dart:ffi';
+
+import "package:expect/expect.dart";
+import "package:ffi/ffi.dart";
+
+import 'dylib_utils.dart';
+
+final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
+void main() {
+ for (int i = 0; i < 10; ++i) {
+ testPassStruct1ByteIntx10();
+ testPassStruct3BytesIntx10();
+ testPassStruct4BytesHomogeneousInt16x10();
+ testPassStruct7BytesIntx10();
+ testPassStruct8BytesIntx10();
+ testPassStruct8BytesHomogeneousFloatx10();
+ testPassStruct8BytesMixedx10();
+ testPassStruct9BytesIntx10();
+ testPassStruct9BytesHomogeneousUint82x10();
+ testPassStruct12BytesHomogeneousFloatx6();
+ testPassStruct16BytesHomogeneousFloatx5();
+ testPassStruct16BytesMixedx10();
+ testPassStruct16BytesMixed2x10();
+ testPassStruct17BytesIntx10();
+ testPassStruct19BytesHomogeneousUint8x10();
+ testPassStruct20BytesHomogeneousInt32x10();
+ testPassStruct20BytesHomogeneousFloat();
+ testPassStruct32BytesHomogeneousDoublex5();
+ testPassStruct40BytesHomogeneousDouble();
+ testPassStruct1024BytesHomogeneousUint64();
+ testPassFloatStruct16BytesHomogeneousFloatFloatStruct1();
+ testPassFloatStruct32BytesHomogeneousDoubleFloatStruct();
+ testPassInt8Struct16BytesMixedInt8Struct16BytesMixedIn();
+ testPassDoublex6Struct16BytesMixedx4Int32();
+ testPassInt32x4Struct16BytesMixedx4Double();
+ testPassStruct40BytesHomogeneousDoubleStruct4BytesHomo();
+ testPassStructAlignmentInt16();
+ testPassStructAlignmentInt32();
+ testPassStructAlignmentInt64();
+ testReturnStruct1ByteInt();
+ testReturnStruct3BytesInt();
+ testReturnStruct4BytesHomogeneousInt16();
+ testReturnStruct7BytesInt();
+ testReturnStruct8BytesInt();
+ testReturnStruct8BytesHomogeneousFloat();
+ testReturnStruct8BytesMixed();
+ testReturnStruct9BytesInt();
+ testReturnStruct9BytesHomogeneousUint82();
+ testReturnStruct12BytesHomogeneousFloat();
+ testReturnStruct16BytesHomogeneousFloat();
+ testReturnStruct16BytesMixed();
+ testReturnStruct16BytesMixed2();
+ testReturnStruct17BytesInt();
+ testReturnStruct19BytesHomogeneousUint8();
+ testReturnStruct20BytesHomogeneousInt32();
+ testReturnStruct20BytesHomogeneousFloat();
+ testReturnStruct32BytesHomogeneousDouble();
+ testReturnStruct40BytesHomogeneousDouble();
+ testReturnStruct1024BytesHomogeneousUint64();
+ testReturnStructArgumentStruct1ByteInt();
+ testReturnStructArgumentInt32x8Struct1ByteInt();
+ testReturnStructArgumentStruct8BytesHomogeneousFloat();
+ testReturnStructArgumentStruct20BytesHomogeneousInt32();
+ testReturnStructArgumentInt32x8Struct20BytesHomogeneou();
+ testReturnStructAlignmentInt16();
+ testReturnStructAlignmentInt32();
+ testReturnStructAlignmentInt64();
+ }
+}
+
+class Struct0Bytes extends Struct {
+ String toString() => "()";
+}
+
+class Struct1ByteInt extends Struct {
+ @Int8()
+ external int a0;
+
+ String toString() => "(${a0})";
+}
+
+class Struct3BytesInt extends Struct {
+ @Int16()
+ external int a0;
+
+ @Int8()
+ external int a1;
+
+ String toString() => "(${a0}, ${a1})";
+}
+
+class Struct4BytesHomogeneousInt16 extends Struct {
+ @Int16()
+ external int a0;
+
+ @Int16()
+ external int a1;
+
+ String toString() => "(${a0}, ${a1})";
+}
+
+class Struct7BytesInt extends Struct {
+ @Int32()
+ external int a0;
+
+ @Int16()
+ external int a1;
+
+ @Int8()
+ external int a2;
+
+ String toString() => "(${a0}, ${a1}, ${a2})";
+}
+
+class Struct8BytesInt extends Struct {
+ @Int16()
+ external int a0;
+
+ @Int16()
+ external int a1;
+
+ @Int32()
+ external int a2;
+
+ String toString() => "(${a0}, ${a1}, ${a2})";
+}
+
+class Struct8BytesHomogeneousFloat extends Struct {
+ @Float()
+ external double a0;
+
+ @Float()
+ external double a1;
+
+ String toString() => "(${a0}, ${a1})";
+}
+
+class Struct8BytesMixed extends Struct {
+ @Float()
+ external double a0;
+
+ @Int16()
+ external int a1;
+
+ @Int16()
+ external int a2;
+
+ String toString() => "(${a0}, ${a1}, ${a2})";
+}
+
+class Struct9BytesInt extends Struct {
+ @Int64()
+ external int a0;
+
+ @Int8()
+ external int a1;
+
+ String toString() => "(${a0}, ${a1})";
+}
+
+class Struct9BytesHomogeneousUint82 extends Struct {
+ @Uint8()
+ external int a0;
+
+ @Uint8()
+ external int a1;
+
+ @Uint8()
+ external int a2;
+
+ @Uint8()
+ external int a3;
+
+ @Uint8()
+ external int a4;
+
+ @Uint8()
+ external int a5;
+
+ @Uint8()
+ external int a6;
+
+ @Uint8()
+ external int a7;
+
+ @Uint8()
+ external int a8;
+
+ String toString() =>
+ "(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8})";
+}
+
+class Struct12BytesHomogeneousFloat extends Struct {
+ @Float()
+ external double a0;
+
+ @Float()
+ external double a1;
+
+ @Float()
+ external double a2;
+
+ String toString() => "(${a0}, ${a1}, ${a2})";
+}
+
+class Struct16BytesHomogeneousFloat extends Struct {
+ @Float()
+ external double a0;
+
+ @Float()
+ external double a1;
+
+ @Float()
+ external double a2;
+
+ @Float()
+ external double a3;
+
+ String toString() => "(${a0}, ${a1}, ${a2}, ${a3})";
+}
+
+class Struct16BytesMixed extends Struct {
+ @Double()
+ external double a0;
+
+ @Int64()
+ external int a1;
+
+ String toString() => "(${a0}, ${a1})";
+}
+
+class Struct16BytesMixed2 extends Struct {
+ @Float()
+ external double a0;
+
+ @Float()
+ external double a1;
+
+ @Float()
+ external double a2;
+
+ @Int32()
+ external int a3;
+
+ String toString() => "(${a0}, ${a1}, ${a2}, ${a3})";
+}
+
+class Struct17BytesInt extends Struct {
+ @Int64()
+ external int a0;
+
+ @Int64()
+ external int a1;
+
+ @Int8()
+ external int a2;
+
+ String toString() => "(${a0}, ${a1}, ${a2})";
+}
+
+class Struct19BytesHomogeneousUint8 extends Struct {
+ @Uint8()
+ external int a0;
+
+ @Uint8()
+ external int a1;
+
+ @Uint8()
+ external int a2;
+
+ @Uint8()
+ external int a3;
+
+ @Uint8()
+ external int a4;
+
+ @Uint8()
+ external int a5;
+
+ @Uint8()
+ external int a6;
+
+ @Uint8()
+ external int a7;
+
+ @Uint8()
+ external int a8;
+
+ @Uint8()
+ external int a9;
+
+ @Uint8()
+ external int a10;
+
+ @Uint8()
+ external int a11;
+
+ @Uint8()
+ external int a12;
+
+ @Uint8()
+ external int a13;
+
+ @Uint8()
+ external int a14;
+
+ @Uint8()
+ external int a15;
+
+ @Uint8()
+ external int a16;
+
+ @Uint8()
+ external int a17;
+
+ @Uint8()
+ external int a18;
+
+ String toString() =>
+ "(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9}, ${a10}, ${a11}, ${a12}, ${a13}, ${a14}, ${a15}, ${a16}, ${a17}, ${a18})";
+}
+
+class Struct20BytesHomogeneousInt32 extends Struct {
+ @Int32()
+ external int a0;
+
+ @Int32()
+ external int a1;
+
+ @Int32()
+ external int a2;
+
+ @Int32()
+ external int a3;
+
+ @Int32()
+ external int a4;
+
+ String toString() => "(${a0}, ${a1}, ${a2}, ${a3}, ${a4})";
+}
+
+class Struct20BytesHomogeneousFloat extends Struct {
+ @Float()
+ external double a0;
+
+ @Float()
+ external double a1;
+
+ @Float()
+ external double a2;
+
+ @Float()
+ external double a3;
+
+ @Float()
+ external double a4;
+
+ String toString() => "(${a0}, ${a1}, ${a2}, ${a3}, ${a4})";
+}
+
+class Struct32BytesHomogeneousDouble extends Struct {
+ @Double()
+ external double a0;
+
+ @Double()
+ external double a1;
+
+ @Double()
+ external double a2;
+
+ @Double()
+ external double a3;
+
+ String toString() => "(${a0}, ${a1}, ${a2}, ${a3})";
+}
+
+class Struct40BytesHomogeneousDouble extends Struct {
+ @Double()
+ external double a0;
+
+ @Double()
+ external double a1;
+
+ @Double()
+ external double a2;
+
+ @Double()
+ external double a3;
+
+ @Double()
+ external double a4;
+
+ String toString() => "(${a0}, ${a1}, ${a2}, ${a3}, ${a4})";
+}
+
+class Struct1024BytesHomogeneousUint64 extends Struct {
+ @Uint64()
+ external int a0;
+
+ @Uint64()
+ external int a1;
+
+ @Uint64()
+ external int a2;
+
+ @Uint64()
+ external int a3;
+
+ @Uint64()
+ external int a4;
+
+ @Uint64()
+ external int a5;
+
+ @Uint64()
+ external int a6;
+
+ @Uint64()
+ external int a7;
+
+ @Uint64()
+ external int a8;
+
+ @Uint64()
+ external int a9;
+
+ @Uint64()
+ external int a10;
+
+ @Uint64()
+ external int a11;
+
+ @Uint64()
+ external int a12;
+
+ @Uint64()
+ external int a13;
+
+ @Uint64()
+ external int a14;
+
+ @Uint64()
+ external int a15;
+
+ @Uint64()
+ external int a16;
+
+ @Uint64()
+ external int a17;
+
+ @Uint64()
+ external int a18;
+
+ @Uint64()
+ external int a19;
+
+ @Uint64()
+ external int a20;
+
+ @Uint64()
+ external int a21;
+
+ @Uint64()
+ external int a22;
+
+ @Uint64()
+ external int a23;
+
+ @Uint64()
+ external int a24;
+
+ @Uint64()
+ external int a25;
+
+ @Uint64()
+ external int a26;
+
+ @Uint64()
+ external int a27;
+
+ @Uint64()
+ external int a28;
+
+ @Uint64()
+ external int a29;
+
+ @Uint64()
+ external int a30;
+
+ @Uint64()
+ external int a31;
+
+ @Uint64()
+ external int a32;
+
+ @Uint64()
+ external int a33;
+
+ @Uint64()
+ external int a34;
+
+ @Uint64()
+ external int a35;
+
+ @Uint64()
+ external int a36;
+
+ @Uint64()
+ external int a37;
+
+ @Uint64()
+ external int a38;
+
+ @Uint64()
+ external int a39;
+
+ @Uint64()
+ external int a40;
+
+ @Uint64()
+ external int a41;
+
+ @Uint64()
+ external int a42;
+
+ @Uint64()
+ external int a43;
+
+ @Uint64()
+ external int a44;
+
+ @Uint64()
+ external int a45;
+
+ @Uint64()
+ external int a46;
+
+ @Uint64()
+ external int a47;
+
+ @Uint64()
+ external int a48;
+
+ @Uint64()
+ external int a49;
+
+ @Uint64()
+ external int a50;
+
+ @Uint64()
+ external int a51;
+
+ @Uint64()
+ external int a52;
+
+ @Uint64()
+ external int a53;
+
+ @Uint64()
+ external int a54;
+
+ @Uint64()
+ external int a55;
+
+ @Uint64()
+ external int a56;
+
+ @Uint64()
+ external int a57;
+
+ @Uint64()
+ external int a58;
+
+ @Uint64()
+ external int a59;
+
+ @Uint64()
+ external int a60;
+
+ @Uint64()
+ external int a61;
+
+ @Uint64()
+ external int a62;
+
+ @Uint64()
+ external int a63;
+
+ @Uint64()
+ external int a64;
+
+ @Uint64()
+ external int a65;
+
+ @Uint64()
+ external int a66;
+
+ @Uint64()
+ external int a67;
+
+ @Uint64()
+ external int a68;
+
+ @Uint64()
+ external int a69;
+
+ @Uint64()
+ external int a70;
+
+ @Uint64()
+ external int a71;
+
+ @Uint64()
+ external int a72;
+
+ @Uint64()
+ external int a73;
+
+ @Uint64()
+ external int a74;
+
+ @Uint64()
+ external int a75;
+
+ @Uint64()
+ external int a76;
+
+ @Uint64()
+ external int a77;
+
+ @Uint64()
+ external int a78;
+
+ @Uint64()
+ external int a79;
+
+ @Uint64()
+ external int a80;
+
+ @Uint64()
+ external int a81;
+
+ @Uint64()
+ external int a82;
+
+ @Uint64()
+ external int a83;
+
+ @Uint64()
+ external int a84;
+
+ @Uint64()
+ external int a85;
+
+ @Uint64()
+ external int a86;
+
+ @Uint64()
+ external int a87;
+
+ @Uint64()
+ external int a88;
+
+ @Uint64()
+ external int a89;
+
+ @Uint64()
+ external int a90;
+
+ @Uint64()
+ external int a91;
+
+ @Uint64()
+ external int a92;
+
+ @Uint64()
+ external int a93;
+
+ @Uint64()
+ external int a94;
+
+ @Uint64()
+ external int a95;
+
+ @Uint64()
+ external int a96;
+
+ @Uint64()
+ external int a97;
+
+ @Uint64()
+ external int a98;
+
+ @Uint64()
+ external int a99;
+
+ @Uint64()
+ external int a100;
+
+ @Uint64()
+ external int a101;
+
+ @Uint64()
+ external int a102;
+
+ @Uint64()
+ external int a103;
+
+ @Uint64()
+ external int a104;
+
+ @Uint64()
+ external int a105;
+
+ @Uint64()
+ external int a106;
+
+ @Uint64()
+ external int a107;
+
+ @Uint64()
+ external int a108;
+
+ @Uint64()
+ external int a109;
+
+ @Uint64()
+ external int a110;
+
+ @Uint64()
+ external int a111;
+
+ @Uint64()
+ external int a112;
+
+ @Uint64()
+ external int a113;
+
+ @Uint64()
+ external int a114;
+
+ @Uint64()
+ external int a115;
+
+ @Uint64()
+ external int a116;
+
+ @Uint64()
+ external int a117;
+
+ @Uint64()
+ external int a118;
+
+ @Uint64()
+ external int a119;
+
+ @Uint64()
+ external int a120;
+
+ @Uint64()
+ external int a121;
+
+ @Uint64()
+ external int a122;
+
+ @Uint64()
+ external int a123;
+
+ @Uint64()
+ external int a124;
+
+ @Uint64()
+ external int a125;
+
+ @Uint64()
+ external int a126;
+
+ @Uint64()
+ external int a127;
+
+ String toString() =>
+ "(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9}, ${a10}, ${a11}, ${a12}, ${a13}, ${a14}, ${a15}, ${a16}, ${a17}, ${a18}, ${a19}, ${a20}, ${a21}, ${a22}, ${a23}, ${a24}, ${a25}, ${a26}, ${a27}, ${a28}, ${a29}, ${a30}, ${a31}, ${a32}, ${a33}, ${a34}, ${a35}, ${a36}, ${a37}, ${a38}, ${a39}, ${a40}, ${a41}, ${a42}, ${a43}, ${a44}, ${a45}, ${a46}, ${a47}, ${a48}, ${a49}, ${a50}, ${a51}, ${a52}, ${a53}, ${a54}, ${a55}, ${a56}, ${a57}, ${a58}, ${a59}, ${a60}, ${a61}, ${a62}, ${a63}, ${a64}, ${a65}, ${a66}, ${a67}, ${a68}, ${a69}, ${a70}, ${a71}, ${a72}, ${a73}, ${a74}, ${a75}, ${a76}, ${a77}, ${a78}, ${a79}, ${a80}, ${a81}, ${a82}, ${a83}, ${a84}, ${a85}, ${a86}, ${a87}, ${a88}, ${a89}, ${a90}, ${a91}, ${a92}, ${a93}, ${a94}, ${a95}, ${a96}, ${a97}, ${a98}, ${a99}, ${a100}, ${a101}, ${a102}, ${a103}, ${a104}, ${a105}, ${a106}, ${a107}, ${a108}, ${a109}, ${a110}, ${a111}, ${a112}, ${a113}, ${a114}, ${a115}, ${a116}, ${a117}, ${a118}, ${a119}, ${a120}, ${a121}, ${a122}, ${a123}, ${a124}, ${a125}, ${a126}, ${a127})";
+}
+
+class StructAlignmentInt16 extends Struct {
+ @Int8()
+ external int a0;
+
+ @Int16()
+ external int a1;
+
+ @Int8()
+ external int a2;
+
+ String toString() => "(${a0}, ${a1}, ${a2})";
+}
+
+class StructAlignmentInt32 extends Struct {
+ @Int8()
+ external int a0;
+
+ @Int32()
+ external int a1;
+
+ @Int8()
+ external int a2;
+
+ String toString() => "(${a0}, ${a1}, ${a2})";
+}
+
+class StructAlignmentInt64 extends Struct {
+ @Int8()
+ external int a0;
+
+ @Int64()
+ external int a1;
+
+ @Int8()
+ external int a2;
+
+ String toString() => "(${a0}, ${a1}, ${a2})";
+}
+
+final passStruct1ByteIntx10 = ffiTestFunctions.lookupFunction<
+ Int64 Function(
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt),
+ int Function(
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt)>("PassStruct1ByteIntx10");
+
+/// Smallest struct with data.
+/// 10 struct arguments will exhaust available registers.
+void testPassStruct1ByteIntx10() {
+ Struct1ByteInt a0 = allocate<Struct1ByteInt>().ref;
+ Struct1ByteInt a1 = allocate<Struct1ByteInt>().ref;
+ Struct1ByteInt a2 = allocate<Struct1ByteInt>().ref;
+ Struct1ByteInt a3 = allocate<Struct1ByteInt>().ref;
+ Struct1ByteInt a4 = allocate<Struct1ByteInt>().ref;
+ Struct1ByteInt a5 = allocate<Struct1ByteInt>().ref;
+ Struct1ByteInt a6 = allocate<Struct1ByteInt>().ref;
+ Struct1ByteInt a7 = allocate<Struct1ByteInt>().ref;
+ Struct1ByteInt a8 = allocate<Struct1ByteInt>().ref;
+ Struct1ByteInt a9 = allocate<Struct1ByteInt>().ref;
+
+ a0.a0 = -1;
+ a1.a0 = 2;
+ a2.a0 = -3;
+ a3.a0 = 4;
+ a4.a0 = -5;
+ a5.a0 = 6;
+ a6.a0 = -7;
+ a7.a0 = 8;
+ a8.a0 = -9;
+ a9.a0 = 10;
+
+ final result = passStruct1ByteIntx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.equals(5, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct3BytesIntx10 = ffiTestFunctions.lookupFunction<
+ Int64 Function(
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt),
+ int Function(
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt)>("PassStruct3BytesIntx10");
+
+/// Not a multiple of word size, not a power of two.
+/// 10 struct arguments will exhaust available registers.
+void testPassStruct3BytesIntx10() {
+ Struct3BytesInt a0 = allocate<Struct3BytesInt>().ref;
+ Struct3BytesInt a1 = allocate<Struct3BytesInt>().ref;
+ Struct3BytesInt a2 = allocate<Struct3BytesInt>().ref;
+ Struct3BytesInt a3 = allocate<Struct3BytesInt>().ref;
+ Struct3BytesInt a4 = allocate<Struct3BytesInt>().ref;
+ Struct3BytesInt a5 = allocate<Struct3BytesInt>().ref;
+ Struct3BytesInt a6 = allocate<Struct3BytesInt>().ref;
+ Struct3BytesInt a7 = allocate<Struct3BytesInt>().ref;
+ Struct3BytesInt a8 = allocate<Struct3BytesInt>().ref;
+ Struct3BytesInt a9 = allocate<Struct3BytesInt>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a1.a0 = -3;
+ a1.a1 = 4;
+ a2.a0 = -5;
+ a2.a1 = 6;
+ a3.a0 = -7;
+ a3.a1 = 8;
+ a4.a0 = -9;
+ a4.a1 = 10;
+ a5.a0 = -11;
+ a5.a1 = 12;
+ a6.a0 = -13;
+ a6.a1 = 14;
+ a7.a0 = -15;
+ a7.a1 = 16;
+ a8.a0 = -17;
+ a8.a1 = 18;
+ a9.a0 = -19;
+ a9.a1 = 20;
+
+ final result = passStruct3BytesIntx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.equals(10, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct4BytesHomogeneousInt16x10 = ffiTestFunctions.lookupFunction<
+ Int64 Function(
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16),
+ int Function(
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16)>("PassStruct4BytesHomogeneousInt16x10");
+
+/// Exactly word size on 32-bit architectures.
+/// 10 struct arguments will exhaust available registers.
+void testPassStruct4BytesHomogeneousInt16x10() {
+ Struct4BytesHomogeneousInt16 a0 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+ Struct4BytesHomogeneousInt16 a1 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+ Struct4BytesHomogeneousInt16 a2 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+ Struct4BytesHomogeneousInt16 a3 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+ Struct4BytesHomogeneousInt16 a4 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+ Struct4BytesHomogeneousInt16 a5 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+ Struct4BytesHomogeneousInt16 a6 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+ Struct4BytesHomogeneousInt16 a7 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+ Struct4BytesHomogeneousInt16 a8 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+ Struct4BytesHomogeneousInt16 a9 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a1.a0 = -3;
+ a1.a1 = 4;
+ a2.a0 = -5;
+ a2.a1 = 6;
+ a3.a0 = -7;
+ a3.a1 = 8;
+ a4.a0 = -9;
+ a4.a1 = 10;
+ a5.a0 = -11;
+ a5.a1 = 12;
+ a6.a0 = -13;
+ a6.a1 = 14;
+ a7.a0 = -15;
+ a7.a1 = 16;
+ a8.a0 = -17;
+ a8.a1 = 18;
+ a9.a0 = -19;
+ a9.a1 = 20;
+
+ final result = passStruct4BytesHomogeneousInt16x10(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.equals(10, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct7BytesIntx10 = ffiTestFunctions.lookupFunction<
+ Int64 Function(
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt),
+ int Function(
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt)>("PassStruct7BytesIntx10");
+
+/// Sub word size on 64 bit architectures.
+/// 10 struct arguments will exhaust available registers.
+void testPassStruct7BytesIntx10() {
+ Struct7BytesInt a0 = allocate<Struct7BytesInt>().ref;
+ Struct7BytesInt a1 = allocate<Struct7BytesInt>().ref;
+ Struct7BytesInt a2 = allocate<Struct7BytesInt>().ref;
+ Struct7BytesInt a3 = allocate<Struct7BytesInt>().ref;
+ Struct7BytesInt a4 = allocate<Struct7BytesInt>().ref;
+ Struct7BytesInt a5 = allocate<Struct7BytesInt>().ref;
+ Struct7BytesInt a6 = allocate<Struct7BytesInt>().ref;
+ Struct7BytesInt a7 = allocate<Struct7BytesInt>().ref;
+ Struct7BytesInt a8 = allocate<Struct7BytesInt>().ref;
+ Struct7BytesInt a9 = allocate<Struct7BytesInt>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+ a1.a0 = 4;
+ a1.a1 = -5;
+ a1.a2 = 6;
+ a2.a0 = -7;
+ a2.a1 = 8;
+ a2.a2 = -9;
+ a3.a0 = 10;
+ a3.a1 = -11;
+ a3.a2 = 12;
+ a4.a0 = -13;
+ a4.a1 = 14;
+ a4.a2 = -15;
+ a5.a0 = 16;
+ a5.a1 = -17;
+ a5.a2 = 18;
+ a6.a0 = -19;
+ a6.a1 = 20;
+ a6.a2 = -21;
+ a7.a0 = 22;
+ a7.a1 = -23;
+ a7.a2 = 24;
+ a8.a0 = -25;
+ a8.a1 = 26;
+ a8.a2 = -27;
+ a9.a0 = 28;
+ a9.a1 = -29;
+ a9.a2 = 30;
+
+ final result = passStruct7BytesIntx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.equals(15, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct8BytesIntx10 = ffiTestFunctions.lookupFunction<
+ Int64 Function(
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt),
+ int Function(
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt)>("PassStruct8BytesIntx10");
+
+/// Exactly word size struct on 64bit architectures.
+/// 10 struct arguments will exhaust available registers.
+void testPassStruct8BytesIntx10() {
+ Struct8BytesInt a0 = allocate<Struct8BytesInt>().ref;
+ Struct8BytesInt a1 = allocate<Struct8BytesInt>().ref;
+ Struct8BytesInt a2 = allocate<Struct8BytesInt>().ref;
+ Struct8BytesInt a3 = allocate<Struct8BytesInt>().ref;
+ Struct8BytesInt a4 = allocate<Struct8BytesInt>().ref;
+ Struct8BytesInt a5 = allocate<Struct8BytesInt>().ref;
+ Struct8BytesInt a6 = allocate<Struct8BytesInt>().ref;
+ Struct8BytesInt a7 = allocate<Struct8BytesInt>().ref;
+ Struct8BytesInt a8 = allocate<Struct8BytesInt>().ref;
+ Struct8BytesInt a9 = allocate<Struct8BytesInt>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+ a1.a0 = 4;
+ a1.a1 = -5;
+ a1.a2 = 6;
+ a2.a0 = -7;
+ a2.a1 = 8;
+ a2.a2 = -9;
+ a3.a0 = 10;
+ a3.a1 = -11;
+ a3.a2 = 12;
+ a4.a0 = -13;
+ a4.a1 = 14;
+ a4.a2 = -15;
+ a5.a0 = 16;
+ a5.a1 = -17;
+ a5.a2 = 18;
+ a6.a0 = -19;
+ a6.a1 = 20;
+ a6.a2 = -21;
+ a7.a0 = 22;
+ a7.a1 = -23;
+ a7.a2 = 24;
+ a8.a0 = -25;
+ a8.a1 = 26;
+ a8.a2 = -27;
+ a9.a0 = 28;
+ a9.a1 = -29;
+ a9.a2 = 30;
+
+ final result = passStruct8BytesIntx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.equals(15, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct8BytesHomogeneousFloatx10 = ffiTestFunctions.lookupFunction<
+ Float Function(
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat),
+ double Function(
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat)>("PassStruct8BytesHomogeneousFloatx10");
+
+/// Arguments passed in FP registers as long as they fit.
+/// 10 struct arguments will exhaust available registers.
+void testPassStruct8BytesHomogeneousFloatx10() {
+ Struct8BytesHomogeneousFloat a0 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+ Struct8BytesHomogeneousFloat a1 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+ Struct8BytesHomogeneousFloat a2 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+ Struct8BytesHomogeneousFloat a3 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+ Struct8BytesHomogeneousFloat a4 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+ Struct8BytesHomogeneousFloat a5 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+ Struct8BytesHomogeneousFloat a6 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+ Struct8BytesHomogeneousFloat a7 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+ Struct8BytesHomogeneousFloat a8 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+ Struct8BytesHomogeneousFloat a9 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a1.a0 = -3.0;
+ a1.a1 = 4.0;
+ a2.a0 = -5.0;
+ a2.a1 = 6.0;
+ a3.a0 = -7.0;
+ a3.a1 = 8.0;
+ a4.a0 = -9.0;
+ a4.a1 = 10.0;
+ a5.a0 = -11.0;
+ a5.a1 = 12.0;
+ a6.a0 = -13.0;
+ a6.a1 = 14.0;
+ a7.a0 = -15.0;
+ a7.a1 = 16.0;
+ a8.a0 = -17.0;
+ a8.a1 = 18.0;
+ a9.a0 = -19.0;
+ a9.a1 = 20.0;
+
+ final result = passStruct8BytesHomogeneousFloatx10(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.approxEquals(10.0, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct8BytesMixedx10 = ffiTestFunctions.lookupFunction<
+ Float Function(
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed),
+ double Function(
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed)>("PassStruct8BytesMixedx10");
+
+/// On x64, arguments go in int registers because it is not only float.
+/// 10 struct arguments will exhaust available registers.
+void testPassStruct8BytesMixedx10() {
+ Struct8BytesMixed a0 = allocate<Struct8BytesMixed>().ref;
+ Struct8BytesMixed a1 = allocate<Struct8BytesMixed>().ref;
+ Struct8BytesMixed a2 = allocate<Struct8BytesMixed>().ref;
+ Struct8BytesMixed a3 = allocate<Struct8BytesMixed>().ref;
+ Struct8BytesMixed a4 = allocate<Struct8BytesMixed>().ref;
+ Struct8BytesMixed a5 = allocate<Struct8BytesMixed>().ref;
+ Struct8BytesMixed a6 = allocate<Struct8BytesMixed>().ref;
+ Struct8BytesMixed a7 = allocate<Struct8BytesMixed>().ref;
+ Struct8BytesMixed a8 = allocate<Struct8BytesMixed>().ref;
+ Struct8BytesMixed a9 = allocate<Struct8BytesMixed>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2;
+ a0.a2 = -3;
+ a1.a0 = 4.0;
+ a1.a1 = -5;
+ a1.a2 = 6;
+ a2.a0 = -7.0;
+ a2.a1 = 8;
+ a2.a2 = -9;
+ a3.a0 = 10.0;
+ a3.a1 = -11;
+ a3.a2 = 12;
+ a4.a0 = -13.0;
+ a4.a1 = 14;
+ a4.a2 = -15;
+ a5.a0 = 16.0;
+ a5.a1 = -17;
+ a5.a2 = 18;
+ a6.a0 = -19.0;
+ a6.a1 = 20;
+ a6.a2 = -21;
+ a7.a0 = 22.0;
+ a7.a1 = -23;
+ a7.a2 = 24;
+ a8.a0 = -25.0;
+ a8.a1 = 26;
+ a8.a2 = -27;
+ a9.a0 = 28.0;
+ a9.a1 = -29;
+ a9.a2 = 30;
+
+ final result =
+ passStruct8BytesMixedx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.approxEquals(15.0, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct9BytesIntx10 = ffiTestFunctions.lookupFunction<
+ Int64 Function(
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt),
+ int Function(
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt)>("PassStruct9BytesIntx10");
+
+/// Argument is a single byte over a multiple of word size.
+/// 10 struct arguments will exhaust available registers.
+/// Tests upper bytes in the integer registers that are partly filled.
+/// Tests stack alignment of non word size stack arguments.
+void testPassStruct9BytesIntx10() {
+ Struct9BytesInt a0 = allocate<Struct9BytesInt>().ref;
+ Struct9BytesInt a1 = allocate<Struct9BytesInt>().ref;
+ Struct9BytesInt a2 = allocate<Struct9BytesInt>().ref;
+ Struct9BytesInt a3 = allocate<Struct9BytesInt>().ref;
+ Struct9BytesInt a4 = allocate<Struct9BytesInt>().ref;
+ Struct9BytesInt a5 = allocate<Struct9BytesInt>().ref;
+ Struct9BytesInt a6 = allocate<Struct9BytesInt>().ref;
+ Struct9BytesInt a7 = allocate<Struct9BytesInt>().ref;
+ Struct9BytesInt a8 = allocate<Struct9BytesInt>().ref;
+ Struct9BytesInt a9 = allocate<Struct9BytesInt>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a1.a0 = -3;
+ a1.a1 = 4;
+ a2.a0 = -5;
+ a2.a1 = 6;
+ a3.a0 = -7;
+ a3.a1 = 8;
+ a4.a0 = -9;
+ a4.a1 = 10;
+ a5.a0 = -11;
+ a5.a1 = 12;
+ a6.a0 = -13;
+ a6.a1 = 14;
+ a7.a0 = -15;
+ a7.a1 = 16;
+ a8.a0 = -17;
+ a8.a1 = 18;
+ a9.a0 = -19;
+ a9.a1 = 20;
+
+ final result = passStruct9BytesIntx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.equals(10, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct9BytesHomogeneousUint82x10 = ffiTestFunctions.lookupFunction<
+ Int64 Function(
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82),
+ int Function(
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82)>("PassStruct9BytesHomogeneousUint82x10");
+
+/// Argument is a single byte over a multiple of word size.
+/// 10 struct arguments will exhaust available registers.
+/// Struct only has 1-byte aligned fields to test struct alignment itself.
+///
+void testPassStruct9BytesHomogeneousUint82x10() {
+ Struct9BytesHomogeneousUint82 a0 =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+ Struct9BytesHomogeneousUint82 a1 =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+ Struct9BytesHomogeneousUint82 a2 =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+ Struct9BytesHomogeneousUint82 a3 =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+ Struct9BytesHomogeneousUint82 a4 =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+ Struct9BytesHomogeneousUint82 a5 =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+ Struct9BytesHomogeneousUint82 a6 =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+ Struct9BytesHomogeneousUint82 a7 =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+ Struct9BytesHomogeneousUint82 a8 =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+ Struct9BytesHomogeneousUint82 a9 =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+
+ a0.a0 = 1;
+ a0.a1 = 2;
+ a0.a2 = 3;
+ a0.a3 = 4;
+ a0.a4 = 5;
+ a0.a5 = 6;
+ a0.a6 = 7;
+ a0.a7 = 8;
+ a0.a8 = 9;
+ a1.a0 = 10;
+ a1.a1 = 11;
+ a1.a2 = 12;
+ a1.a3 = 13;
+ a1.a4 = 14;
+ a1.a5 = 15;
+ a1.a6 = 16;
+ a1.a7 = 17;
+ a1.a8 = 18;
+ a2.a0 = 19;
+ a2.a1 = 20;
+ a2.a2 = 21;
+ a2.a3 = 22;
+ a2.a4 = 23;
+ a2.a5 = 24;
+ a2.a6 = 25;
+ a2.a7 = 26;
+ a2.a8 = 27;
+ a3.a0 = 28;
+ a3.a1 = 29;
+ a3.a2 = 30;
+ a3.a3 = 31;
+ a3.a4 = 32;
+ a3.a5 = 33;
+ a3.a6 = 34;
+ a3.a7 = 35;
+ a3.a8 = 36;
+ a4.a0 = 37;
+ a4.a1 = 38;
+ a4.a2 = 39;
+ a4.a3 = 40;
+ a4.a4 = 41;
+ a4.a5 = 42;
+ a4.a6 = 43;
+ a4.a7 = 44;
+ a4.a8 = 45;
+ a5.a0 = 46;
+ a5.a1 = 47;
+ a5.a2 = 48;
+ a5.a3 = 49;
+ a5.a4 = 50;
+ a5.a5 = 51;
+ a5.a6 = 52;
+ a5.a7 = 53;
+ a5.a8 = 54;
+ a6.a0 = 55;
+ a6.a1 = 56;
+ a6.a2 = 57;
+ a6.a3 = 58;
+ a6.a4 = 59;
+ a6.a5 = 60;
+ a6.a6 = 61;
+ a6.a7 = 62;
+ a6.a8 = 63;
+ a7.a0 = 64;
+ a7.a1 = 65;
+ a7.a2 = 66;
+ a7.a3 = 67;
+ a7.a4 = 68;
+ a7.a5 = 69;
+ a7.a6 = 70;
+ a7.a7 = 71;
+ a7.a8 = 72;
+ a8.a0 = 73;
+ a8.a1 = 74;
+ a8.a2 = 75;
+ a8.a3 = 76;
+ a8.a4 = 77;
+ a8.a5 = 78;
+ a8.a6 = 79;
+ a8.a7 = 80;
+ a8.a8 = 81;
+ a9.a0 = 82;
+ a9.a1 = 83;
+ a9.a2 = 84;
+ a9.a3 = 85;
+ a9.a4 = 86;
+ a9.a5 = 87;
+ a9.a6 = 88;
+ a9.a7 = 89;
+ a9.a8 = 90;
+
+ final result = passStruct9BytesHomogeneousUint82x10(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.equals(4095, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct12BytesHomogeneousFloatx6 = ffiTestFunctions.lookupFunction<
+ Float Function(
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat),
+ double Function(
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat)>("PassStruct12BytesHomogeneousFloatx6");
+
+/// Arguments in FPU registers on arm hardfp and arm64.
+/// Struct arguments will exhaust available registers, and leave some empty.
+/// The last argument is to test whether arguments are backfilled.
+void testPassStruct12BytesHomogeneousFloatx6() {
+ Struct12BytesHomogeneousFloat a0 =
+ allocate<Struct12BytesHomogeneousFloat>().ref;
+ Struct12BytesHomogeneousFloat a1 =
+ allocate<Struct12BytesHomogeneousFloat>().ref;
+ Struct12BytesHomogeneousFloat a2 =
+ allocate<Struct12BytesHomogeneousFloat>().ref;
+ Struct12BytesHomogeneousFloat a3 =
+ allocate<Struct12BytesHomogeneousFloat>().ref;
+ Struct12BytesHomogeneousFloat a4 =
+ allocate<Struct12BytesHomogeneousFloat>().ref;
+ Struct12BytesHomogeneousFloat a5 =
+ allocate<Struct12BytesHomogeneousFloat>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a0.a2 = -3.0;
+ a1.a0 = 4.0;
+ a1.a1 = -5.0;
+ a1.a2 = 6.0;
+ a2.a0 = -7.0;
+ a2.a1 = 8.0;
+ a2.a2 = -9.0;
+ a3.a0 = 10.0;
+ a3.a1 = -11.0;
+ a3.a2 = 12.0;
+ a4.a0 = -13.0;
+ a4.a1 = 14.0;
+ a4.a2 = -15.0;
+ a5.a0 = 16.0;
+ a5.a1 = -17.0;
+ a5.a2 = 18.0;
+
+ final result = passStruct12BytesHomogeneousFloatx6(a0, a1, a2, a3, a4, a5);
+
+ print("result = $result");
+
+ Expect.approxEquals(9.0, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+}
+
+final passStruct16BytesHomogeneousFloatx5 = ffiTestFunctions.lookupFunction<
+ Float Function(
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat),
+ double Function(
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat)>("PassStruct16BytesHomogeneousFloatx5");
+
+/// On Linux x64 argument is transferred on stack because it is over 16 bytes.
+/// Arguments in FPU registers on arm hardfp and arm64.
+/// 5 struct arguments will exhaust available registers.
+void testPassStruct16BytesHomogeneousFloatx5() {
+ Struct16BytesHomogeneousFloat a0 =
+ allocate<Struct16BytesHomogeneousFloat>().ref;
+ Struct16BytesHomogeneousFloat a1 =
+ allocate<Struct16BytesHomogeneousFloat>().ref;
+ Struct16BytesHomogeneousFloat a2 =
+ allocate<Struct16BytesHomogeneousFloat>().ref;
+ Struct16BytesHomogeneousFloat a3 =
+ allocate<Struct16BytesHomogeneousFloat>().ref;
+ Struct16BytesHomogeneousFloat a4 =
+ allocate<Struct16BytesHomogeneousFloat>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a0.a2 = -3.0;
+ a0.a3 = 4.0;
+ a1.a0 = -5.0;
+ a1.a1 = 6.0;
+ a1.a2 = -7.0;
+ a1.a3 = 8.0;
+ a2.a0 = -9.0;
+ a2.a1 = 10.0;
+ a2.a2 = -11.0;
+ a2.a3 = 12.0;
+ a3.a0 = -13.0;
+ a3.a1 = 14.0;
+ a3.a2 = -15.0;
+ a3.a3 = 16.0;
+ a4.a0 = -17.0;
+ a4.a1 = 18.0;
+ a4.a2 = -19.0;
+ a4.a3 = 20.0;
+
+ final result = passStruct16BytesHomogeneousFloatx5(a0, a1, a2, a3, a4);
+
+ print("result = $result");
+
+ Expect.approxEquals(10.0, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+}
+
+final passStruct16BytesMixedx10 = ffiTestFunctions.lookupFunction<
+ Double Function(
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed),
+ double Function(
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed)>("PassStruct16BytesMixedx10");
+
+/// On x64, arguments are split over FP and int registers.
+/// On x64, it will exhaust the integer registers with the 6th argument.
+/// The rest goes on the stack.
+/// On arm, arguments are 8 byte aligned.
+void testPassStruct16BytesMixedx10() {
+ Struct16BytesMixed a0 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a1 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a2 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a3 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a4 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a5 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a6 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a7 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a8 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a9 = allocate<Struct16BytesMixed>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2;
+ a1.a0 = -3.0;
+ a1.a1 = 4;
+ a2.a0 = -5.0;
+ a2.a1 = 6;
+ a3.a0 = -7.0;
+ a3.a1 = 8;
+ a4.a0 = -9.0;
+ a4.a1 = 10;
+ a5.a0 = -11.0;
+ a5.a1 = 12;
+ a6.a0 = -13.0;
+ a6.a1 = 14;
+ a7.a0 = -15.0;
+ a7.a1 = 16;
+ a8.a0 = -17.0;
+ a8.a1 = 18;
+ a9.a0 = -19.0;
+ a9.a1 = 20;
+
+ final result =
+ passStruct16BytesMixedx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.approxEquals(10.0, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct16BytesMixed2x10 = ffiTestFunctions.lookupFunction<
+ Float Function(
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2),
+ double Function(
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2)>("PassStruct16BytesMixed2x10");
+
+/// On x64, arguments are split over FP and int registers.
+/// On x64, it will exhaust the integer registers with the 6th argument.
+/// The rest goes on the stack.
+/// On arm, arguments are 4 byte aligned.
+void testPassStruct16BytesMixed2x10() {
+ Struct16BytesMixed2 a0 = allocate<Struct16BytesMixed2>().ref;
+ Struct16BytesMixed2 a1 = allocate<Struct16BytesMixed2>().ref;
+ Struct16BytesMixed2 a2 = allocate<Struct16BytesMixed2>().ref;
+ Struct16BytesMixed2 a3 = allocate<Struct16BytesMixed2>().ref;
+ Struct16BytesMixed2 a4 = allocate<Struct16BytesMixed2>().ref;
+ Struct16BytesMixed2 a5 = allocate<Struct16BytesMixed2>().ref;
+ Struct16BytesMixed2 a6 = allocate<Struct16BytesMixed2>().ref;
+ Struct16BytesMixed2 a7 = allocate<Struct16BytesMixed2>().ref;
+ Struct16BytesMixed2 a8 = allocate<Struct16BytesMixed2>().ref;
+ Struct16BytesMixed2 a9 = allocate<Struct16BytesMixed2>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a0.a2 = -3.0;
+ a0.a3 = 4;
+ a1.a0 = -5.0;
+ a1.a1 = 6.0;
+ a1.a2 = -7.0;
+ a1.a3 = 8;
+ a2.a0 = -9.0;
+ a2.a1 = 10.0;
+ a2.a2 = -11.0;
+ a2.a3 = 12;
+ a3.a0 = -13.0;
+ a3.a1 = 14.0;
+ a3.a2 = -15.0;
+ a3.a3 = 16;
+ a4.a0 = -17.0;
+ a4.a1 = 18.0;
+ a4.a2 = -19.0;
+ a4.a3 = 20;
+ a5.a0 = -21.0;
+ a5.a1 = 22.0;
+ a5.a2 = -23.0;
+ a5.a3 = 24;
+ a6.a0 = -25.0;
+ a6.a1 = 26.0;
+ a6.a2 = -27.0;
+ a6.a3 = 28;
+ a7.a0 = -29.0;
+ a7.a1 = 30.0;
+ a7.a2 = -31.0;
+ a7.a3 = 32;
+ a8.a0 = -33.0;
+ a8.a1 = 34.0;
+ a8.a2 = -35.0;
+ a8.a3 = 36;
+ a9.a0 = -37.0;
+ a9.a1 = 38.0;
+ a9.a2 = -39.0;
+ a9.a3 = 40;
+
+ final result =
+ passStruct16BytesMixed2x10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.approxEquals(20.0, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct17BytesIntx10 = ffiTestFunctions.lookupFunction<
+ Int64 Function(
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt),
+ int Function(
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt)>("PassStruct17BytesIntx10");
+
+/// Arguments are passed as pointer to copy on arm64.
+/// Tests that the memory allocated for copies are rounded up to word size.
+void testPassStruct17BytesIntx10() {
+ Struct17BytesInt a0 = allocate<Struct17BytesInt>().ref;
+ Struct17BytesInt a1 = allocate<Struct17BytesInt>().ref;
+ Struct17BytesInt a2 = allocate<Struct17BytesInt>().ref;
+ Struct17BytesInt a3 = allocate<Struct17BytesInt>().ref;
+ Struct17BytesInt a4 = allocate<Struct17BytesInt>().ref;
+ Struct17BytesInt a5 = allocate<Struct17BytesInt>().ref;
+ Struct17BytesInt a6 = allocate<Struct17BytesInt>().ref;
+ Struct17BytesInt a7 = allocate<Struct17BytesInt>().ref;
+ Struct17BytesInt a8 = allocate<Struct17BytesInt>().ref;
+ Struct17BytesInt a9 = allocate<Struct17BytesInt>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+ a1.a0 = 4;
+ a1.a1 = -5;
+ a1.a2 = 6;
+ a2.a0 = -7;
+ a2.a1 = 8;
+ a2.a2 = -9;
+ a3.a0 = 10;
+ a3.a1 = -11;
+ a3.a2 = 12;
+ a4.a0 = -13;
+ a4.a1 = 14;
+ a4.a2 = -15;
+ a5.a0 = 16;
+ a5.a1 = -17;
+ a5.a2 = 18;
+ a6.a0 = -19;
+ a6.a1 = 20;
+ a6.a2 = -21;
+ a7.a0 = 22;
+ a7.a1 = -23;
+ a7.a2 = 24;
+ a8.a0 = -25;
+ a8.a1 = 26;
+ a8.a2 = -27;
+ a9.a0 = 28;
+ a9.a1 = -29;
+ a9.a2 = 30;
+
+ final result =
+ passStruct17BytesIntx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.equals(15, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct19BytesHomogeneousUint8x10 = ffiTestFunctions.lookupFunction<
+ Int64 Function(
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8),
+ int Function(
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8)>("PassStruct19BytesHomogeneousUint8x10");
+
+/// The minimum alignment of this struct is only 1 byte based on its fields.
+/// Test that the memory backing these structs is extended to the right size.
+///
+void testPassStruct19BytesHomogeneousUint8x10() {
+ Struct19BytesHomogeneousUint8 a0 =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+ Struct19BytesHomogeneousUint8 a1 =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+ Struct19BytesHomogeneousUint8 a2 =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+ Struct19BytesHomogeneousUint8 a3 =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+ Struct19BytesHomogeneousUint8 a4 =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+ Struct19BytesHomogeneousUint8 a5 =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+ Struct19BytesHomogeneousUint8 a6 =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+ Struct19BytesHomogeneousUint8 a7 =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+ Struct19BytesHomogeneousUint8 a8 =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+ Struct19BytesHomogeneousUint8 a9 =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+
+ a0.a0 = 1;
+ a0.a1 = 2;
+ a0.a2 = 3;
+ a0.a3 = 4;
+ a0.a4 = 5;
+ a0.a5 = 6;
+ a0.a6 = 7;
+ a0.a7 = 8;
+ a0.a8 = 9;
+ a0.a9 = 10;
+ a0.a10 = 11;
+ a0.a11 = 12;
+ a0.a12 = 13;
+ a0.a13 = 14;
+ a0.a14 = 15;
+ a0.a15 = 16;
+ a0.a16 = 17;
+ a0.a17 = 18;
+ a0.a18 = 19;
+ a1.a0 = 20;
+ a1.a1 = 21;
+ a1.a2 = 22;
+ a1.a3 = 23;
+ a1.a4 = 24;
+ a1.a5 = 25;
+ a1.a6 = 26;
+ a1.a7 = 27;
+ a1.a8 = 28;
+ a1.a9 = 29;
+ a1.a10 = 30;
+ a1.a11 = 31;
+ a1.a12 = 32;
+ a1.a13 = 33;
+ a1.a14 = 34;
+ a1.a15 = 35;
+ a1.a16 = 36;
+ a1.a17 = 37;
+ a1.a18 = 38;
+ a2.a0 = 39;
+ a2.a1 = 40;
+ a2.a2 = 41;
+ a2.a3 = 42;
+ a2.a4 = 43;
+ a2.a5 = 44;
+ a2.a6 = 45;
+ a2.a7 = 46;
+ a2.a8 = 47;
+ a2.a9 = 48;
+ a2.a10 = 49;
+ a2.a11 = 50;
+ a2.a12 = 51;
+ a2.a13 = 52;
+ a2.a14 = 53;
+ a2.a15 = 54;
+ a2.a16 = 55;
+ a2.a17 = 56;
+ a2.a18 = 57;
+ a3.a0 = 58;
+ a3.a1 = 59;
+ a3.a2 = 60;
+ a3.a3 = 61;
+ a3.a4 = 62;
+ a3.a5 = 63;
+ a3.a6 = 64;
+ a3.a7 = 65;
+ a3.a8 = 66;
+ a3.a9 = 67;
+ a3.a10 = 68;
+ a3.a11 = 69;
+ a3.a12 = 70;
+ a3.a13 = 71;
+ a3.a14 = 72;
+ a3.a15 = 73;
+ a3.a16 = 74;
+ a3.a17 = 75;
+ a3.a18 = 76;
+ a4.a0 = 77;
+ a4.a1 = 78;
+ a4.a2 = 79;
+ a4.a3 = 80;
+ a4.a4 = 81;
+ a4.a5 = 82;
+ a4.a6 = 83;
+ a4.a7 = 84;
+ a4.a8 = 85;
+ a4.a9 = 86;
+ a4.a10 = 87;
+ a4.a11 = 88;
+ a4.a12 = 89;
+ a4.a13 = 90;
+ a4.a14 = 91;
+ a4.a15 = 92;
+ a4.a16 = 93;
+ a4.a17 = 94;
+ a4.a18 = 95;
+ a5.a0 = 96;
+ a5.a1 = 97;
+ a5.a2 = 98;
+ a5.a3 = 99;
+ a5.a4 = 100;
+ a5.a5 = 101;
+ a5.a6 = 102;
+ a5.a7 = 103;
+ a5.a8 = 104;
+ a5.a9 = 105;
+ a5.a10 = 106;
+ a5.a11 = 107;
+ a5.a12 = 108;
+ a5.a13 = 109;
+ a5.a14 = 110;
+ a5.a15 = 111;
+ a5.a16 = 112;
+ a5.a17 = 113;
+ a5.a18 = 114;
+ a6.a0 = 115;
+ a6.a1 = 116;
+ a6.a2 = 117;
+ a6.a3 = 118;
+ a6.a4 = 119;
+ a6.a5 = 120;
+ a6.a6 = 121;
+ a6.a7 = 122;
+ a6.a8 = 123;
+ a6.a9 = 124;
+ a6.a10 = 125;
+ a6.a11 = 126;
+ a6.a12 = 127;
+ a6.a13 = 128;
+ a6.a14 = 129;
+ a6.a15 = 130;
+ a6.a16 = 131;
+ a6.a17 = 132;
+ a6.a18 = 133;
+ a7.a0 = 134;
+ a7.a1 = 135;
+ a7.a2 = 136;
+ a7.a3 = 137;
+ a7.a4 = 138;
+ a7.a5 = 139;
+ a7.a6 = 140;
+ a7.a7 = 141;
+ a7.a8 = 142;
+ a7.a9 = 143;
+ a7.a10 = 144;
+ a7.a11 = 145;
+ a7.a12 = 146;
+ a7.a13 = 147;
+ a7.a14 = 148;
+ a7.a15 = 149;
+ a7.a16 = 150;
+ a7.a17 = 151;
+ a7.a18 = 152;
+ a8.a0 = 153;
+ a8.a1 = 154;
+ a8.a2 = 155;
+ a8.a3 = 156;
+ a8.a4 = 157;
+ a8.a5 = 158;
+ a8.a6 = 159;
+ a8.a7 = 160;
+ a8.a8 = 161;
+ a8.a9 = 162;
+ a8.a10 = 163;
+ a8.a11 = 164;
+ a8.a12 = 165;
+ a8.a13 = 166;
+ a8.a14 = 167;
+ a8.a15 = 168;
+ a8.a16 = 169;
+ a8.a17 = 170;
+ a8.a18 = 171;
+ a9.a0 = 172;
+ a9.a1 = 173;
+ a9.a2 = 174;
+ a9.a3 = 175;
+ a9.a4 = 176;
+ a9.a5 = 177;
+ a9.a6 = 178;
+ a9.a7 = 179;
+ a9.a8 = 180;
+ a9.a9 = 181;
+ a9.a10 = 182;
+ a9.a11 = 183;
+ a9.a12 = 184;
+ a9.a13 = 185;
+ a9.a14 = 186;
+ a9.a15 = 187;
+ a9.a16 = 188;
+ a9.a17 = 189;
+ a9.a18 = 190;
+
+ final result = passStruct19BytesHomogeneousUint8x10(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.equals(18145, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct20BytesHomogeneousInt32x10 = ffiTestFunctions.lookupFunction<
+ Int32 Function(
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32),
+ int Function(
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32)>("PassStruct20BytesHomogeneousInt32x10");
+
+/// Argument too big to go into integer registers on arm64.
+/// The arguments are passed as pointers to copies.
+/// The amount of arguments exhausts the number of integer registers, such that
+/// pointers to copies are also passed on the stack.
+void testPassStruct20BytesHomogeneousInt32x10() {
+ Struct20BytesHomogeneousInt32 a0 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+ Struct20BytesHomogeneousInt32 a1 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+ Struct20BytesHomogeneousInt32 a2 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+ Struct20BytesHomogeneousInt32 a3 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+ Struct20BytesHomogeneousInt32 a4 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+ Struct20BytesHomogeneousInt32 a5 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+ Struct20BytesHomogeneousInt32 a6 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+ Struct20BytesHomogeneousInt32 a7 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+ Struct20BytesHomogeneousInt32 a8 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+ Struct20BytesHomogeneousInt32 a9 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+ a0.a3 = 4;
+ a0.a4 = -5;
+ a1.a0 = 6;
+ a1.a1 = -7;
+ a1.a2 = 8;
+ a1.a3 = -9;
+ a1.a4 = 10;
+ a2.a0 = -11;
+ a2.a1 = 12;
+ a2.a2 = -13;
+ a2.a3 = 14;
+ a2.a4 = -15;
+ a3.a0 = 16;
+ a3.a1 = -17;
+ a3.a2 = 18;
+ a3.a3 = -19;
+ a3.a4 = 20;
+ a4.a0 = -21;
+ a4.a1 = 22;
+ a4.a2 = -23;
+ a4.a3 = 24;
+ a4.a4 = -25;
+ a5.a0 = 26;
+ a5.a1 = -27;
+ a5.a2 = 28;
+ a5.a3 = -29;
+ a5.a4 = 30;
+ a6.a0 = -31;
+ a6.a1 = 32;
+ a6.a2 = -33;
+ a6.a3 = 34;
+ a6.a4 = -35;
+ a7.a0 = 36;
+ a7.a1 = -37;
+ a7.a2 = 38;
+ a7.a3 = -39;
+ a7.a4 = 40;
+ a8.a0 = -41;
+ a8.a1 = 42;
+ a8.a2 = -43;
+ a8.a3 = 44;
+ a8.a4 = -45;
+ a9.a0 = 46;
+ a9.a1 = -47;
+ a9.a2 = 48;
+ a9.a3 = -49;
+ a9.a4 = 50;
+
+ final result = passStruct20BytesHomogeneousInt32x10(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.equals(25, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct20BytesHomogeneousFloat = ffiTestFunctions.lookupFunction<
+ Float Function(Struct20BytesHomogeneousFloat),
+ double Function(
+ Struct20BytesHomogeneousFloat)>("PassStruct20BytesHomogeneousFloat");
+
+/// Argument too big to go into FPU registers in hardfp and arm64.
+void testPassStruct20BytesHomogeneousFloat() {
+ Struct20BytesHomogeneousFloat a0 =
+ allocate<Struct20BytesHomogeneousFloat>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a0.a2 = -3.0;
+ a0.a3 = 4.0;
+ a0.a4 = -5.0;
+
+ final result = passStruct20BytesHomogeneousFloat(a0);
+
+ print("result = $result");
+
+ Expect.approxEquals(-3.0, result);
+
+ free(a0.addressOf);
+}
+
+final passStruct32BytesHomogeneousDoublex5 = ffiTestFunctions.lookupFunction<
+ Double Function(
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble),
+ double Function(
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble)>(
+ "PassStruct32BytesHomogeneousDoublex5");
+
+/// Arguments in FPU registers on arm64.
+/// 5 struct arguments will exhaust available registers.
+void testPassStruct32BytesHomogeneousDoublex5() {
+ Struct32BytesHomogeneousDouble a0 =
+ allocate<Struct32BytesHomogeneousDouble>().ref;
+ Struct32BytesHomogeneousDouble a1 =
+ allocate<Struct32BytesHomogeneousDouble>().ref;
+ Struct32BytesHomogeneousDouble a2 =
+ allocate<Struct32BytesHomogeneousDouble>().ref;
+ Struct32BytesHomogeneousDouble a3 =
+ allocate<Struct32BytesHomogeneousDouble>().ref;
+ Struct32BytesHomogeneousDouble a4 =
+ allocate<Struct32BytesHomogeneousDouble>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a0.a2 = -3.0;
+ a0.a3 = 4.0;
+ a1.a0 = -5.0;
+ a1.a1 = 6.0;
+ a1.a2 = -7.0;
+ a1.a3 = 8.0;
+ a2.a0 = -9.0;
+ a2.a1 = 10.0;
+ a2.a2 = -11.0;
+ a2.a3 = 12.0;
+ a3.a0 = -13.0;
+ a3.a1 = 14.0;
+ a3.a2 = -15.0;
+ a3.a3 = 16.0;
+ a4.a0 = -17.0;
+ a4.a1 = 18.0;
+ a4.a2 = -19.0;
+ a4.a3 = 20.0;
+
+ final result = passStruct32BytesHomogeneousDoublex5(a0, a1, a2, a3, a4);
+
+ print("result = $result");
+
+ Expect.approxEquals(10.0, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+}
+
+final passStruct40BytesHomogeneousDouble = ffiTestFunctions.lookupFunction<
+ Double Function(Struct40BytesHomogeneousDouble),
+ double Function(
+ Struct40BytesHomogeneousDouble)>("PassStruct40BytesHomogeneousDouble");
+
+/// Argument too big to go into FPU registers in arm64.
+void testPassStruct40BytesHomogeneousDouble() {
+ Struct40BytesHomogeneousDouble a0 =
+ allocate<Struct40BytesHomogeneousDouble>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a0.a2 = -3.0;
+ a0.a3 = 4.0;
+ a0.a4 = -5.0;
+
+ final result = passStruct40BytesHomogeneousDouble(a0);
+
+ print("result = $result");
+
+ Expect.approxEquals(-3.0, result);
+
+ free(a0.addressOf);
+}
+
+final passStruct1024BytesHomogeneousUint64 = ffiTestFunctions.lookupFunction<
+ Uint64 Function(Struct1024BytesHomogeneousUint64),
+ int Function(Struct1024BytesHomogeneousUint64)>(
+ "PassStruct1024BytesHomogeneousUint64");
+
+/// Test 1kb struct.
+void testPassStruct1024BytesHomogeneousUint64() {
+ Struct1024BytesHomogeneousUint64 a0 =
+ allocate<Struct1024BytesHomogeneousUint64>().ref;
+
+ a0.a0 = 1;
+ a0.a1 = 2;
+ a0.a2 = 3;
+ a0.a3 = 4;
+ a0.a4 = 5;
+ a0.a5 = 6;
+ a0.a6 = 7;
+ a0.a7 = 8;
+ a0.a8 = 9;
+ a0.a9 = 10;
+ a0.a10 = 11;
+ a0.a11 = 12;
+ a0.a12 = 13;
+ a0.a13 = 14;
+ a0.a14 = 15;
+ a0.a15 = 16;
+ a0.a16 = 17;
+ a0.a17 = 18;
+ a0.a18 = 19;
+ a0.a19 = 20;
+ a0.a20 = 21;
+ a0.a21 = 22;
+ a0.a22 = 23;
+ a0.a23 = 24;
+ a0.a24 = 25;
+ a0.a25 = 26;
+ a0.a26 = 27;
+ a0.a27 = 28;
+ a0.a28 = 29;
+ a0.a29 = 30;
+ a0.a30 = 31;
+ a0.a31 = 32;
+ a0.a32 = 33;
+ a0.a33 = 34;
+ a0.a34 = 35;
+ a0.a35 = 36;
+ a0.a36 = 37;
+ a0.a37 = 38;
+ a0.a38 = 39;
+ a0.a39 = 40;
+ a0.a40 = 41;
+ a0.a41 = 42;
+ a0.a42 = 43;
+ a0.a43 = 44;
+ a0.a44 = 45;
+ a0.a45 = 46;
+ a0.a46 = 47;
+ a0.a47 = 48;
+ a0.a48 = 49;
+ a0.a49 = 50;
+ a0.a50 = 51;
+ a0.a51 = 52;
+ a0.a52 = 53;
+ a0.a53 = 54;
+ a0.a54 = 55;
+ a0.a55 = 56;
+ a0.a56 = 57;
+ a0.a57 = 58;
+ a0.a58 = 59;
+ a0.a59 = 60;
+ a0.a60 = 61;
+ a0.a61 = 62;
+ a0.a62 = 63;
+ a0.a63 = 64;
+ a0.a64 = 65;
+ a0.a65 = 66;
+ a0.a66 = 67;
+ a0.a67 = 68;
+ a0.a68 = 69;
+ a0.a69 = 70;
+ a0.a70 = 71;
+ a0.a71 = 72;
+ a0.a72 = 73;
+ a0.a73 = 74;
+ a0.a74 = 75;
+ a0.a75 = 76;
+ a0.a76 = 77;
+ a0.a77 = 78;
+ a0.a78 = 79;
+ a0.a79 = 80;
+ a0.a80 = 81;
+ a0.a81 = 82;
+ a0.a82 = 83;
+ a0.a83 = 84;
+ a0.a84 = 85;
+ a0.a85 = 86;
+ a0.a86 = 87;
+ a0.a87 = 88;
+ a0.a88 = 89;
+ a0.a89 = 90;
+ a0.a90 = 91;
+ a0.a91 = 92;
+ a0.a92 = 93;
+ a0.a93 = 94;
+ a0.a94 = 95;
+ a0.a95 = 96;
+ a0.a96 = 97;
+ a0.a97 = 98;
+ a0.a98 = 99;
+ a0.a99 = 100;
+ a0.a100 = 101;
+ a0.a101 = 102;
+ a0.a102 = 103;
+ a0.a103 = 104;
+ a0.a104 = 105;
+ a0.a105 = 106;
+ a0.a106 = 107;
+ a0.a107 = 108;
+ a0.a108 = 109;
+ a0.a109 = 110;
+ a0.a110 = 111;
+ a0.a111 = 112;
+ a0.a112 = 113;
+ a0.a113 = 114;
+ a0.a114 = 115;
+ a0.a115 = 116;
+ a0.a116 = 117;
+ a0.a117 = 118;
+ a0.a118 = 119;
+ a0.a119 = 120;
+ a0.a120 = 121;
+ a0.a121 = 122;
+ a0.a122 = 123;
+ a0.a123 = 124;
+ a0.a124 = 125;
+ a0.a125 = 126;
+ a0.a126 = 127;
+ a0.a127 = 128;
+
+ final result = passStruct1024BytesHomogeneousUint64(a0);
+
+ print("result = $result");
+
+ Expect.equals(8256, result);
+
+ free(a0.addressOf);
+}
+
+final passFloatStruct16BytesHomogeneousFloatFloatStruct1 =
+ ffiTestFunctions.lookupFunction<
+ Float Function(
+ Float,
+ Struct16BytesHomogeneousFloat,
+ Float,
+ Struct16BytesHomogeneousFloat,
+ Float,
+ Struct16BytesHomogeneousFloat,
+ Float,
+ Struct16BytesHomogeneousFloat,
+ Float),
+ double Function(
+ double,
+ Struct16BytesHomogeneousFloat,
+ double,
+ Struct16BytesHomogeneousFloat,
+ double,
+ Struct16BytesHomogeneousFloat,
+ double,
+ Struct16BytesHomogeneousFloat,
+ double)>("PassFloatStruct16BytesHomogeneousFloatFloatStruct1");
+
+/// Tests the alignment of structs in FPU registers and backfilling.
+void testPassFloatStruct16BytesHomogeneousFloatFloatStruct1() {
+ double a0;
+ Struct16BytesHomogeneousFloat a1 =
+ allocate<Struct16BytesHomogeneousFloat>().ref;
+ double a2;
+ Struct16BytesHomogeneousFloat a3 =
+ allocate<Struct16BytesHomogeneousFloat>().ref;
+ double a4;
+ Struct16BytesHomogeneousFloat a5 =
+ allocate<Struct16BytesHomogeneousFloat>().ref;
+ double a6;
+ Struct16BytesHomogeneousFloat a7 =
+ allocate<Struct16BytesHomogeneousFloat>().ref;
+ double a8;
+
+ a0 = -1.0;
+ a1.a0 = 2.0;
+ a1.a1 = -3.0;
+ a1.a2 = 4.0;
+ a1.a3 = -5.0;
+ a2 = 6.0;
+ a3.a0 = -7.0;
+ a3.a1 = 8.0;
+ a3.a2 = -9.0;
+ a3.a3 = 10.0;
+ a4 = -11.0;
+ a5.a0 = 12.0;
+ a5.a1 = -13.0;
+ a5.a2 = 14.0;
+ a5.a3 = -15.0;
+ a6 = 16.0;
+ a7.a0 = -17.0;
+ a7.a1 = 18.0;
+ a7.a2 = -19.0;
+ a7.a3 = 20.0;
+ a8 = -21.0;
+
+ final result = passFloatStruct16BytesHomogeneousFloatFloatStruct1(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ print("result = $result");
+
+ Expect.approxEquals(-11.0, result);
+
+ free(a1.addressOf);
+ free(a3.addressOf);
+ free(a5.addressOf);
+ free(a7.addressOf);
+}
+
+final passFloatStruct32BytesHomogeneousDoubleFloatStruct =
+ ffiTestFunctions.lookupFunction<
+ Double Function(
+ Float,
+ Struct32BytesHomogeneousDouble,
+ Float,
+ Struct32BytesHomogeneousDouble,
+ Float,
+ Struct32BytesHomogeneousDouble,
+ Float,
+ Struct32BytesHomogeneousDouble,
+ Float),
+ double Function(
+ double,
+ Struct32BytesHomogeneousDouble,
+ double,
+ Struct32BytesHomogeneousDouble,
+ double,
+ Struct32BytesHomogeneousDouble,
+ double,
+ Struct32BytesHomogeneousDouble,
+ double)>("PassFloatStruct32BytesHomogeneousDoubleFloatStruct");
+
+/// Tests the alignment of structs in FPU registers and backfilling.
+void testPassFloatStruct32BytesHomogeneousDoubleFloatStruct() {
+ double a0;
+ Struct32BytesHomogeneousDouble a1 =
+ allocate<Struct32BytesHomogeneousDouble>().ref;
+ double a2;
+ Struct32BytesHomogeneousDouble a3 =
+ allocate<Struct32BytesHomogeneousDouble>().ref;
+ double a4;
+ Struct32BytesHomogeneousDouble a5 =
+ allocate<Struct32BytesHomogeneousDouble>().ref;
+ double a6;
+ Struct32BytesHomogeneousDouble a7 =
+ allocate<Struct32BytesHomogeneousDouble>().ref;
+ double a8;
+
+ a0 = -1.0;
+ a1.a0 = 2.0;
+ a1.a1 = -3.0;
+ a1.a2 = 4.0;
+ a1.a3 = -5.0;
+ a2 = 6.0;
+ a3.a0 = -7.0;
+ a3.a1 = 8.0;
+ a3.a2 = -9.0;
+ a3.a3 = 10.0;
+ a4 = -11.0;
+ a5.a0 = 12.0;
+ a5.a1 = -13.0;
+ a5.a2 = 14.0;
+ a5.a3 = -15.0;
+ a6 = 16.0;
+ a7.a0 = -17.0;
+ a7.a1 = 18.0;
+ a7.a2 = -19.0;
+ a7.a3 = 20.0;
+ a8 = -21.0;
+
+ final result = passFloatStruct32BytesHomogeneousDoubleFloatStruct(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ print("result = $result");
+
+ Expect.approxEquals(-11.0, result);
+
+ free(a1.addressOf);
+ free(a3.addressOf);
+ free(a5.addressOf);
+ free(a7.addressOf);
+}
+
+final passInt8Struct16BytesMixedInt8Struct16BytesMixedIn =
+ ffiTestFunctions.lookupFunction<
+ Double Function(Int8, Struct16BytesMixed, Int8, Struct16BytesMixed,
+ Int8, Struct16BytesMixed, Int8, Struct16BytesMixed, Int8),
+ double Function(
+ int,
+ Struct16BytesMixed,
+ int,
+ Struct16BytesMixed,
+ int,
+ Struct16BytesMixed,
+ int,
+ Struct16BytesMixed,
+ int)>("PassInt8Struct16BytesMixedInt8Struct16BytesMixedIn");
+
+/// Tests the alignment of structs in integers registers and on the stack.
+/// Arm32 aligns this struct at 8.
+/// Also, arm32 allocates the second struct partially in registers, partially
+/// on stack.
+/// Test backfilling of integer registers.
+void testPassInt8Struct16BytesMixedInt8Struct16BytesMixedIn() {
+ int a0;
+ Struct16BytesMixed a1 = allocate<Struct16BytesMixed>().ref;
+ int a2;
+ Struct16BytesMixed a3 = allocate<Struct16BytesMixed>().ref;
+ int a4;
+ Struct16BytesMixed a5 = allocate<Struct16BytesMixed>().ref;
+ int a6;
+ Struct16BytesMixed a7 = allocate<Struct16BytesMixed>().ref;
+ int a8;
+
+ a0 = -1;
+ a1.a0 = 2.0;
+ a1.a1 = -3;
+ a2 = 4;
+ a3.a0 = -5.0;
+ a3.a1 = 6;
+ a4 = -7;
+ a5.a0 = 8.0;
+ a5.a1 = -9;
+ a6 = 10;
+ a7.a0 = -11.0;
+ a7.a1 = 12;
+ a8 = -13;
+
+ final result = passInt8Struct16BytesMixedInt8Struct16BytesMixedIn(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ print("result = $result");
+
+ Expect.approxEquals(-7.0, result);
+
+ free(a1.addressOf);
+ free(a3.addressOf);
+ free(a5.addressOf);
+ free(a7.addressOf);
+}
+
+final passDoublex6Struct16BytesMixedx4Int32 = ffiTestFunctions.lookupFunction<
+ Double Function(
+ Double,
+ Double,
+ Double,
+ Double,
+ Double,
+ Double,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Int32),
+ double Function(
+ double,
+ double,
+ double,
+ double,
+ double,
+ double,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ int)>("PassDoublex6Struct16BytesMixedx4Int32");
+
+/// On Linux x64, it will exhaust xmm registers first, after 6 doubles and 2
+/// structs. The rest of the structs will go on the stack.
+/// The int will be backfilled into the int register.
+void testPassDoublex6Struct16BytesMixedx4Int32() {
+ double a0;
+ double a1;
+ double a2;
+ double a3;
+ double a4;
+ double a5;
+ Struct16BytesMixed a6 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a7 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a8 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a9 = allocate<Struct16BytesMixed>().ref;
+ int a10;
+
+ a0 = -1.0;
+ a1 = 2.0;
+ a2 = -3.0;
+ a3 = 4.0;
+ a4 = -5.0;
+ a5 = 6.0;
+ a6.a0 = -7.0;
+ a6.a1 = 8;
+ a7.a0 = -9.0;
+ a7.a1 = 10;
+ a8.a0 = -11.0;
+ a8.a1 = 12;
+ a9.a0 = -13.0;
+ a9.a1 = 14;
+ a10 = -15;
+
+ final result = passDoublex6Struct16BytesMixedx4Int32(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
+
+ print("result = $result");
+
+ Expect.approxEquals(-8.0, result);
+
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passInt32x4Struct16BytesMixedx4Double = ffiTestFunctions.lookupFunction<
+ Double Function(Int32, Int32, Int32, Int32, Struct16BytesMixed,
+ Struct16BytesMixed, Struct16BytesMixed, Struct16BytesMixed, Double),
+ double Function(
+ int,
+ int,
+ int,
+ int,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ double)>("PassInt32x4Struct16BytesMixedx4Double");
+
+/// On Linux x64, it will exhaust int registers first.
+/// The rest of the structs will go on the stack.
+/// The double will be backfilled into the xmm register.
+void testPassInt32x4Struct16BytesMixedx4Double() {
+ int a0;
+ int a1;
+ int a2;
+ int a3;
+ Struct16BytesMixed a4 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a5 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a6 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a7 = allocate<Struct16BytesMixed>().ref;
+ double a8;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+ a3 = 4;
+ a4.a0 = -5.0;
+ a4.a1 = 6;
+ a5.a0 = -7.0;
+ a5.a1 = 8;
+ a6.a0 = -9.0;
+ a6.a1 = 10;
+ a7.a0 = -11.0;
+ a7.a1 = 12;
+ a8 = -13.0;
+
+ final result =
+ passInt32x4Struct16BytesMixedx4Double(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ print("result = $result");
+
+ Expect.approxEquals(-7.0, result);
+
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+}
+
+final passStruct40BytesHomogeneousDoubleStruct4BytesHomo =
+ ffiTestFunctions.lookupFunction<
+ Double Function(Struct40BytesHomogeneousDouble,
+ Struct4BytesHomogeneousInt16, Struct8BytesHomogeneousFloat),
+ double Function(Struct40BytesHomogeneousDouble,
+ Struct4BytesHomogeneousInt16, Struct8BytesHomogeneousFloat)>(
+ "PassStruct40BytesHomogeneousDoubleStruct4BytesHomo");
+
+/// On various architectures, first struct is allocated on stack.
+/// Check that the other two arguments are allocated on registers.
+void testPassStruct40BytesHomogeneousDoubleStruct4BytesHomo() {
+ Struct40BytesHomogeneousDouble a0 =
+ allocate<Struct40BytesHomogeneousDouble>().ref;
+ Struct4BytesHomogeneousInt16 a1 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+ Struct8BytesHomogeneousFloat a2 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a0.a2 = -3.0;
+ a0.a3 = 4.0;
+ a0.a4 = -5.0;
+ a1.a0 = 6;
+ a1.a1 = -7;
+ a2.a0 = 8.0;
+ a2.a1 = -9.0;
+
+ final result = passStruct40BytesHomogeneousDoubleStruct4BytesHomo(a0, a1, a2);
+
+ print("result = $result");
+
+ Expect.approxEquals(-5.0, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+}
+
+final passStructAlignmentInt16 = ffiTestFunctions.lookupFunction<
+ Int64 Function(StructAlignmentInt16),
+ int Function(StructAlignmentInt16)>("PassStructAlignmentInt16");
+
+/// Test alignment and padding of 16 byte int within struct.
+void testPassStructAlignmentInt16() {
+ StructAlignmentInt16 a0 = allocate<StructAlignmentInt16>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+
+ final result = passStructAlignmentInt16(a0);
+
+ print("result = $result");
+
+ Expect.equals(-2, result);
+
+ free(a0.addressOf);
+}
+
+final passStructAlignmentInt32 = ffiTestFunctions.lookupFunction<
+ Int64 Function(StructAlignmentInt32),
+ int Function(StructAlignmentInt32)>("PassStructAlignmentInt32");
+
+/// Test alignment and padding of 32 byte int within struct.
+void testPassStructAlignmentInt32() {
+ StructAlignmentInt32 a0 = allocate<StructAlignmentInt32>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+
+ final result = passStructAlignmentInt32(a0);
+
+ print("result = $result");
+
+ Expect.equals(-2, result);
+
+ free(a0.addressOf);
+}
+
+final passStructAlignmentInt64 = ffiTestFunctions.lookupFunction<
+ Int64 Function(StructAlignmentInt64),
+ int Function(StructAlignmentInt64)>("PassStructAlignmentInt64");
+
+/// Test alignment and padding of 64 byte int within struct.
+void testPassStructAlignmentInt64() {
+ StructAlignmentInt64 a0 = allocate<StructAlignmentInt64>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+
+ final result = passStructAlignmentInt64(a0);
+
+ print("result = $result");
+
+ Expect.equals(-2, result);
+
+ free(a0.addressOf);
+}
+
+final returnStruct1ByteInt = ffiTestFunctions.lookupFunction<
+ Struct1ByteInt Function(Int8),
+ Struct1ByteInt Function(int)>("ReturnStruct1ByteInt");
+
+/// Smallest struct with data.
+void testReturnStruct1ByteInt() {
+ int a0;
+
+ a0 = -1;
+
+ final result = returnStruct1ByteInt(a0);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+}
+
+final returnStruct3BytesInt = ffiTestFunctions.lookupFunction<
+ Struct3BytesInt Function(Int16, Int8),
+ Struct3BytesInt Function(int, int)>("ReturnStruct3BytesInt");
+
+/// Smaller than word size return value on all architectures.
+void testReturnStruct3BytesInt() {
+ int a0;
+ int a1;
+
+ a0 = -1;
+ a1 = 2;
+
+ final result = returnStruct3BytesInt(a0, a1);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+}
+
+final returnStruct4BytesHomogeneousInt16 = ffiTestFunctions.lookupFunction<
+ Struct4BytesHomogeneousInt16 Function(Int16, Int16),
+ Struct4BytesHomogeneousInt16 Function(
+ int, int)>("ReturnStruct4BytesHomogeneousInt16");
+
+/// Word size return value on 32 bit architectures..
+void testReturnStruct4BytesHomogeneousInt16() {
+ int a0;
+ int a1;
+
+ a0 = -1;
+ a1 = 2;
+
+ final result = returnStruct4BytesHomogeneousInt16(a0, a1);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+}
+
+final returnStruct7BytesInt = ffiTestFunctions.lookupFunction<
+ Struct7BytesInt Function(Int32, Int16, Int8),
+ Struct7BytesInt Function(int, int, int)>("ReturnStruct7BytesInt");
+
+/// Non-wordsize return value.
+void testReturnStruct7BytesInt() {
+ int a0;
+ int a1;
+ int a2;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+
+ final result = returnStruct7BytesInt(a0, a1, a2);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+}
+
+final returnStruct8BytesInt = ffiTestFunctions.lookupFunction<
+ Struct8BytesInt Function(Int16, Int16, Int32),
+ Struct8BytesInt Function(int, int, int)>("ReturnStruct8BytesInt");
+
+/// Return value in integer registers on many architectures.
+void testReturnStruct8BytesInt() {
+ int a0;
+ int a1;
+ int a2;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+
+ final result = returnStruct8BytesInt(a0, a1, a2);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+}
+
+final returnStruct8BytesHomogeneousFloat = ffiTestFunctions.lookupFunction<
+ Struct8BytesHomogeneousFloat Function(Float, Float),
+ Struct8BytesHomogeneousFloat Function(
+ double, double)>("ReturnStruct8BytesHomogeneousFloat");
+
+/// Return value in FP registers on many architectures.
+void testReturnStruct8BytesHomogeneousFloat() {
+ double a0;
+ double a1;
+
+ a0 = -1.0;
+ a1 = 2.0;
+
+ final result = returnStruct8BytesHomogeneousFloat(a0, a1);
+
+ print("result = $result");
+
+ Expect.approxEquals(a0, result.a0);
+ Expect.approxEquals(a1, result.a1);
+}
+
+final returnStruct8BytesMixed = ffiTestFunctions.lookupFunction<
+ Struct8BytesMixed Function(Float, Int16, Int16),
+ Struct8BytesMixed Function(double, int, int)>("ReturnStruct8BytesMixed");
+
+/// Return value split over FP and integer register in x64.
+void testReturnStruct8BytesMixed() {
+ double a0;
+ int a1;
+ int a2;
+
+ a0 = -1.0;
+ a1 = 2;
+ a2 = -3;
+
+ final result = returnStruct8BytesMixed(a0, a1, a2);
+
+ print("result = $result");
+
+ Expect.approxEquals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+}
+
+final returnStruct9BytesInt = ffiTestFunctions.lookupFunction<
+ Struct9BytesInt Function(Int64, Int8),
+ Struct9BytesInt Function(int, int)>("ReturnStruct9BytesInt");
+
+/// Return value in two integer registers on x64.
+/// The second register only contains a single byte.
+void testReturnStruct9BytesInt() {
+ int a0;
+ int a1;
+
+ a0 = -1;
+ a1 = 2;
+
+ final result = returnStruct9BytesInt(a0, a1);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+}
+
+final returnStruct9BytesHomogeneousUint82 = ffiTestFunctions.lookupFunction<
+ Struct9BytesHomogeneousUint82 Function(
+ Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8),
+ Struct9BytesHomogeneousUint82 Function(int, int, int, int, int, int, int,
+ int, int)>("ReturnStruct9BytesHomogeneousUint82");
+
+/// The minimum alignment of this struct is only 1 byte based on its fields.
+/// Test that the memory backing these structs is the right size and that
+/// dart:ffi trampolines do not write outside this size.
+void testReturnStruct9BytesHomogeneousUint82() {
+ int a0;
+ int a1;
+ int a2;
+ int a3;
+ int a4;
+ int a5;
+ int a6;
+ int a7;
+ int a8;
+
+ a0 = 1;
+ a1 = 2;
+ a2 = 3;
+ a3 = 4;
+ a4 = 5;
+ a5 = 6;
+ a6 = 7;
+ a7 = 8;
+ a8 = 9;
+
+ final result =
+ returnStruct9BytesHomogeneousUint82(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+ Expect.equals(a3, result.a3);
+ Expect.equals(a4, result.a4);
+ Expect.equals(a5, result.a5);
+ Expect.equals(a6, result.a6);
+ Expect.equals(a7, result.a7);
+ Expect.equals(a8, result.a8);
+}
+
+final returnStruct12BytesHomogeneousFloat = ffiTestFunctions.lookupFunction<
+ Struct12BytesHomogeneousFloat Function(Float, Float, Float),
+ Struct12BytesHomogeneousFloat Function(
+ double, double, double)>("ReturnStruct12BytesHomogeneousFloat");
+
+/// Return value in FPU registers, but does not use all registers on arm hardfp
+/// and arm64.
+void testReturnStruct12BytesHomogeneousFloat() {
+ double a0;
+ double a1;
+ double a2;
+
+ a0 = -1.0;
+ a1 = 2.0;
+ a2 = -3.0;
+
+ final result = returnStruct12BytesHomogeneousFloat(a0, a1, a2);
+
+ print("result = $result");
+
+ Expect.approxEquals(a0, result.a0);
+ Expect.approxEquals(a1, result.a1);
+ Expect.approxEquals(a2, result.a2);
+}
+
+final returnStruct16BytesHomogeneousFloat = ffiTestFunctions.lookupFunction<
+ Struct16BytesHomogeneousFloat Function(Float, Float, Float, Float),
+ Struct16BytesHomogeneousFloat Function(
+ double, double, double, double)>("ReturnStruct16BytesHomogeneousFloat");
+
+/// Return value in FPU registers on arm hardfp and arm64.
+void testReturnStruct16BytesHomogeneousFloat() {
+ double a0;
+ double a1;
+ double a2;
+ double a3;
+
+ a0 = -1.0;
+ a1 = 2.0;
+ a2 = -3.0;
+ a3 = 4.0;
+
+ final result = returnStruct16BytesHomogeneousFloat(a0, a1, a2, a3);
+
+ print("result = $result");
+
+ Expect.approxEquals(a0, result.a0);
+ Expect.approxEquals(a1, result.a1);
+ Expect.approxEquals(a2, result.a2);
+ Expect.approxEquals(a3, result.a3);
+}
+
+final returnStruct16BytesMixed = ffiTestFunctions.lookupFunction<
+ Struct16BytesMixed Function(Double, Int64),
+ Struct16BytesMixed Function(double, int)>("ReturnStruct16BytesMixed");
+
+/// Return value split over FP and integer register in x64.
+void testReturnStruct16BytesMixed() {
+ double a0;
+ int a1;
+
+ a0 = -1.0;
+ a1 = 2;
+
+ final result = returnStruct16BytesMixed(a0, a1);
+
+ print("result = $result");
+
+ Expect.approxEquals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+}
+
+final returnStruct16BytesMixed2 = ffiTestFunctions.lookupFunction<
+ Struct16BytesMixed2 Function(Float, Float, Float, Int32),
+ Struct16BytesMixed2 Function(
+ double, double, double, int)>("ReturnStruct16BytesMixed2");
+
+/// Return value split over FP and integer register in x64.
+/// The integer register contains half float half int.
+void testReturnStruct16BytesMixed2() {
+ double a0;
+ double a1;
+ double a2;
+ int a3;
+
+ a0 = -1.0;
+ a1 = 2.0;
+ a2 = -3.0;
+ a3 = 4;
+
+ final result = returnStruct16BytesMixed2(a0, a1, a2, a3);
+
+ print("result = $result");
+
+ Expect.approxEquals(a0, result.a0);
+ Expect.approxEquals(a1, result.a1);
+ Expect.approxEquals(a2, result.a2);
+ Expect.equals(a3, result.a3);
+}
+
+final returnStruct17BytesInt = ffiTestFunctions.lookupFunction<
+ Struct17BytesInt Function(Int64, Int64, Int8),
+ Struct17BytesInt Function(int, int, int)>("ReturnStruct17BytesInt");
+
+/// Rerturn value returned in preallocated space passed by pointer on most ABIs.
+/// Is non word size on purpose, to test that structs are rounded up to word size
+/// on all ABIs.
+void testReturnStruct17BytesInt() {
+ int a0;
+ int a1;
+ int a2;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+
+ final result = returnStruct17BytesInt(a0, a1, a2);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+}
+
+final returnStruct19BytesHomogeneousUint8 = ffiTestFunctions.lookupFunction<
+ Struct19BytesHomogeneousUint8 Function(
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8),
+ Struct19BytesHomogeneousUint8 Function(
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int)>("ReturnStruct19BytesHomogeneousUint8");
+
+/// The minimum alignment of this struct is only 1 byte based on its fields.
+/// Test that the memory backing these structs is the right size and that
+/// dart:ffi trampolines do not write outside this size.
+void testReturnStruct19BytesHomogeneousUint8() {
+ int a0;
+ int a1;
+ int a2;
+ int a3;
+ int a4;
+ int a5;
+ int a6;
+ int a7;
+ int a8;
+ int a9;
+ int a10;
+ int a11;
+ int a12;
+ int a13;
+ int a14;
+ int a15;
+ int a16;
+ int a17;
+ int a18;
+
+ a0 = 1;
+ a1 = 2;
+ a2 = 3;
+ a3 = 4;
+ a4 = 5;
+ a5 = 6;
+ a6 = 7;
+ a7 = 8;
+ a8 = 9;
+ a9 = 10;
+ a10 = 11;
+ a11 = 12;
+ a12 = 13;
+ a13 = 14;
+ a14 = 15;
+ a15 = 16;
+ a16 = 17;
+ a17 = 18;
+ a18 = 19;
+
+ final result = returnStruct19BytesHomogeneousUint8(a0, a1, a2, a3, a4, a5, a6,
+ a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+ Expect.equals(a3, result.a3);
+ Expect.equals(a4, result.a4);
+ Expect.equals(a5, result.a5);
+ Expect.equals(a6, result.a6);
+ Expect.equals(a7, result.a7);
+ Expect.equals(a8, result.a8);
+ Expect.equals(a9, result.a9);
+ Expect.equals(a10, result.a10);
+ Expect.equals(a11, result.a11);
+ Expect.equals(a12, result.a12);
+ Expect.equals(a13, result.a13);
+ Expect.equals(a14, result.a14);
+ Expect.equals(a15, result.a15);
+ Expect.equals(a16, result.a16);
+ Expect.equals(a17, result.a17);
+ Expect.equals(a18, result.a18);
+}
+
+final returnStruct20BytesHomogeneousInt32 = ffiTestFunctions.lookupFunction<
+ Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32, Int32),
+ Struct20BytesHomogeneousInt32 Function(
+ int, int, int, int, int)>("ReturnStruct20BytesHomogeneousInt32");
+
+/// Return value too big to go in cpu registers on arm64.
+void testReturnStruct20BytesHomogeneousInt32() {
+ int a0;
+ int a1;
+ int a2;
+ int a3;
+ int a4;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+ a3 = 4;
+ a4 = -5;
+
+ final result = returnStruct20BytesHomogeneousInt32(a0, a1, a2, a3, a4);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+ Expect.equals(a3, result.a3);
+ Expect.equals(a4, result.a4);
+}
+
+final returnStruct20BytesHomogeneousFloat = ffiTestFunctions.lookupFunction<
+ Struct20BytesHomogeneousFloat Function(Float, Float, Float, Float, Float),
+ Struct20BytesHomogeneousFloat Function(double, double, double, double,
+ double)>("ReturnStruct20BytesHomogeneousFloat");
+
+/// Return value too big to go in FPU registers on x64, arm hardfp and arm64.
+void testReturnStruct20BytesHomogeneousFloat() {
+ double a0;
+ double a1;
+ double a2;
+ double a3;
+ double a4;
+
+ a0 = -1.0;
+ a1 = 2.0;
+ a2 = -3.0;
+ a3 = 4.0;
+ a4 = -5.0;
+
+ final result = returnStruct20BytesHomogeneousFloat(a0, a1, a2, a3, a4);
+
+ print("result = $result");
+
+ Expect.approxEquals(a0, result.a0);
+ Expect.approxEquals(a1, result.a1);
+ Expect.approxEquals(a2, result.a2);
+ Expect.approxEquals(a3, result.a3);
+ Expect.approxEquals(a4, result.a4);
+}
+
+final returnStruct32BytesHomogeneousDouble = ffiTestFunctions.lookupFunction<
+ Struct32BytesHomogeneousDouble Function(Double, Double, Double, Double),
+ Struct32BytesHomogeneousDouble Function(double, double, double,
+ double)>("ReturnStruct32BytesHomogeneousDouble");
+
+/// Return value in FPU registers on arm64.
+void testReturnStruct32BytesHomogeneousDouble() {
+ double a0;
+ double a1;
+ double a2;
+ double a3;
+
+ a0 = -1.0;
+ a1 = 2.0;
+ a2 = -3.0;
+ a3 = 4.0;
+
+ final result = returnStruct32BytesHomogeneousDouble(a0, a1, a2, a3);
+
+ print("result = $result");
+
+ Expect.approxEquals(a0, result.a0);
+ Expect.approxEquals(a1, result.a1);
+ Expect.approxEquals(a2, result.a2);
+ Expect.approxEquals(a3, result.a3);
+}
+
+final returnStruct40BytesHomogeneousDouble = ffiTestFunctions.lookupFunction<
+ Struct40BytesHomogeneousDouble Function(
+ Double, Double, Double, Double, Double),
+ Struct40BytesHomogeneousDouble Function(double, double, double, double,
+ double)>("ReturnStruct40BytesHomogeneousDouble");
+
+/// Return value too big to go in FPU registers on arm64.
+void testReturnStruct40BytesHomogeneousDouble() {
+ double a0;
+ double a1;
+ double a2;
+ double a3;
+ double a4;
+
+ a0 = -1.0;
+ a1 = 2.0;
+ a2 = -3.0;
+ a3 = 4.0;
+ a4 = -5.0;
+
+ final result = returnStruct40BytesHomogeneousDouble(a0, a1, a2, a3, a4);
+
+ print("result = $result");
+
+ Expect.approxEquals(a0, result.a0);
+ Expect.approxEquals(a1, result.a1);
+ Expect.approxEquals(a2, result.a2);
+ Expect.approxEquals(a3, result.a3);
+ Expect.approxEquals(a4, result.a4);
+}
+
+final returnStruct1024BytesHomogeneousUint64 = ffiTestFunctions.lookupFunction<
+ Struct1024BytesHomogeneousUint64 Function(
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64),
+ Struct1024BytesHomogeneousUint64 Function(
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int)>("ReturnStruct1024BytesHomogeneousUint64");
+
+/// Test 1kb struct.
+void testReturnStruct1024BytesHomogeneousUint64() {
+ int a0;
+ int a1;
+ int a2;
+ int a3;
+ int a4;
+ int a5;
+ int a6;
+ int a7;
+ int a8;
+ int a9;
+ int a10;
+ int a11;
+ int a12;
+ int a13;
+ int a14;
+ int a15;
+ int a16;
+ int a17;
+ int a18;
+ int a19;
+ int a20;
+ int a21;
+ int a22;
+ int a23;
+ int a24;
+ int a25;
+ int a26;
+ int a27;
+ int a28;
+ int a29;
+ int a30;
+ int a31;
+ int a32;
+ int a33;
+ int a34;
+ int a35;
+ int a36;
+ int a37;
+ int a38;
+ int a39;
+ int a40;
+ int a41;
+ int a42;
+ int a43;
+ int a44;
+ int a45;
+ int a46;
+ int a47;
+ int a48;
+ int a49;
+ int a50;
+ int a51;
+ int a52;
+ int a53;
+ int a54;
+ int a55;
+ int a56;
+ int a57;
+ int a58;
+ int a59;
+ int a60;
+ int a61;
+ int a62;
+ int a63;
+ int a64;
+ int a65;
+ int a66;
+ int a67;
+ int a68;
+ int a69;
+ int a70;
+ int a71;
+ int a72;
+ int a73;
+ int a74;
+ int a75;
+ int a76;
+ int a77;
+ int a78;
+ int a79;
+ int a80;
+ int a81;
+ int a82;
+ int a83;
+ int a84;
+ int a85;
+ int a86;
+ int a87;
+ int a88;
+ int a89;
+ int a90;
+ int a91;
+ int a92;
+ int a93;
+ int a94;
+ int a95;
+ int a96;
+ int a97;
+ int a98;
+ int a99;
+ int a100;
+ int a101;
+ int a102;
+ int a103;
+ int a104;
+ int a105;
+ int a106;
+ int a107;
+ int a108;
+ int a109;
+ int a110;
+ int a111;
+ int a112;
+ int a113;
+ int a114;
+ int a115;
+ int a116;
+ int a117;
+ int a118;
+ int a119;
+ int a120;
+ int a121;
+ int a122;
+ int a123;
+ int a124;
+ int a125;
+ int a126;
+ int a127;
+
+ a0 = 1;
+ a1 = 2;
+ a2 = 3;
+ a3 = 4;
+ a4 = 5;
+ a5 = 6;
+ a6 = 7;
+ a7 = 8;
+ a8 = 9;
+ a9 = 10;
+ a10 = 11;
+ a11 = 12;
+ a12 = 13;
+ a13 = 14;
+ a14 = 15;
+ a15 = 16;
+ a16 = 17;
+ a17 = 18;
+ a18 = 19;
+ a19 = 20;
+ a20 = 21;
+ a21 = 22;
+ a22 = 23;
+ a23 = 24;
+ a24 = 25;
+ a25 = 26;
+ a26 = 27;
+ a27 = 28;
+ a28 = 29;
+ a29 = 30;
+ a30 = 31;
+ a31 = 32;
+ a32 = 33;
+ a33 = 34;
+ a34 = 35;
+ a35 = 36;
+ a36 = 37;
+ a37 = 38;
+ a38 = 39;
+ a39 = 40;
+ a40 = 41;
+ a41 = 42;
+ a42 = 43;
+ a43 = 44;
+ a44 = 45;
+ a45 = 46;
+ a46 = 47;
+ a47 = 48;
+ a48 = 49;
+ a49 = 50;
+ a50 = 51;
+ a51 = 52;
+ a52 = 53;
+ a53 = 54;
+ a54 = 55;
+ a55 = 56;
+ a56 = 57;
+ a57 = 58;
+ a58 = 59;
+ a59 = 60;
+ a60 = 61;
+ a61 = 62;
+ a62 = 63;
+ a63 = 64;
+ a64 = 65;
+ a65 = 66;
+ a66 = 67;
+ a67 = 68;
+ a68 = 69;
+ a69 = 70;
+ a70 = 71;
+ a71 = 72;
+ a72 = 73;
+ a73 = 74;
+ a74 = 75;
+ a75 = 76;
+ a76 = 77;
+ a77 = 78;
+ a78 = 79;
+ a79 = 80;
+ a80 = 81;
+ a81 = 82;
+ a82 = 83;
+ a83 = 84;
+ a84 = 85;
+ a85 = 86;
+ a86 = 87;
+ a87 = 88;
+ a88 = 89;
+ a89 = 90;
+ a90 = 91;
+ a91 = 92;
+ a92 = 93;
+ a93 = 94;
+ a94 = 95;
+ a95 = 96;
+ a96 = 97;
+ a97 = 98;
+ a98 = 99;
+ a99 = 100;
+ a100 = 101;
+ a101 = 102;
+ a102 = 103;
+ a103 = 104;
+ a104 = 105;
+ a105 = 106;
+ a106 = 107;
+ a107 = 108;
+ a108 = 109;
+ a109 = 110;
+ a110 = 111;
+ a111 = 112;
+ a112 = 113;
+ a113 = 114;
+ a114 = 115;
+ a115 = 116;
+ a116 = 117;
+ a117 = 118;
+ a118 = 119;
+ a119 = 120;
+ a120 = 121;
+ a121 = 122;
+ a122 = 123;
+ a123 = 124;
+ a124 = 125;
+ a125 = 126;
+ a126 = 127;
+ a127 = 128;
+
+ final result = returnStruct1024BytesHomogeneousUint64(
+ a0,
+ a1,
+ a2,
+ a3,
+ a4,
+ a5,
+ a6,
+ a7,
+ a8,
+ a9,
+ a10,
+ a11,
+ a12,
+ a13,
+ a14,
+ a15,
+ a16,
+ a17,
+ a18,
+ a19,
+ a20,
+ a21,
+ a22,
+ a23,
+ a24,
+ a25,
+ a26,
+ a27,
+ a28,
+ a29,
+ a30,
+ a31,
+ a32,
+ a33,
+ a34,
+ a35,
+ a36,
+ a37,
+ a38,
+ a39,
+ a40,
+ a41,
+ a42,
+ a43,
+ a44,
+ a45,
+ a46,
+ a47,
+ a48,
+ a49,
+ a50,
+ a51,
+ a52,
+ a53,
+ a54,
+ a55,
+ a56,
+ a57,
+ a58,
+ a59,
+ a60,
+ a61,
+ a62,
+ a63,
+ a64,
+ a65,
+ a66,
+ a67,
+ a68,
+ a69,
+ a70,
+ a71,
+ a72,
+ a73,
+ a74,
+ a75,
+ a76,
+ a77,
+ a78,
+ a79,
+ a80,
+ a81,
+ a82,
+ a83,
+ a84,
+ a85,
+ a86,
+ a87,
+ a88,
+ a89,
+ a90,
+ a91,
+ a92,
+ a93,
+ a94,
+ a95,
+ a96,
+ a97,
+ a98,
+ a99,
+ a100,
+ a101,
+ a102,
+ a103,
+ a104,
+ a105,
+ a106,
+ a107,
+ a108,
+ a109,
+ a110,
+ a111,
+ a112,
+ a113,
+ a114,
+ a115,
+ a116,
+ a117,
+ a118,
+ a119,
+ a120,
+ a121,
+ a122,
+ a123,
+ a124,
+ a125,
+ a126,
+ a127);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+ Expect.equals(a3, result.a3);
+ Expect.equals(a4, result.a4);
+ Expect.equals(a5, result.a5);
+ Expect.equals(a6, result.a6);
+ Expect.equals(a7, result.a7);
+ Expect.equals(a8, result.a8);
+ Expect.equals(a9, result.a9);
+ Expect.equals(a10, result.a10);
+ Expect.equals(a11, result.a11);
+ Expect.equals(a12, result.a12);
+ Expect.equals(a13, result.a13);
+ Expect.equals(a14, result.a14);
+ Expect.equals(a15, result.a15);
+ Expect.equals(a16, result.a16);
+ Expect.equals(a17, result.a17);
+ Expect.equals(a18, result.a18);
+ Expect.equals(a19, result.a19);
+ Expect.equals(a20, result.a20);
+ Expect.equals(a21, result.a21);
+ Expect.equals(a22, result.a22);
+ Expect.equals(a23, result.a23);
+ Expect.equals(a24, result.a24);
+ Expect.equals(a25, result.a25);
+ Expect.equals(a26, result.a26);
+ Expect.equals(a27, result.a27);
+ Expect.equals(a28, result.a28);
+ Expect.equals(a29, result.a29);
+ Expect.equals(a30, result.a30);
+ Expect.equals(a31, result.a31);
+ Expect.equals(a32, result.a32);
+ Expect.equals(a33, result.a33);
+ Expect.equals(a34, result.a34);
+ Expect.equals(a35, result.a35);
+ Expect.equals(a36, result.a36);
+ Expect.equals(a37, result.a37);
+ Expect.equals(a38, result.a38);
+ Expect.equals(a39, result.a39);
+ Expect.equals(a40, result.a40);
+ Expect.equals(a41, result.a41);
+ Expect.equals(a42, result.a42);
+ Expect.equals(a43, result.a43);
+ Expect.equals(a44, result.a44);
+ Expect.equals(a45, result.a45);
+ Expect.equals(a46, result.a46);
+ Expect.equals(a47, result.a47);
+ Expect.equals(a48, result.a48);
+ Expect.equals(a49, result.a49);
+ Expect.equals(a50, result.a50);
+ Expect.equals(a51, result.a51);
+ Expect.equals(a52, result.a52);
+ Expect.equals(a53, result.a53);
+ Expect.equals(a54, result.a54);
+ Expect.equals(a55, result.a55);
+ Expect.equals(a56, result.a56);
+ Expect.equals(a57, result.a57);
+ Expect.equals(a58, result.a58);
+ Expect.equals(a59, result.a59);
+ Expect.equals(a60, result.a60);
+ Expect.equals(a61, result.a61);
+ Expect.equals(a62, result.a62);
+ Expect.equals(a63, result.a63);
+ Expect.equals(a64, result.a64);
+ Expect.equals(a65, result.a65);
+ Expect.equals(a66, result.a66);
+ Expect.equals(a67, result.a67);
+ Expect.equals(a68, result.a68);
+ Expect.equals(a69, result.a69);
+ Expect.equals(a70, result.a70);
+ Expect.equals(a71, result.a71);
+ Expect.equals(a72, result.a72);
+ Expect.equals(a73, result.a73);
+ Expect.equals(a74, result.a74);
+ Expect.equals(a75, result.a75);
+ Expect.equals(a76, result.a76);
+ Expect.equals(a77, result.a77);
+ Expect.equals(a78, result.a78);
+ Expect.equals(a79, result.a79);
+ Expect.equals(a80, result.a80);
+ Expect.equals(a81, result.a81);
+ Expect.equals(a82, result.a82);
+ Expect.equals(a83, result.a83);
+ Expect.equals(a84, result.a84);
+ Expect.equals(a85, result.a85);
+ Expect.equals(a86, result.a86);
+ Expect.equals(a87, result.a87);
+ Expect.equals(a88, result.a88);
+ Expect.equals(a89, result.a89);
+ Expect.equals(a90, result.a90);
+ Expect.equals(a91, result.a91);
+ Expect.equals(a92, result.a92);
+ Expect.equals(a93, result.a93);
+ Expect.equals(a94, result.a94);
+ Expect.equals(a95, result.a95);
+ Expect.equals(a96, result.a96);
+ Expect.equals(a97, result.a97);
+ Expect.equals(a98, result.a98);
+ Expect.equals(a99, result.a99);
+ Expect.equals(a100, result.a100);
+ Expect.equals(a101, result.a101);
+ Expect.equals(a102, result.a102);
+ Expect.equals(a103, result.a103);
+ Expect.equals(a104, result.a104);
+ Expect.equals(a105, result.a105);
+ Expect.equals(a106, result.a106);
+ Expect.equals(a107, result.a107);
+ Expect.equals(a108, result.a108);
+ Expect.equals(a109, result.a109);
+ Expect.equals(a110, result.a110);
+ Expect.equals(a111, result.a111);
+ Expect.equals(a112, result.a112);
+ Expect.equals(a113, result.a113);
+ Expect.equals(a114, result.a114);
+ Expect.equals(a115, result.a115);
+ Expect.equals(a116, result.a116);
+ Expect.equals(a117, result.a117);
+ Expect.equals(a118, result.a118);
+ Expect.equals(a119, result.a119);
+ Expect.equals(a120, result.a120);
+ Expect.equals(a121, result.a121);
+ Expect.equals(a122, result.a122);
+ Expect.equals(a123, result.a123);
+ Expect.equals(a124, result.a124);
+ Expect.equals(a125, result.a125);
+ Expect.equals(a126, result.a126);
+ Expect.equals(a127, result.a127);
+}
+
+final returnStructArgumentStruct1ByteInt = ffiTestFunctions.lookupFunction<
+ Struct1ByteInt Function(Struct1ByteInt),
+ Struct1ByteInt Function(
+ Struct1ByteInt)>("ReturnStructArgumentStruct1ByteInt");
+
+/// Test that a struct passed in as argument can be returned.
+/// Especially for ffi callbacks.
+/// Struct is passed in int registers in most ABIs.
+void testReturnStructArgumentStruct1ByteInt() {
+ Struct1ByteInt a0 = allocate<Struct1ByteInt>().ref;
+
+ a0.a0 = -1;
+
+ final result = returnStructArgumentStruct1ByteInt(a0);
+
+ print("result = $result");
+
+ Expect.equals(a0.a0, result.a0);
+
+ free(a0.addressOf);
+}
+
+final returnStructArgumentInt32x8Struct1ByteInt =
+ ffiTestFunctions.lookupFunction<
+ Struct1ByteInt Function(Int32, Int32, Int32, Int32, Int32, Int32, Int32,
+ Int32, Struct1ByteInt),
+ Struct1ByteInt Function(int, int, int, int, int, int, int, int,
+ Struct1ByteInt)>("ReturnStructArgumentInt32x8Struct1ByteInt");
+
+/// Test that a struct passed in as argument can be returned.
+/// Especially for ffi callbacks.
+/// Struct is passed on stack on all ABIs.
+void testReturnStructArgumentInt32x8Struct1ByteInt() {
+ int a0;
+ int a1;
+ int a2;
+ int a3;
+ int a4;
+ int a5;
+ int a6;
+ int a7;
+ Struct1ByteInt a8 = allocate<Struct1ByteInt>().ref;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+ a3 = 4;
+ a4 = -5;
+ a5 = 6;
+ a6 = -7;
+ a7 = 8;
+ a8.a0 = -9;
+
+ final result = returnStructArgumentInt32x8Struct1ByteInt(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ print("result = $result");
+
+ Expect.equals(a8.a0, result.a0);
+
+ free(a8.addressOf);
+}
+
+final returnStructArgumentStruct8BytesHomogeneousFloat =
+ ffiTestFunctions.lookupFunction<
+ Struct8BytesHomogeneousFloat Function(Struct8BytesHomogeneousFloat),
+ Struct8BytesHomogeneousFloat Function(
+ Struct8BytesHomogeneousFloat)>(
+ "ReturnStructArgumentStruct8BytesHomogeneousFloat");
+
+/// Test that a struct passed in as argument can be returned.
+/// Especially for ffi callbacks.
+/// Struct is passed in float registers in most ABIs.
+void testReturnStructArgumentStruct8BytesHomogeneousFloat() {
+ Struct8BytesHomogeneousFloat a0 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+
+ final result = returnStructArgumentStruct8BytesHomogeneousFloat(a0);
+
+ print("result = $result");
+
+ Expect.approxEquals(a0.a0, result.a0);
+ Expect.approxEquals(a0.a1, result.a1);
+
+ free(a0.addressOf);
+}
+
+final returnStructArgumentStruct20BytesHomogeneousInt32 =
+ ffiTestFunctions
+ .lookupFunction<
+ Struct20BytesHomogeneousInt32 Function(
+ Struct20BytesHomogeneousInt32),
+ Struct20BytesHomogeneousInt32 Function(
+ Struct20BytesHomogeneousInt32)>(
+ "ReturnStructArgumentStruct20BytesHomogeneousInt32");
+
+/// On arm64, both argument and return value are passed in by pointer.
+void testReturnStructArgumentStruct20BytesHomogeneousInt32() {
+ Struct20BytesHomogeneousInt32 a0 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+ a0.a3 = 4;
+ a0.a4 = -5;
+
+ final result = returnStructArgumentStruct20BytesHomogeneousInt32(a0);
+
+ print("result = $result");
+
+ Expect.equals(a0.a0, result.a0);
+ Expect.equals(a0.a1, result.a1);
+ Expect.equals(a0.a2, result.a2);
+ Expect.equals(a0.a3, result.a3);
+ Expect.equals(a0.a4, result.a4);
+
+ free(a0.addressOf);
+}
+
+final returnStructArgumentInt32x8Struct20BytesHomogeneou =
+ ffiTestFunctions.lookupFunction<
+ Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32,
+ Int32, Int32, Int32, Int32, Struct20BytesHomogeneousInt32),
+ Struct20BytesHomogeneousInt32 Function(int, int, int, int, int, int,
+ int, int, Struct20BytesHomogeneousInt32)>(
+ "ReturnStructArgumentInt32x8Struct20BytesHomogeneou");
+
+/// On arm64, both argument and return value are passed in by pointer.
+/// Ints exhaust registers, so that pointer is passed on stack.
+void testReturnStructArgumentInt32x8Struct20BytesHomogeneou() {
+ int a0;
+ int a1;
+ int a2;
+ int a3;
+ int a4;
+ int a5;
+ int a6;
+ int a7;
+ Struct20BytesHomogeneousInt32 a8 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+ a3 = 4;
+ a4 = -5;
+ a5 = 6;
+ a6 = -7;
+ a7 = 8;
+ a8.a0 = -9;
+ a8.a1 = 10;
+ a8.a2 = -11;
+ a8.a3 = 12;
+ a8.a4 = -13;
+
+ final result = returnStructArgumentInt32x8Struct20BytesHomogeneou(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ print("result = $result");
+
+ Expect.equals(a8.a0, result.a0);
+ Expect.equals(a8.a1, result.a1);
+ Expect.equals(a8.a2, result.a2);
+ Expect.equals(a8.a3, result.a3);
+ Expect.equals(a8.a4, result.a4);
+
+ free(a8.addressOf);
+}
+
+final returnStructAlignmentInt16 = ffiTestFunctions.lookupFunction<
+ StructAlignmentInt16 Function(Int8, Int16, Int8),
+ StructAlignmentInt16 Function(int, int, int)>("ReturnStructAlignmentInt16");
+
+/// Test alignment and padding of 16 byte int within struct.
+void testReturnStructAlignmentInt16() {
+ int a0;
+ int a1;
+ int a2;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+
+ final result = returnStructAlignmentInt16(a0, a1, a2);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+}
+
+final returnStructAlignmentInt32 = ffiTestFunctions.lookupFunction<
+ StructAlignmentInt32 Function(Int8, Int32, Int8),
+ StructAlignmentInt32 Function(int, int, int)>("ReturnStructAlignmentInt32");
+
+/// Test alignment and padding of 32 byte int within struct.
+void testReturnStructAlignmentInt32() {
+ int a0;
+ int a1;
+ int a2;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+
+ final result = returnStructAlignmentInt32(a0, a1, a2);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+}
+
+final returnStructAlignmentInt64 = ffiTestFunctions.lookupFunction<
+ StructAlignmentInt64 Function(Int8, Int64, Int8),
+ StructAlignmentInt64 Function(int, int, int)>("ReturnStructAlignmentInt64");
+
+/// Test alignment and padding of 64 byte int within struct.
+void testReturnStructAlignmentInt64() {
+ int a0;
+ int a1;
+ int a2;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+
+ final result = returnStructAlignmentInt64(a0, a1, a2);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+}
diff --git a/tests/ffi/generator/c_types.dart b/tests/ffi/generator/c_types.dart
new file mode 100644
index 0000000..f2948fa
--- /dev/null
+++ b/tests/ffi/generator/c_types.dart
@@ -0,0 +1,299 @@
+// Copyright (c) 2020, 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 'utils.dart';
+
+const int8 = FundamentalType(PrimitiveType.int8);
+const int16 = FundamentalType(PrimitiveType.int16);
+const int32 = FundamentalType(PrimitiveType.int32);
+const int64 = FundamentalType(PrimitiveType.int64);
+const uint8 = FundamentalType(PrimitiveType.uint8);
+const uint16 = FundamentalType(PrimitiveType.uint16);
+const uint32 = FundamentalType(PrimitiveType.uint32);
+const uint64 = FundamentalType(PrimitiveType.uint64);
+const intptr = FundamentalType(PrimitiveType.intptr);
+const float = FundamentalType(PrimitiveType.float);
+const double_ = FundamentalType(PrimitiveType.double_);
+
+enum PrimitiveType {
+ int8,
+ int16,
+ int32,
+ int64,
+ uint8,
+ uint16,
+ uint32,
+ uint64,
+ intptr,
+ float,
+ double_,
+}
+
+const primitiveNames = [
+ "int8",
+ "int16",
+ "int32",
+ "int64",
+ "uint8",
+ "uint16",
+ "uint32",
+ "uint64",
+ "intptr",
+ "float",
+ "double",
+];
+
+const intptrSize = -1;
+const primitiveSizesInBytes = [1, 2, 4, 8, 1, 2, 4, 8, intptrSize, 4, 8];
+
+abstract class CType {
+ String get cType;
+ String get dartCType;
+ String get dartType;
+ String get dartStructFieldAnnotation;
+
+ /// Has a known [size] that is the same for all architectures.
+ bool get hasSize;
+
+ /// Get a size in bytes that is the same on all architectures.
+ int get size;
+
+ String toString() => dartCType;
+
+ const CType();
+}
+
+class FundamentalType extends CType {
+ final PrimitiveType primitive;
+
+ const FundamentalType(this.primitive);
+
+ bool get isFloatingPoint =>
+ primitive == PrimitiveType.float || primitive == PrimitiveType.double_;
+ bool get isInteger => !isFloatingPoint;
+ bool get isUnsigned =>
+ primitive == PrimitiveType.uint8 ||
+ primitive == PrimitiveType.uint16 ||
+ primitive == PrimitiveType.uint32 ||
+ primitive == PrimitiveType.uint64;
+ bool get isSigned => !isUnsigned;
+
+ String get name => primitiveNames[primitive.index];
+
+ String get cType => "${name}${isInteger ? "_t" : ""}";
+ String get dartCType => name.upperCaseFirst();
+ String get dartType => isInteger ? "int" : "double";
+ String get dartStructFieldAnnotation => "@${dartCType}()";
+ bool get hasSize => primitive != PrimitiveType.intptr;
+ int get size {
+ if (!hasSize) {
+ throw "Size unknown.";
+ }
+ return primitiveSizesInBytes[primitive.index];
+ }
+}
+
+class PointerType extends CType {
+ final CType pointerTo;
+
+ PointerType(this.pointerTo);
+
+ String get cType => "${pointerTo.cType}*";
+ String get dartCType => "Pointer<${pointerTo.dartCType}>";
+ String get dartType => "Pointer<${pointerTo.dartType}>";
+ String get dartStructFieldAnnotation => "";
+ bool get hasSize => false;
+ int get size => throw "Size unknown";
+}
+
+/// Used to give [StructType] fields and [FunctionType] arguments names.
+class Member {
+ final CType type;
+ final String name;
+
+ Member(this.type, this.name);
+
+ String dartStructField(bool nnbd) {
+ final modifier = nnbd ? "external" : "";
+ return "${type.dartStructFieldAnnotation} $modifier ${type.dartType} $name;";
+ }
+
+ String get cStructField => "${type.cType} $name;";
+
+ String toString() => "$type $name";
+}
+
+List<Member> generateMemberNames(List<CType> memberTypes) {
+ int index = 0;
+ List<Member> result = [];
+ for (final type in memberTypes) {
+ result.add(Member(type, "a$index"));
+ index++;
+ }
+ return result;
+}
+
+class StructType extends CType {
+ final List<Member> members;
+
+ /// To disambiguate same size structs.
+ final String suffix;
+
+ StructType(List<CType> memberTypes)
+ : this.members = generateMemberNames(memberTypes),
+ this.suffix = "";
+ StructType.disambiguate(List<CType> memberTypes, this.suffix)
+ : this.members = generateMemberNames(memberTypes);
+
+ List<CType> get memberTypes => members.map((a) => a.type).toList();
+
+ String get cType => name;
+ String get dartCType => name;
+ String get dartType => name;
+ String get dartStructFieldAnnotation => "";
+
+ bool get hasSize =>
+ !memberTypes.map((e) => e.hasSize).contains(false) && !hasPadding;
+ int get size => memberTypes.fold(0, (int acc, e) => acc + e.size);
+
+ /// Rough approximation, to not redo all ABI logic here.
+ bool get hasPadding =>
+ members.length < 2 ? false : members[0].type.size < members[1].type.size;
+
+ bool get hasNestedStructs =>
+ members.map((e) => e.type is StructType).contains(true);
+
+ /// All members have the same type.
+ bool get isHomogeneous => memberTypes.toSet().length == 1;
+
+ /// All members have a floating point type.
+ bool get isOnlyFloatingPoint => !memberTypes.map((e) {
+ if (e is FundamentalType) {
+ return e.isFloatingPoint;
+ }
+ if (e is StructType) {
+ return e.isOnlyFloatingPoint;
+ }
+ }).contains(false);
+
+ /// All members have a integer type.
+ bool get isOnlyInteger => !memberTypes.map((e) {
+ if (e is FundamentalType) {
+ return e.isInteger;
+ }
+ if (e is StructType) {
+ return e.isOnlyInteger;
+ }
+ }).contains(false);
+
+ bool get isMixed => !isOnlyInteger && !isOnlyFloatingPoint;
+
+ String get name {
+ String result = "Struct";
+ if (hasSize) {
+ result += "${size}Byte" + (size != 1 ? "s" : "");
+ }
+ if (hasNestedStructs) {
+ result += "Nested";
+ }
+ if (members.length == 0) {
+ // No suffix.
+ } else if (hasPadding) {
+ result += "Alignment${memberTypes[1].dartCType}";
+ } else if (isHomogeneous && members.length > 1 && !hasNestedStructs) {
+ result += "Homogeneous${memberTypes.first.dartCType}";
+ } else if (isOnlyFloatingPoint) {
+ result += "Float";
+ } else if (isOnlyInteger) {
+ result += "Int";
+ } else {
+ result += "Mixed";
+ }
+ result += suffix;
+ return result;
+ }
+}
+
+class FunctionType extends CType {
+ final List<Member> arguments;
+ final CType returnValue;
+ final String reason;
+
+ List<CType> get argumentTypes => arguments.map((a) => a.type).toList();
+
+ FunctionType(List<CType> argumentTypes, this.returnValue, this.reason)
+ : this.arguments = generateMemberNames(argumentTypes);
+
+ String get cType =>
+ throw "Are not represented without function or variable name in C.";
+
+ String get dartCType {
+ final argumentsDartCType = argumentTypes.map((e) => e.dartCType).join(", ");
+ return "${returnValue.dartCType} Function($argumentsDartCType)";
+ }
+
+ String get dartType {
+ final argumentsDartType = argumentTypes.map((e) => e.dartType).join(", ");
+ return "${returnValue.dartType} Function($argumentsDartType)";
+ }
+
+ String get dartStructFieldAnnotation => throw "No nested function pointers.";
+
+ bool get hasSize => false;
+ int get size => throw "Unknown size.";
+
+ /// Group consecutive [arguments] by same type.
+ ///
+ /// Used for naming.
+ List<List<Member>> get argumentsGrouped {
+ List<List<Member>> result = [];
+ for (final a in arguments) {
+ if (result.isEmpty) {
+ result.add([a]);
+ } else if (result.last.first.type.dartCType == a.type.dartCType) {
+ result.last.add(a);
+ } else {
+ result.add([a]);
+ }
+ }
+ return result;
+ }
+
+ /// A suitable name based on the signature.
+ String get cName {
+ String result = "";
+ if (arguments.containsStructs && returnValue is FundamentalType) {
+ result = "Pass";
+ } else if (returnValue is StructType &&
+ argumentTypes.contains(returnValue)) {
+ result = "ReturnStructArgument";
+ } else if (returnValue is StructType) {
+ if (arguments.length == (returnValue as StructType).members.length) {
+ return "Return${returnValue.dartCType}";
+ }
+ } else {
+ result = "Uncategorized";
+ }
+
+ for (final group in argumentsGrouped) {
+ result += group.first.type.dartCType;
+ if (group.length > 1) {
+ result += "x${group.length}";
+ }
+ }
+ return result.limitTo(50);
+ }
+
+ String get dartTestName => "test$cName";
+
+ String get dartName => cName.lowerCaseFirst();
+
+ /// Only valid for [TestType.structReturnArgument].
+ Member get structReturnArgument =>
+ arguments.firstWhere((a) => a.type == returnValue);
+}
+
+extension MemberList on List<Member> {
+ bool get containsStructs => map((m) => m.type is StructType).contains(true);
+}
diff --git a/tests/ffi/generator/structs_by_value_tests_confguration.dart b/tests/ffi/generator/structs_by_value_tests_confguration.dart
new file mode 100644
index 0000000..487a68e
--- /dev/null
+++ b/tests/ffi/generator/structs_by_value_tests_confguration.dart
@@ -0,0 +1,373 @@
+// Copyright (c) 2020, 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 'c_types.dart';
+
+final functions = [
+ FunctionType(List.filled(10, struct1byteInt), int64, """
+Smallest struct with data.
+10 struct arguments will exhaust available registers."""),
+ FunctionType(List.filled(10, struct3bytesInt), int64, """
+Not a multiple of word size, not a power of two.
+10 struct arguments will exhaust available registers."""),
+ FunctionType(List.filled(10, struct4bytesInt), int64, """
+Exactly word size on 32-bit architectures.
+10 struct arguments will exhaust available registers."""),
+ FunctionType(List.filled(10, struct7bytesInt), int64, """
+Sub word size on 64 bit architectures.
+10 struct arguments will exhaust available registers."""),
+ FunctionType(List.filled(10, struct8bytesInt), int64, """
+Exactly word size struct on 64bit architectures.
+10 struct arguments will exhaust available registers."""),
+ FunctionType(List.filled(10, struct8bytesFloat), float, """
+Arguments passed in FP registers as long as they fit.
+10 struct arguments will exhaust available registers."""),
+ FunctionType(List.filled(10, struct8BytesMixed), float, """
+On x64, arguments go in int registers because it is not only float.
+10 struct arguments will exhaust available registers."""),
+ FunctionType(List.filled(10, struct9bytesInt), int64, """
+Argument is a single byte over a multiple of word size.
+10 struct arguments will exhaust available registers.
+Tests upper bytes in the integer registers that are partly filled.
+Tests stack alignment of non word size stack arguments."""),
+ FunctionType(List.filled(10, struct9bytesInt2), int64, """
+Argument is a single byte over a multiple of word size.
+10 struct arguments will exhaust available registers.
+Struct only has 1-byte aligned fields to test struct alignment itself.
+"""),
+ FunctionType(List.filled(6, struct12bytesFloat), float, """
+Arguments in FPU registers on arm hardfp and arm64.
+Struct arguments will exhaust available registers, and leave some empty.
+The last argument is to test whether arguments are backfilled."""),
+ FunctionType(List.filled(5, struct16bytesFloat), float, """
+On Linux x64 argument is transferred on stack because it is over 16 bytes.
+Arguments in FPU registers on arm hardfp and arm64.
+5 struct arguments will exhaust available registers."""),
+ FunctionType(List.filled(10, struct16bytesMixed), double_, """
+On x64, arguments are split over FP and int registers.
+On x64, it will exhaust the integer registers with the 6th argument.
+The rest goes on the stack.
+On arm, arguments are 8 byte aligned."""),
+ FunctionType(List.filled(10, struct16bytesMixed2), float, """
+On x64, arguments are split over FP and int registers.
+On x64, it will exhaust the integer registers with the 6th argument.
+The rest goes on the stack.
+On arm, arguments are 4 byte aligned."""),
+ FunctionType(List.filled(10, struct17bytesInt), int64, """
+Arguments are passed as pointer to copy on arm64.
+Tests that the memory allocated for copies are rounded up to word size."""),
+ FunctionType(List.filled(10, struct19bytesInt), int64, """
+The minimum alignment of this struct is only 1 byte based on its fields.
+Test that the memory backing these structs is extended to the right size.
+"""),
+ FunctionType(List.filled(10, struct20bytesInt), int32, """
+Argument too big to go into integer registers on arm64.
+The arguments are passed as pointers to copies.
+The amount of arguments exhausts the number of integer registers, such that
+pointers to copies are also passed on the stack."""),
+ FunctionType(
+ [struct20bytesFloat],
+ float,
+ """
+Argument too big to go into FPU registers in hardfp and arm64."""),
+ FunctionType(List.filled(5, struct32bytesDouble), double_, """
+Arguments in FPU registers on arm64.
+5 struct arguments will exhaust available registers."""),
+ FunctionType(
+ [struct40bytesDouble],
+ double_,
+ """
+Argument too big to go into FPU registers in arm64."""),
+ FunctionType(
+ [struct1024bytesInt],
+ uint64,
+ """
+Test 1kb struct."""),
+ FunctionType(
+ [
+ float,
+ struct16bytesFloat,
+ float,
+ struct16bytesFloat,
+ float,
+ struct16bytesFloat,
+ float,
+ struct16bytesFloat,
+ float
+ ],
+ float,
+ """
+Tests the alignment of structs in FPU registers and backfilling."""),
+ FunctionType(
+ [
+ float,
+ struct32bytesDouble,
+ float,
+ struct32bytesDouble,
+ float,
+ struct32bytesDouble,
+ float,
+ struct32bytesDouble,
+ float
+ ],
+ double_,
+ """
+Tests the alignment of structs in FPU registers and backfilling."""),
+ FunctionType(
+ [
+ int8,
+ struct16bytesMixed,
+ int8,
+ struct16bytesMixed,
+ int8,
+ struct16bytesMixed,
+ int8,
+ struct16bytesMixed,
+ int8
+ ],
+ double_,
+ """
+Tests the alignment of structs in integers registers and on the stack.
+Arm32 aligns this struct at 8.
+Also, arm32 allocates the second struct partially in registers, partially
+on stack.
+Test backfilling of integer registers."""),
+ FunctionType(
+ [
+ double_,
+ double_,
+ double_,
+ double_,
+ double_,
+ double_,
+ struct16bytesMixed,
+ struct16bytesMixed,
+ struct16bytesMixed,
+ struct16bytesMixed,
+ int32,
+ ],
+ double_,
+ """
+On Linux x64, it will exhaust xmm registers first, after 6 doubles and 2
+structs. The rest of the structs will go on the stack.
+The int will be backfilled into the int register."""),
+ FunctionType(
+ [
+ int32,
+ int32,
+ int32,
+ int32,
+ struct16bytesMixed,
+ struct16bytesMixed,
+ struct16bytesMixed,
+ struct16bytesMixed,
+ double_,
+ ],
+ double_,
+ """
+On Linux x64, it will exhaust int registers first.
+The rest of the structs will go on the stack.
+The double will be backfilled into the xmm register."""),
+ FunctionType(
+ [
+ struct40bytesDouble,
+ struct4bytesInt,
+ struct8bytesFloat,
+ ],
+ double_,
+ """
+On various architectures, first struct is allocated on stack.
+Check that the other two arguments are allocated on registers."""),
+ FunctionType(
+ [structAlignmentInt16],
+ int64,
+ """
+Test alignment and padding of 16 byte int within struct."""),
+ FunctionType(
+ [structAlignmentInt32],
+ int64,
+ """
+Test alignment and padding of 32 byte int within struct."""),
+ FunctionType(
+ [structAlignmentInt64],
+ int64,
+ """
+Test alignment and padding of 64 byte int within struct."""),
+ FunctionType(struct1byteInt.memberTypes, struct1byteInt, """
+Smallest struct with data."""),
+ FunctionType(struct3bytesInt.memberTypes, struct3bytesInt, """
+Smaller than word size return value on all architectures."""),
+ FunctionType(struct4bytesInt.memberTypes, struct4bytesInt, """
+Word size return value on 32 bit architectures.."""),
+ FunctionType(struct7bytesInt.memberTypes, struct7bytesInt, """
+Non-wordsize return value."""),
+ FunctionType(struct8bytesInt.memberTypes, struct8bytesInt, """
+Return value in integer registers on many architectures."""),
+ FunctionType(struct8bytesFloat.memberTypes, struct8bytesFloat, """
+Return value in FP registers on many architectures."""),
+ FunctionType(struct8BytesMixed.memberTypes, struct8BytesMixed, """
+Return value split over FP and integer register in x64."""),
+ FunctionType(struct9bytesInt.memberTypes, struct9bytesInt, """
+Return value in two integer registers on x64.
+The second register only contains a single byte."""),
+ FunctionType(struct9bytesInt2.memberTypes, struct9bytesInt2, """
+The minimum alignment of this struct is only 1 byte based on its fields.
+Test that the memory backing these structs is the right size and that
+dart:ffi trampolines do not write outside this size."""),
+ FunctionType(struct12bytesFloat.memberTypes, struct12bytesFloat, """
+Return value in FPU registers, but does not use all registers on arm hardfp
+and arm64."""),
+ FunctionType(struct16bytesFloat.memberTypes, struct16bytesFloat, """
+Return value in FPU registers on arm hardfp and arm64."""),
+ FunctionType(struct16bytesMixed.memberTypes, struct16bytesMixed, """
+Return value split over FP and integer register in x64."""),
+ FunctionType(struct16bytesMixed2.memberTypes, struct16bytesMixed2, """
+Return value split over FP and integer register in x64.
+The integer register contains half float half int."""),
+ FunctionType(struct17bytesInt.memberTypes, struct17bytesInt, """
+Rerturn value returned in preallocated space passed by pointer on most ABIs.
+Is non word size on purpose, to test that structs are rounded up to word size
+on all ABIs."""),
+ FunctionType(struct19bytesInt.memberTypes, struct19bytesInt, """
+The minimum alignment of this struct is only 1 byte based on its fields.
+Test that the memory backing these structs is the right size and that
+dart:ffi trampolines do not write outside this size."""),
+ FunctionType(struct20bytesInt.memberTypes, struct20bytesInt, """
+Return value too big to go in cpu registers on arm64."""),
+ FunctionType(struct20bytesFloat.memberTypes, struct20bytesFloat, """
+Return value too big to go in FPU registers on x64, arm hardfp and arm64."""),
+ FunctionType(struct32bytesDouble.memberTypes, struct32bytesDouble, """
+Return value in FPU registers on arm64."""),
+ FunctionType(struct40bytesDouble.memberTypes, struct40bytesDouble, """
+Return value too big to go in FPU registers on arm64."""),
+ FunctionType(struct1024bytesInt.memberTypes, struct1024bytesInt, """
+Test 1kb struct."""),
+ FunctionType(
+ [struct1byteInt],
+ struct1byteInt,
+ """
+Test that a struct passed in as argument can be returned.
+Especially for ffi callbacks.
+Struct is passed in int registers in most ABIs."""),
+ FunctionType(
+ [int32, int32, int32, int32, int32, int32, int32, int32, struct1byteInt],
+ struct1byteInt,
+ """
+Test that a struct passed in as argument can be returned.
+Especially for ffi callbacks.
+Struct is passed on stack on all ABIs."""),
+ FunctionType(
+ [struct8bytesFloat],
+ struct8bytesFloat,
+ """
+Test that a struct passed in as argument can be returned.
+Especially for ffi callbacks.
+Struct is passed in float registers in most ABIs."""),
+ FunctionType(
+ [struct20bytesInt],
+ struct20bytesInt,
+ """
+On arm64, both argument and return value are passed in by pointer."""),
+ FunctionType(
+ [
+ int32,
+ int32,
+ int32,
+ int32,
+ int32,
+ int32,
+ int32,
+ int32,
+ struct20bytesInt
+ ],
+ struct20bytesInt,
+ """
+On arm64, both argument and return value are passed in by pointer.
+Ints exhaust registers, so that pointer is passed on stack."""),
+ FunctionType(structAlignmentInt16.memberTypes, structAlignmentInt16, """
+Test alignment and padding of 16 byte int within struct."""),
+ FunctionType(structAlignmentInt32.memberTypes, structAlignmentInt32, """
+Test alignment and padding of 32 byte int within struct."""),
+ FunctionType(structAlignmentInt64.memberTypes, structAlignmentInt64, """
+Test alignment and padding of 64 byte int within struct."""),
+];
+
+final structs = [
+ struct0bytes,
+ struct1byteInt,
+ struct3bytesInt,
+ struct4bytesInt,
+ struct7bytesInt,
+ struct8bytesInt,
+ struct8bytesFloat,
+ struct8BytesMixed,
+ struct9bytesInt,
+ struct9bytesInt2,
+ struct12bytesFloat,
+ struct16bytesFloat,
+ struct16bytesMixed,
+ struct16bytesMixed2,
+ struct17bytesInt,
+ struct19bytesInt,
+ struct20bytesInt,
+ struct20bytesFloat,
+ struct32bytesDouble,
+ struct40bytesDouble,
+ struct1024bytesInt,
+ structAlignmentInt16,
+ structAlignmentInt32,
+ structAlignmentInt64,
+];
+
+/// Using empty structs is undefined behavior in C.
+final struct0bytes = StructType([]);
+
+final struct1byteInt = StructType([int8]);
+final struct3bytesInt = StructType([int16, int8]);
+final struct4bytesInt = StructType([int16, int16]);
+final struct7bytesInt = StructType([int32, int16, int8]);
+final struct8bytesInt = StructType([int16, int16, int32]);
+final struct8bytesFloat = StructType([float, float]);
+final struct8BytesMixed = StructType([float, int16, int16]);
+final struct9bytesInt = StructType([int64, int8]);
+final struct9bytesInt2 = StructType.disambiguate(List.filled(9, uint8), "2");
+final struct12bytesFloat = StructType([float, float, float]);
+
+/// The largest homogenous float that goes into FPU registers on softfp and
+/// arm64.
+final struct16bytesFloat = StructType([float, float, float, float]);
+
+/// This struct will be 8 byte aligned on arm.
+final struct16bytesMixed = StructType([double_, int64]);
+
+/// This struct will be 4 byte aligned on arm.
+final struct16bytesMixed2 =
+ StructType.disambiguate([float, float, float, int32], "2");
+
+final struct17bytesInt = StructType([int64, int64, int8]);
+
+/// This struct has only 1 byte field-alignmnent requirements.
+final struct19bytesInt = StructType(List.filled(19, uint8));
+
+/// The first homogenous integer struct that does not go into registers
+/// anymore on arm64.
+final struct20bytesInt = StructType([int32, int32, int32, int32, int32]);
+
+/// The first homogenous float that does not go into FPU registers anymore on
+/// softfp and arm64.
+final struct20bytesFloat = StructType([float, float, float, float, float]);
+
+/// Largest homogenous doubles in arm64 that goes into FPU registers.
+final struct32bytesDouble = StructType([double_, double_, double_, double_]);
+
+/// The first homogenous doubles that does not go into FPU registers anymore on
+/// arm64.
+final struct40bytesDouble =
+ StructType([double_, double_, double_, double_, double_]);
+
+final struct1024bytesInt = StructType(List.filled(128, uint64));
+
+final structAlignmentInt16 = StructType([int8, int16, int8]);
+final structAlignmentInt32 = StructType([int8, int32, int8]);
+final structAlignmentInt64 = StructType([int8, int64, int8]);
diff --git a/tests/ffi/generator/structs_by_value_tests_generator.dart b/tests/ffi/generator/structs_by_value_tests_generator.dart
new file mode 100644
index 0000000..e233753
--- /dev/null
+++ b/tests/ffi/generator/structs_by_value_tests_generator.dart
@@ -0,0 +1,930 @@
+// Copyright (c) 2020, 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 'dart:io';
+
+import 'c_types.dart';
+import 'structs_by_value_tests_confguration.dart';
+import 'utils.dart';
+
+/// The test type determines how to convert the arguments into return values
+/// such that the caller knows what to check.
+enum TestType {
+ /// Tested by getting all the individual fields out of the structs and
+ /// summing their values.
+ structArguments,
+
+ /// Tested by passing assigning the arguments to the struct fields.
+ structReturn,
+
+ /// Tested by returning the struct passed in.
+ structReturnArgument,
+}
+
+extension on FunctionType {
+ TestType get testType {
+ if (arguments.containsStructs && returnValue is FundamentalType) {
+ return TestType.structArguments;
+ }
+ if (returnValue is StructType && argumentTypes.contains(returnValue)) {
+ return TestType.structReturnArgument;
+ }
+ if (returnValue is StructType) {
+ if (arguments.length == (returnValue as StructType).members.length) {
+ return TestType.structReturn;
+ }
+ }
+ throw Exception("Unknown test type: $this");
+ }
+}
+
+/// We use the class structure as an algebraic data type in order to keep the
+/// relevant parts of the code generation closer together.
+extension on CType {
+ /// The part of the cout expression after `std::cout` and before the `;`.
+ String coutExpression(String variableName) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ if (this == uint8 || this == int8) {
+ return "<< static_cast<int>($variableName)";
+ }
+ return "<< $variableName";
+
+ case StructType:
+ final this_ = this as StructType;
+ return this_.members.coutExpression("$variableName.");
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+
+ /// A statement recursively outputting all members.
+ String coutStatement(String variableName) {
+ final coutExpr = this.coutExpression(variableName);
+ return 'std::cout << "$variableName = " $coutExpr << "\\n";';
+ }
+}
+
+extension on List<Member> {
+ /// The part of the cout expression after `std::cout` and before the `;`.
+ String coutExpression([String namePrefix = ""]) {
+ String result = '<< "("';
+ result += this
+ .map((m) => m.type.coutExpression("$namePrefix${m.name}"))
+ .join('<< ", "');
+ result += '<< ")"';
+ return result.trimCouts();
+ }
+}
+
+extension on CType {
+ /// A list of statements adding all members recurisvely to `result`.
+ ///
+ /// Both valid in Dart and C.
+ String addToResultStatements(String variableName) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ return "result += $variableName;\n";
+
+ case StructType:
+ final this_ = this as StructType;
+ return this_.members.addToResultStatements("$variableName.");
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+}
+
+extension on List<Member> {
+ /// A list of statements adding all members recurisvely to `result`.
+ ///
+ /// Both valid in Dart and C.
+ String addToResultStatements([String namePrefix = ""]) {
+ return map((m) => m.type.addToResultStatements("$namePrefix${m.name}"))
+ .join();
+ }
+}
+
+extension on CType {
+ /// A list of statements recursively assigning all members with [a].
+ ///
+ /// Both valid in Dart and C.
+ String assignValueStatements(ArgumentValueAssigner a, String variableName) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ final this_ = this as FundamentalType;
+ return "$variableName = ${a.nextValue(this_)};\n";
+
+ case StructType:
+ final this_ = this as StructType;
+ return this_.members.assignValueStatements(a, "$variableName.");
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+
+ /// A list of statements recursively coping all members from [source].
+ ///
+ /// Both valid in Dart and C.
+ String copyValueStatements(String source, String destination) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ return "$destination = $source;\n";
+
+ case StructType:
+ final this_ = this as StructType;
+ return this_.members.copyValueStatements("$source.", "$destination.");
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+}
+
+extension on List<Member> {
+ /// A list of statements recursively assigning all members with [a].
+ ///
+ /// Both valid in Dart and C.
+ String assignValueStatements(ArgumentValueAssigner a,
+ [String namePrefix = ""]) {
+ return map((m) => m.type.assignValueStatements(a, "$namePrefix${m.name}"))
+ .join();
+ }
+
+ /// A list of statements recursively coping all members from [source].
+ ///
+ /// Both valid in Dart and C.
+ String copyValueStatements([sourcePrefix = "", destinationPrefix = ""]) {
+ return map((m) => m.type.copyValueStatements(
+ "$sourcePrefix${m.name}", "$destinationPrefix${m.name}")).join();
+ }
+}
+
+/// A helper class that assigns values to fundamental types.
+///
+/// Also keeps track of a sum of all values, to be used for testing the result.
+class ArgumentValueAssigner {
+ int i = 1;
+ int sum = 0;
+ String nextValue(FundamentalType type) {
+ int argumentValue = i;
+ i++;
+ if (type.isSigned && i % 2 == 0) {
+ argumentValue = -argumentValue;
+ }
+ sum += argumentValue;
+ if (type.isFloatingPoint) {
+ return argumentValue.toDouble().toString();
+ } else {
+ return argumentValue.toString();
+ }
+ }
+
+ String sumValue(FundamentalType type) {
+ if (type.isFloatingPoint) {
+ return sum.toDouble().toString();
+ } else {
+ return sum.toString();
+ }
+ }
+}
+
+extension on CType {
+ /// A list of Dart statements recursively allocating all members.
+ String dartAllocateStatements(String variableName) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ return "${dartType} ${variableName};\n";
+
+ case StructType:
+ return "${dartType} ${variableName} = allocate<$dartType>().ref;\n";
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+
+ /// A list of Dart statements allocating as zero or nullptr.
+ String dartAllocateZeroStatements(String variableName) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ final this_ = this as FundamentalType;
+ if (this_.isInteger) {
+ return "${dartType} ${variableName} = 0;\n";
+ }
+ return "${dartType} ${variableName} = 0.0;\n";
+
+ case StructType:
+ return "${dartType} ${variableName} = ${dartType}();\n";
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+}
+
+extension on List<Member> {
+ /// A list of Dart statements recursively allocating all members.
+ String dartAllocateStatements([String namePrefix = ""]) {
+ return map((m) => m.type.dartAllocateStatements("$namePrefix${m.name}"))
+ .join();
+ }
+
+ /// A list of Dart statements as zero or nullptr.
+ String dartAllocateZeroStatements([String namePrefix = ""]) {
+ return map((m) => m.type.dartAllocateZeroStatements("$namePrefix${m.name}"))
+ .join();
+ }
+}
+
+extension on CType {
+ /// A list of Dart statements recursively freeing all members.
+ String dartFreeStatements(String variableName) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ return "";
+
+ case StructType:
+ return "free($variableName.addressOf);\n";
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+}
+
+extension on List<Member> {
+ /// A list of Dart statements recursively freeing all members.
+ String dartFreeStatements([String namePrefix = ""]) {
+ return map((m) => m.type.dartFreeStatements("$namePrefix${m.name}")).join();
+ }
+}
+
+extension on CType {
+ /// A list of C statements recursively allocating all members.
+ String cAllocateStatements(String variableName) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ case StructType:
+ return "${cType} ${variableName};\n";
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+}
+
+extension on List<Member> {
+ /// A list of C statements recursively allocating all members.
+ String cAllocateStatements([String namePrefix = ""]) {
+ return map((m) => m.type.cAllocateStatements("$namePrefix${m.name}"))
+ .join();
+ }
+}
+
+extension on CType {
+ /// A list of Dart statements recursively checking all members.
+ String dartExpectsStatements(String expected, String actual) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ final this_ = this as FundamentalType;
+ if (this_.isInteger) {
+ return "Expect.equals(${expected}, ${actual});";
+ }
+ assert(this_.isFloatingPoint);
+ return "Expect.approxEquals(${expected}, ${actual});";
+
+ case StructType:
+ final this_ = this as StructType;
+ return this_.members.dartExpectsStatements("$expected.", "$actual.");
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+}
+
+extension on List<Member> {
+ /// A list of Dart statements recursively checking all members.
+ String dartExpectsStatements(
+ [String expectedPrefix = "", String actualPrefix = ""]) {
+ return map((m) => m.type.dartExpectsStatements(
+ "$expectedPrefix${m.name}", "$actualPrefix${m.name}")).join();
+ }
+}
+
+extension on CType {
+ /// A list of C statements recursively checking all members.
+ String cExpectsStatements(String expected, String actual) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ final this_ = this as FundamentalType;
+ if (this_.isInteger) {
+ return "CHECK_EQ(${expected}, ${actual});";
+ }
+ assert(this_.isFloatingPoint);
+ return "CHECK_APPROX(${expected}, ${actual});";
+
+ case StructType:
+ final this_ = this as StructType;
+ return this_.members.cExpectsStatements("$expected.", "$actual.");
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+
+ /// A list of C statements recursively checking all members for zero.
+ String cExpectsZeroStatements(String actual) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ final this_ = this as FundamentalType;
+ if (this_.isInteger) {
+ return "CHECK_EQ(0, ${actual});";
+ }
+ assert(this_.isFloatingPoint);
+ return "CHECK_APPROX(0.0, ${actual});";
+
+ case StructType:
+ final this_ = this as StructType;
+ return this_.members.cExpectsZeroStatements("$actual.");
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+}
+
+extension on List<Member> {
+ /// A list of C statements recursively checking all members.
+ String cExpectsStatements(
+ [String expectedPrefix = "", String actualPrefix = ""]) {
+ return map((m) => m.type.cExpectsStatements(
+ "$expectedPrefix${m.name}", "$actualPrefix${m.name}")).join();
+ }
+
+ /// A list of C statements recursively checking all members for zero.
+ String cExpectsZeroStatements([String actualPrefix = ""]) {
+ return map((m) => m.type.cExpectsZeroStatements("$actualPrefix${m.name}"))
+ .join();
+ }
+}
+
+extension on CType {
+ /// Expression denoting the first FundamentalType field.
+ ///
+ /// Both valid in Dart and C.
+ String firstArgumentName(String variableName) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ return variableName;
+
+ case StructType:
+ final this_ = this as StructType;
+ return this_.members.firstArgumentName("$variableName.");
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+}
+
+extension on List<Member> {
+ /// Expression denoting the first FundamentalType field.
+ ///
+ /// Both valid in Dart and C.
+ String firstArgumentName([String prefix = ""]) {
+ return this[0].type.firstArgumentName("$prefix${this[0].name}");
+ }
+}
+
+extension on StructType {
+ String dartClass(bool nnbd) {
+ String dartFields = "";
+ for (final member in members) {
+ dartFields += "${member.dartStructField(nnbd)}\n\n";
+ }
+ String toStringBody = members.map((m) => "\$\{${m.name}\}").join(", ");
+ return """
+ class $name extends Struct {
+ $dartFields
+
+ String toString() => "($toStringBody)";
+ }
+ """;
+ }
+
+ String get cDefinition {
+ String cFields = "";
+ for (final member in members) {
+ cFields += " ${member.cStructField}\n";
+ }
+ return """
+ struct $name {
+ $cFields
+ };
+
+ """;
+ }
+}
+
+extension on FunctionType {
+ String get dartCallCode {
+ final a = ArgumentValueAssigner();
+ final assignValues = arguments.assignValueStatements(a);
+ final argumentFrees = arguments.dartFreeStatements();
+
+ final argumentNames = arguments.map((e) => e.name).join(", ");
+
+ String expects;
+ switch (testType) {
+ case TestType.structArguments:
+ // Check against sum value.
+ final expectedResult = a.sumValue(returnValue as FundamentalType);
+ expects = returnValue.dartExpectsStatements(expectedResult, "result");
+ break;
+ case TestType.structReturn:
+ // Check against input arguments.
+ expects = arguments.dartExpectsStatements("", "result.");
+ break;
+ case TestType.structReturnArgument:
+ expects = returnValue.dartExpectsStatements(
+ structReturnArgument.name, "result");
+ break;
+ }
+
+ return """
+ final $dartName =
+ ffiTestFunctions.lookupFunction<$dartCType, $dartType>("$cName");
+
+ ${reason.makeDartDocComment()}
+ void $dartTestName() {
+ ${arguments.dartAllocateStatements()}
+
+ ${assignValues}
+
+ final result = $dartName($argumentNames);
+
+ print("result = \$result");
+
+ $expects
+
+ $argumentFrees
+ }
+ """;
+ }
+
+ String dartCallbackCode(bool nnbd) {
+ final argumentss =
+ arguments.map((a) => "${a.type.dartType} ${a.name}").join(", ");
+
+ final prints = arguments.map((a) => "\$\{${a.name}\}").join(", ");
+
+ String buildReturnValue = "";
+ switch (testType) {
+ case TestType.structArguments:
+ // Sum all input values.
+ buildReturnValue = """
+ ${returnValue.dartType} result = 0;
+
+ ${arguments.addToResultStatements('${dartName}_')}
+ """;
+ break;
+ case TestType.structReturn:
+ // Allocate a struct.
+ buildReturnValue = """
+ ${returnValue.dartType} result = allocate<${returnValue.dartType}>().ref;
+
+ ${arguments.copyValueStatements("${dartName}_", "result.")}
+ """;
+ break;
+ case TestType.structReturnArgument:
+ buildReturnValue = """
+ ${returnValue.cType} result = ${dartName}_${structReturnArgument.name};
+ """;
+ break;
+ }
+
+ final globals = arguments.dartAllocateZeroStatements("${dartName}_");
+
+ final copyToGlobals =
+ arguments.map((a) => '${dartName}_${a.name} = ${a.name};').join("\n");
+
+ // Simulate assigning values the same way as in C, so that we know what the
+ // final return value should be.
+ final a = ArgumentValueAssigner();
+ arguments.assignValueStatements(a);
+ String afterCallbackExpects = "";
+ String afterCallbackFrees = "";
+ switch (testType) {
+ case TestType.structArguments:
+ // Check that the input structs are still available.
+ // Check against sum value.
+ final expectedResult = a.sumValue(returnValue as FundamentalType);
+ afterCallbackExpects =
+ returnValue.dartExpectsStatements(expectedResult, "result");
+ break;
+ case TestType.structReturn:
+ // We're passing allocating structs in [buildReturnValue].
+ afterCallbackFrees =
+ returnValue.dartFreeStatements("${dartName}Result");
+ break;
+ case TestType.structReturnArgument:
+ break;
+ }
+
+ String returnNull = "";
+ if (!nnbd) {
+ returnNull = """
+ if (${arguments.firstArgumentName()} == $returnNullValue) {
+ print("returning null!");
+ return null;
+ }
+ """;
+ }
+
+ return """
+ typedef ${cName}Type = $dartCType;
+
+ // Global variables to be able to test inputs after callback returned.
+ $globals
+
+ // Result variable also global, so we can delete it after the callback.
+ ${returnValue.dartAllocateZeroStatements("${dartName}Result")}
+
+ ${returnValue.dartType} ${dartName}CalculateResult() {
+ $buildReturnValue
+
+ ${dartName}Result = result;
+
+ return result;
+ }
+
+ ${reason.makeDartDocComment()}
+ ${returnValue.dartType} $dartName($argumentss) {
+ print("$dartName($prints)");
+
+ // In legacy mode, possibly return null.
+ $returnNull
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (${arguments.firstArgumentName()} == $throwExceptionValue ||
+ ${arguments.firstArgumentName()} == $returnNullValue) {
+ print("throwing!");
+ throw Exception("$cName throwing on purpuse!");
+ }
+
+ $copyToGlobals
+
+ final result = ${dartName}CalculateResult();
+
+ print(\"result = \$result\");
+
+ return result;
+ }
+
+ void ${dartName}AfterCallback() {
+ $afterCallbackFrees
+
+ final result = ${dartName}CalculateResult();
+
+ print(\"after callback result = \$result\");
+
+ $afterCallbackExpects
+
+ $afterCallbackFrees
+ }
+
+ """;
+ }
+
+ String get dartCallbackTestConstructor {
+ String exceptionalReturn = "";
+ if (returnValue is FundamentalType) {
+ if ((returnValue as FundamentalType).isFloatingPoint) {
+ exceptionalReturn = ", 0.0";
+ } else {
+ exceptionalReturn = ", 0";
+ }
+ }
+ return """
+ CallbackTest.withCheck("$cName",
+ Pointer.fromFunction<${cName}Type>($dartName$exceptionalReturn),
+ ${dartName}AfterCallback),
+ """;
+ }
+
+ String get cCallCode {
+ String body = "";
+ switch (testType) {
+ case TestType.structArguments:
+ body = """
+ ${returnValue.cType} result = 0;
+
+ ${arguments.addToResultStatements()}
+ """;
+ break;
+ case TestType.structReturn:
+ body = """
+ ${returnValue.cType} result;
+
+ ${arguments.copyValueStatements("", "result.")}
+ """;
+ break;
+ case TestType.structReturnArgument:
+ body = """
+ ${returnValue.cType} result = ${structReturnArgument.name};
+ """;
+ break;
+ }
+
+ final argumentss =
+ arguments.map((e) => "${e.type.cType} ${e.name}").join(", ");
+
+ return """
+ // Used for testing structs by value.
+ ${reason.makeCComment()}
+ DART_EXPORT ${returnValue.cType} $cName($argumentss) {
+ std::cout << \"$cName\" ${arguments.coutExpression()} << \"\\n\";
+
+ $body
+
+ ${returnValue.coutStatement("result")}
+
+ return result;
+ }
+
+ """;
+ }
+
+ String get cCallbackCode {
+ final a = ArgumentValueAssigner();
+ final argumentAllocations = arguments.cAllocateStatements();
+ final assignValues = arguments.assignValueStatements(a);
+
+ final argumentss =
+ arguments.map((e) => "${e.type.cType} ${e.name}").join(", ");
+
+ final argumentNames = arguments.map((e) => e.name).join(", ");
+
+ String expects = "";
+ String expectsZero = "";
+ switch (testType) {
+ case TestType.structArguments:
+ // Check against sum value.
+ final returnValue_ = returnValue as FundamentalType;
+ final expectedResult = a.sumValue(returnValue_);
+ expects = returnValue.cExpectsStatements(expectedResult, "result");
+
+ expectsZero = returnValue.cExpectsZeroStatements("result");
+ break;
+ case TestType.structReturn:
+ // Check against input statements.
+ expects = arguments.cExpectsStatements("", "result.");
+
+ expectsZero = arguments.cExpectsZeroStatements("result.");
+ break;
+ case TestType.structReturnArgument:
+ // Check against input struct fields.
+ expects =
+ returnValue.cExpectsStatements(structReturnArgument.name, "result");
+
+ expectsZero = returnValue.cExpectsZeroStatements("result");
+ break;
+ }
+
+ return """
+ // Used for testing structs by value.
+ ${reason.makeCComment()}
+ DART_EXPORT intptr_t
+ Test$cName(
+ // NOLINTNEXTLINE(whitespace/parens)
+ ${returnValue.cType} (*f)($argumentss)) {
+ $argumentAllocations
+
+ $assignValues
+
+ std::cout << \"Calling Test$cName(\" ${arguments.coutExpression()} << \")\\n\";
+
+ ${returnValue.cType} result = f($argumentNames);
+
+ ${returnValue.coutStatement("result")}
+
+ $expects
+
+ // Pass argument that will make the Dart callback throw.
+ ${arguments.firstArgumentName()} = $throwExceptionValue;
+
+ result = f($argumentNames);
+
+ $expectsZero
+
+ // Pass argument that will make the Dart callback return null.
+ ${arguments.firstArgumentName()} = $returnNullValue;
+
+ result = f($argumentNames);
+
+ $expectsZero
+
+ return 0;
+ }
+
+ """;
+ }
+}
+
+/// Some value between 0 and 127 (works in every native type).
+const throwExceptionValue = 42;
+
+/// Some value between 0 and 127 (works in every native type).
+const returnNullValue = 84;
+
+const headerDartCallTest = """
+// Copyright (c) 2020, 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.
+//
+// This file has been automatically generated. Please do not edit it manually.
+//
+// SharedObjects=ffi_test_functions
+// VMOptions=
+// VMOptions=--deterministic --optimization-counter-threshold=5
+// VMOptions=--use-slow-path
+// VMOptions=--use-slow-path --stacktrace-every=100
+
+import 'dart:ffi';
+
+import "package:expect/expect.dart";
+import "package:ffi/ffi.dart";
+
+import 'dylib_utils.dart';
+
+final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
+""";
+
+void writeDartCallTest() {
+ for (bool nnbd in [true, false]) {
+ final StringBuffer buffer = StringBuffer();
+ buffer.write(headerDartCallTest);
+
+ buffer.write("""
+ void main() {
+ for (int i = 0; i < 10; ++i) {
+ ${functions.map((e) => "${e.dartTestName}();").join("\n")}
+ }
+ }
+ """);
+ buffer.writeAll(structs.map((e) => e.dartClass(nnbd)));
+ buffer.writeAll(functions.map((e) => e.dartCallCode));
+
+ final path = callTestPath(nnbd);
+ File(path).writeAsStringSync(buffer.toString());
+ Process.runSync("dartfmt", ["-w", path]);
+ }
+}
+
+String callTestPath(bool nnbd) {
+ final folder = nnbd ? "ffi" : "ffi_2";
+ return Platform.script
+ .resolve("../../$folder/function_structs_by_value_generated_test.dart")
+ .path;
+}
+
+const headerDartCallbackTest = """
+// Copyright (c) 2020, 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.
+//
+// This file has been automatically generated. Please do not edit it manually.
+//
+// SharedObjects=ffi_test_functions
+// VMOptions=
+// VMOptions=--deterministic --optimization-counter-threshold=10
+// VMOptions=--use-slow-path
+// VMOptions=--use-slow-path --stacktrace-every=100
+
+import 'dart:ffi';
+
+import "package:expect/expect.dart";
+import "package:ffi/ffi.dart";
+
+import 'callback_tests_utils.dart';
+
+// Reuse the struct classes.
+import 'function_structs_by_value_generated_test.dart';
+
+
+void main() {
+ testCases.forEach((t) {
+ print("==== Running " + t.name);
+ t.run();
+ });
+}
+
+
+""";
+
+void writeDartCallbackTest() {
+ for (bool nnbd in [true, false]) {
+ final StringBuffer buffer = StringBuffer();
+ buffer.write(headerDartCallbackTest);
+
+ buffer.write("""
+ final testCases = [
+ ${functions.map((e) => e.dartCallbackTestConstructor).join("\n")}
+ ];
+ """);
+
+ buffer.writeAll(functions.map((e) => e.dartCallbackCode(nnbd)));
+
+ final path = callbackTestPath(nnbd);
+ File(path).writeAsStringSync(buffer.toString());
+ Process.runSync("dartfmt", ["-w", path]);
+ }
+}
+
+String callbackTestPath(bool nnbd) {
+ final folder = nnbd ? "ffi" : "ffi_2";
+ return Platform.script
+ .resolve(
+ "../../$folder/function_callbacks_structs_by_value_generated_test.dart")
+ .path;
+}
+
+const headerC = """
+// Copyright (c) 2020, 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.
+//
+// This file has been automatically generated. Please do not edit it manually.
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include <cmath>
+#include <iostream>
+#include <limits>
+
+#if defined(_WIN32)
+#define DART_EXPORT extern "C" __declspec(dllexport)
+#else
+#define DART_EXPORT \\
+ extern "C" __attribute__((visibility("default"))) __attribute((used))
+#endif
+
+namespace dart {
+
+#define CHECK(X) \\
+ if (!(X)) { \\
+ fprintf(stderr, "%s\\n", "Check failed: " #X); \\
+ return 1; \\
+ }
+
+#define CHECK_EQ(X, Y) CHECK((X) == (Y))
+
+// Works for positive, negative and zero.
+#define CHECK_APPROX(EXPECTED, ACTUAL) \\
+ CHECK(((EXPECTED * 0.99) <= (ACTUAL) && (EXPECTED * 1.01) >= (ACTUAL)) || \\
+ ((EXPECTED * 0.99) >= (ACTUAL) && (EXPECTED * 1.01) <= (ACTUAL)))
+
+""";
+
+const footerC = """
+
+} // namespace dart
+""";
+
+void writeC() {
+ final StringBuffer buffer = StringBuffer();
+ buffer.write(headerC);
+
+ buffer.writeAll(structs.map((e) => e.cDefinition));
+ buffer.writeAll(functions.map((e) => e.cCallCode));
+ buffer.writeAll(functions.map((e) => e.cCallbackCode));
+
+ buffer.write(footerC);
+
+ File(ccPath).writeAsStringSync(buffer.toString());
+ Process.runSync("clang-format", ["-i", ccPath]);
+}
+
+final ccPath = Platform.script
+ .resolve("../../../runtime/bin/ffi_test/ffi_test_functions_generated.cc")
+ .path;
+
+void printUsage() {
+ print("""
+Generates structs by value tests.
+
+Generates:
+- $ccPath
+- ${callbackTestPath(true)}
+- ${callTestPath(true)}
+- ${callbackTestPath(false)}
+- ${callTestPath(false)}
+""");
+}
+
+void main(List<String> arguments) {
+ if (arguments.length != 0) {
+ printUsage();
+ return;
+ }
+
+ writeDartCallTest();
+ writeDartCallbackTest();
+ writeC();
+}
diff --git a/tests/ffi/generator/utils.dart b/tests/ffi/generator/utils.dart
new file mode 100644
index 0000000..735e769
--- /dev/null
+++ b/tests/ffi/generator/utils.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2020, 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.
+
+extension TestGeneratorStringExtension on String {
+ String upperCaseFirst() => "${this[0].toUpperCase()}${this.substring(1)}";
+
+ String lowerCaseFirst() => "${this[0].toLowerCase()}${this.substring(1)}";
+
+ String makeCComment() => "// " + split("\n").join("\n// ");
+
+ String makeDartDocComment() => "/// " + split("\n").join("\n/// ");
+
+ String limitTo(int lenght) {
+ if (this.length > lenght) {
+ return substring(0, lenght);
+ }
+ return this;
+ }
+
+ String trimCouts() => replaceAll('" << "', '').replaceAll('"<< "', '');
+}
diff --git a/tests/ffi_2/callback_tests_utils.dart b/tests/ffi_2/callback_tests_utils.dart
index ac5fdcb..e34a52b 100644
--- a/tests/ffi_2/callback_tests_utils.dart
+++ b/tests/ffi_2/callback_tests_utils.dart
@@ -16,19 +16,23 @@
class CallbackTest {
final String name;
final Pointer callback;
- final bool skip;
+ final void Function() afterCallbackChecks;
- CallbackTest(this.name, this.callback, {bool skipIf: false})
- : skip = skipIf {}
+ CallbackTest(this.name, this.callback) : afterCallbackChecks = noChecks {}
+ CallbackTest.withCheck(this.name, this.callback, this.afterCallbackChecks) {}
void run() {
- if (skip) return;
-
final NativeCallbackTestFn tester = ffiTestFunctions
.lookupFunction<NativeCallbackTest, NativeCallbackTestFn>("Test$name");
+
final int testCode = tester(callback);
+
if (testCode != 0) {
Expect.fail("Test $name failed.");
}
+
+ afterCallbackChecks();
}
}
+
+void noChecks() {}
diff --git a/tests/ffi_2/ffi_2.status b/tests/ffi_2/ffi_2.status
index 37ab3e9..3baf069 100644
--- a/tests/ffi_2/ffi_2.status
+++ b/tests/ffi_2/ffi_2.status
@@ -2,6 +2,11 @@
# 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.
+# TODO(dartbug.com/36730): Implement structs by value.
+function_callbacks_structs_by_value_generated_test: Skip
+function_callbacks_structs_by_value_test: Skip
+function_structs_by_value_generated_test: Skip
+
[ $builder_tag == msan ]
vmspecific_handle_test: Skip # https://dartbug.com/42314
diff --git a/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart b/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart
new file mode 100644
index 0000000..4db290f
--- /dev/null
+++ b/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart
@@ -0,0 +1,6124 @@
+// Copyright (c) 2020, 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.
+//
+// This file has been automatically generated. Please do not edit it manually.
+//
+// SharedObjects=ffi_test_functions
+// VMOptions=
+// VMOptions=--deterministic --optimization-counter-threshold=10
+// VMOptions=--use-slow-path
+// VMOptions=--use-slow-path --stacktrace-every=100
+
+import 'dart:ffi';
+
+import "package:expect/expect.dart";
+import "package:ffi/ffi.dart";
+
+import 'callback_tests_utils.dart';
+
+// Reuse the struct classes.
+import 'function_structs_by_value_generated_test.dart';
+
+void main() {
+ testCases.forEach((t) {
+ print("==== Running " + t.name);
+ t.run();
+ });
+}
+
+final testCases = [
+ CallbackTest.withCheck(
+ "PassStruct1ByteIntx10",
+ Pointer.fromFunction<PassStruct1ByteIntx10Type>(passStruct1ByteIntx10, 0),
+ passStruct1ByteIntx10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct3BytesIntx10",
+ Pointer.fromFunction<PassStruct3BytesIntx10Type>(
+ passStruct3BytesIntx10, 0),
+ passStruct3BytesIntx10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct4BytesHomogeneousInt16x10",
+ Pointer.fromFunction<PassStruct4BytesHomogeneousInt16x10Type>(
+ passStruct4BytesHomogeneousInt16x10, 0),
+ passStruct4BytesHomogeneousInt16x10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct7BytesIntx10",
+ Pointer.fromFunction<PassStruct7BytesIntx10Type>(
+ passStruct7BytesIntx10, 0),
+ passStruct7BytesIntx10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct8BytesIntx10",
+ Pointer.fromFunction<PassStruct8BytesIntx10Type>(
+ passStruct8BytesIntx10, 0),
+ passStruct8BytesIntx10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct8BytesHomogeneousFloatx10",
+ Pointer.fromFunction<PassStruct8BytesHomogeneousFloatx10Type>(
+ passStruct8BytesHomogeneousFloatx10, 0.0),
+ passStruct8BytesHomogeneousFloatx10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct8BytesMixedx10",
+ Pointer.fromFunction<PassStruct8BytesMixedx10Type>(
+ passStruct8BytesMixedx10, 0.0),
+ passStruct8BytesMixedx10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct9BytesIntx10",
+ Pointer.fromFunction<PassStruct9BytesIntx10Type>(
+ passStruct9BytesIntx10, 0),
+ passStruct9BytesIntx10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct9BytesHomogeneousUint82x10",
+ Pointer.fromFunction<PassStruct9BytesHomogeneousUint82x10Type>(
+ passStruct9BytesHomogeneousUint82x10, 0),
+ passStruct9BytesHomogeneousUint82x10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct12BytesHomogeneousFloatx6",
+ Pointer.fromFunction<PassStruct12BytesHomogeneousFloatx6Type>(
+ passStruct12BytesHomogeneousFloatx6, 0.0),
+ passStruct12BytesHomogeneousFloatx6AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct16BytesHomogeneousFloatx5",
+ Pointer.fromFunction<PassStruct16BytesHomogeneousFloatx5Type>(
+ passStruct16BytesHomogeneousFloatx5, 0.0),
+ passStruct16BytesHomogeneousFloatx5AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct16BytesMixedx10",
+ Pointer.fromFunction<PassStruct16BytesMixedx10Type>(
+ passStruct16BytesMixedx10, 0.0),
+ passStruct16BytesMixedx10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct16BytesMixed2x10",
+ Pointer.fromFunction<PassStruct16BytesMixed2x10Type>(
+ passStruct16BytesMixed2x10, 0.0),
+ passStruct16BytesMixed2x10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct17BytesIntx10",
+ Pointer.fromFunction<PassStruct17BytesIntx10Type>(
+ passStruct17BytesIntx10, 0),
+ passStruct17BytesIntx10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct19BytesHomogeneousUint8x10",
+ Pointer.fromFunction<PassStruct19BytesHomogeneousUint8x10Type>(
+ passStruct19BytesHomogeneousUint8x10, 0),
+ passStruct19BytesHomogeneousUint8x10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct20BytesHomogeneousInt32x10",
+ Pointer.fromFunction<PassStruct20BytesHomogeneousInt32x10Type>(
+ passStruct20BytesHomogeneousInt32x10, 0),
+ passStruct20BytesHomogeneousInt32x10AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct20BytesHomogeneousFloat",
+ Pointer.fromFunction<PassStruct20BytesHomogeneousFloatType>(
+ passStruct20BytesHomogeneousFloat, 0.0),
+ passStruct20BytesHomogeneousFloatAfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct32BytesHomogeneousDoublex5",
+ Pointer.fromFunction<PassStruct32BytesHomogeneousDoublex5Type>(
+ passStruct32BytesHomogeneousDoublex5, 0.0),
+ passStruct32BytesHomogeneousDoublex5AfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct40BytesHomogeneousDouble",
+ Pointer.fromFunction<PassStruct40BytesHomogeneousDoubleType>(
+ passStruct40BytesHomogeneousDouble, 0.0),
+ passStruct40BytesHomogeneousDoubleAfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct1024BytesHomogeneousUint64",
+ Pointer.fromFunction<PassStruct1024BytesHomogeneousUint64Type>(
+ passStruct1024BytesHomogeneousUint64, 0),
+ passStruct1024BytesHomogeneousUint64AfterCallback),
+ CallbackTest.withCheck(
+ "PassFloatStruct16BytesHomogeneousFloatFloatStruct1",
+ Pointer.fromFunction<
+ PassFloatStruct16BytesHomogeneousFloatFloatStruct1Type>(
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1, 0.0),
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1AfterCallback),
+ CallbackTest.withCheck(
+ "PassFloatStruct32BytesHomogeneousDoubleFloatStruct",
+ Pointer.fromFunction<
+ PassFloatStruct32BytesHomogeneousDoubleFloatStructType>(
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct, 0.0),
+ passFloatStruct32BytesHomogeneousDoubleFloatStructAfterCallback),
+ CallbackTest.withCheck(
+ "PassInt8Struct16BytesMixedInt8Struct16BytesMixedIn",
+ Pointer.fromFunction<
+ PassInt8Struct16BytesMixedInt8Struct16BytesMixedInType>(
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedIn, 0.0),
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedInAfterCallback),
+ CallbackTest.withCheck(
+ "PassDoublex6Struct16BytesMixedx4Int32",
+ Pointer.fromFunction<PassDoublex6Struct16BytesMixedx4Int32Type>(
+ passDoublex6Struct16BytesMixedx4Int32, 0.0),
+ passDoublex6Struct16BytesMixedx4Int32AfterCallback),
+ CallbackTest.withCheck(
+ "PassInt32x4Struct16BytesMixedx4Double",
+ Pointer.fromFunction<PassInt32x4Struct16BytesMixedx4DoubleType>(
+ passInt32x4Struct16BytesMixedx4Double, 0.0),
+ passInt32x4Struct16BytesMixedx4DoubleAfterCallback),
+ CallbackTest.withCheck(
+ "PassStruct40BytesHomogeneousDoubleStruct4BytesHomo",
+ Pointer.fromFunction<
+ PassStruct40BytesHomogeneousDoubleStruct4BytesHomoType>(
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomo, 0.0),
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomoAfterCallback),
+ CallbackTest.withCheck(
+ "PassStructAlignmentInt16",
+ Pointer.fromFunction<PassStructAlignmentInt16Type>(
+ passStructAlignmentInt16, 0),
+ passStructAlignmentInt16AfterCallback),
+ CallbackTest.withCheck(
+ "PassStructAlignmentInt32",
+ Pointer.fromFunction<PassStructAlignmentInt32Type>(
+ passStructAlignmentInt32, 0),
+ passStructAlignmentInt32AfterCallback),
+ CallbackTest.withCheck(
+ "PassStructAlignmentInt64",
+ Pointer.fromFunction<PassStructAlignmentInt64Type>(
+ passStructAlignmentInt64, 0),
+ passStructAlignmentInt64AfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct1ByteInt",
+ Pointer.fromFunction<ReturnStruct1ByteIntType>(returnStruct1ByteInt),
+ returnStruct1ByteIntAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct3BytesInt",
+ Pointer.fromFunction<ReturnStruct3BytesIntType>(returnStruct3BytesInt),
+ returnStruct3BytesIntAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct4BytesHomogeneousInt16",
+ Pointer.fromFunction<ReturnStruct4BytesHomogeneousInt16Type>(
+ returnStruct4BytesHomogeneousInt16),
+ returnStruct4BytesHomogeneousInt16AfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct7BytesInt",
+ Pointer.fromFunction<ReturnStruct7BytesIntType>(returnStruct7BytesInt),
+ returnStruct7BytesIntAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct8BytesInt",
+ Pointer.fromFunction<ReturnStruct8BytesIntType>(returnStruct8BytesInt),
+ returnStruct8BytesIntAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct8BytesHomogeneousFloat",
+ Pointer.fromFunction<ReturnStruct8BytesHomogeneousFloatType>(
+ returnStruct8BytesHomogeneousFloat),
+ returnStruct8BytesHomogeneousFloatAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct8BytesMixed",
+ Pointer.fromFunction<ReturnStruct8BytesMixedType>(
+ returnStruct8BytesMixed),
+ returnStruct8BytesMixedAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct9BytesInt",
+ Pointer.fromFunction<ReturnStruct9BytesIntType>(returnStruct9BytesInt),
+ returnStruct9BytesIntAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct9BytesHomogeneousUint82",
+ Pointer.fromFunction<ReturnStruct9BytesHomogeneousUint82Type>(
+ returnStruct9BytesHomogeneousUint82),
+ returnStruct9BytesHomogeneousUint82AfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct12BytesHomogeneousFloat",
+ Pointer.fromFunction<ReturnStruct12BytesHomogeneousFloatType>(
+ returnStruct12BytesHomogeneousFloat),
+ returnStruct12BytesHomogeneousFloatAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct16BytesHomogeneousFloat",
+ Pointer.fromFunction<ReturnStruct16BytesHomogeneousFloatType>(
+ returnStruct16BytesHomogeneousFloat),
+ returnStruct16BytesHomogeneousFloatAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct16BytesMixed",
+ Pointer.fromFunction<ReturnStruct16BytesMixedType>(
+ returnStruct16BytesMixed),
+ returnStruct16BytesMixedAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct16BytesMixed2",
+ Pointer.fromFunction<ReturnStruct16BytesMixed2Type>(
+ returnStruct16BytesMixed2),
+ returnStruct16BytesMixed2AfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct17BytesInt",
+ Pointer.fromFunction<ReturnStruct17BytesIntType>(returnStruct17BytesInt),
+ returnStruct17BytesIntAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct19BytesHomogeneousUint8",
+ Pointer.fromFunction<ReturnStruct19BytesHomogeneousUint8Type>(
+ returnStruct19BytesHomogeneousUint8),
+ returnStruct19BytesHomogeneousUint8AfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct20BytesHomogeneousInt32",
+ Pointer.fromFunction<ReturnStruct20BytesHomogeneousInt32Type>(
+ returnStruct20BytesHomogeneousInt32),
+ returnStruct20BytesHomogeneousInt32AfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct20BytesHomogeneousFloat",
+ Pointer.fromFunction<ReturnStruct20BytesHomogeneousFloatType>(
+ returnStruct20BytesHomogeneousFloat),
+ returnStruct20BytesHomogeneousFloatAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct32BytesHomogeneousDouble",
+ Pointer.fromFunction<ReturnStruct32BytesHomogeneousDoubleType>(
+ returnStruct32BytesHomogeneousDouble),
+ returnStruct32BytesHomogeneousDoubleAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct40BytesHomogeneousDouble",
+ Pointer.fromFunction<ReturnStruct40BytesHomogeneousDoubleType>(
+ returnStruct40BytesHomogeneousDouble),
+ returnStruct40BytesHomogeneousDoubleAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStruct1024BytesHomogeneousUint64",
+ Pointer.fromFunction<ReturnStruct1024BytesHomogeneousUint64Type>(
+ returnStruct1024BytesHomogeneousUint64),
+ returnStruct1024BytesHomogeneousUint64AfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStructArgumentStruct1ByteInt",
+ Pointer.fromFunction<ReturnStructArgumentStruct1ByteIntType>(
+ returnStructArgumentStruct1ByteInt),
+ returnStructArgumentStruct1ByteIntAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStructArgumentInt32x8Struct1ByteInt",
+ Pointer.fromFunction<ReturnStructArgumentInt32x8Struct1ByteIntType>(
+ returnStructArgumentInt32x8Struct1ByteInt),
+ returnStructArgumentInt32x8Struct1ByteIntAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStructArgumentStruct8BytesHomogeneousFloat",
+ Pointer.fromFunction<
+ ReturnStructArgumentStruct8BytesHomogeneousFloatType>(
+ returnStructArgumentStruct8BytesHomogeneousFloat),
+ returnStructArgumentStruct8BytesHomogeneousFloatAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStructArgumentStruct20BytesHomogeneousInt32",
+ Pointer.fromFunction<
+ ReturnStructArgumentStruct20BytesHomogeneousInt32Type>(
+ returnStructArgumentStruct20BytesHomogeneousInt32),
+ returnStructArgumentStruct20BytesHomogeneousInt32AfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStructArgumentInt32x8Struct20BytesHomogeneou",
+ Pointer.fromFunction<
+ ReturnStructArgumentInt32x8Struct20BytesHomogeneouType>(
+ returnStructArgumentInt32x8Struct20BytesHomogeneou),
+ returnStructArgumentInt32x8Struct20BytesHomogeneouAfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStructAlignmentInt16",
+ Pointer.fromFunction<ReturnStructAlignmentInt16Type>(
+ returnStructAlignmentInt16),
+ returnStructAlignmentInt16AfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStructAlignmentInt32",
+ Pointer.fromFunction<ReturnStructAlignmentInt32Type>(
+ returnStructAlignmentInt32),
+ returnStructAlignmentInt32AfterCallback),
+ CallbackTest.withCheck(
+ "ReturnStructAlignmentInt64",
+ Pointer.fromFunction<ReturnStructAlignmentInt64Type>(
+ returnStructAlignmentInt64),
+ returnStructAlignmentInt64AfterCallback),
+];
+typedef PassStruct1ByteIntx10Type = Int64 Function(
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct1ByteInt passStruct1ByteIntx10_a0 = Struct1ByteInt();
+Struct1ByteInt passStruct1ByteIntx10_a1 = Struct1ByteInt();
+Struct1ByteInt passStruct1ByteIntx10_a2 = Struct1ByteInt();
+Struct1ByteInt passStruct1ByteIntx10_a3 = Struct1ByteInt();
+Struct1ByteInt passStruct1ByteIntx10_a4 = Struct1ByteInt();
+Struct1ByteInt passStruct1ByteIntx10_a5 = Struct1ByteInt();
+Struct1ByteInt passStruct1ByteIntx10_a6 = Struct1ByteInt();
+Struct1ByteInt passStruct1ByteIntx10_a7 = Struct1ByteInt();
+Struct1ByteInt passStruct1ByteIntx10_a8 = Struct1ByteInt();
+Struct1ByteInt passStruct1ByteIntx10_a9 = Struct1ByteInt();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct1ByteIntx10Result = 0;
+
+int passStruct1ByteIntx10CalculateResult() {
+ int result = 0;
+
+ result += passStruct1ByteIntx10_a0.a0;
+ result += passStruct1ByteIntx10_a1.a0;
+ result += passStruct1ByteIntx10_a2.a0;
+ result += passStruct1ByteIntx10_a3.a0;
+ result += passStruct1ByteIntx10_a4.a0;
+ result += passStruct1ByteIntx10_a5.a0;
+ result += passStruct1ByteIntx10_a6.a0;
+ result += passStruct1ByteIntx10_a7.a0;
+ result += passStruct1ByteIntx10_a8.a0;
+ result += passStruct1ByteIntx10_a9.a0;
+
+ passStruct1ByteIntx10Result = result;
+
+ return result;
+}
+
+/// Smallest struct with data.
+/// 10 struct arguments will exhaust available registers.
+int passStruct1ByteIntx10(
+ Struct1ByteInt a0,
+ Struct1ByteInt a1,
+ Struct1ByteInt a2,
+ Struct1ByteInt a3,
+ Struct1ByteInt a4,
+ Struct1ByteInt a5,
+ Struct1ByteInt a6,
+ Struct1ByteInt a7,
+ Struct1ByteInt a8,
+ Struct1ByteInt a9) {
+ print(
+ "passStruct1ByteIntx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct1ByteIntx10 throwing on purpuse!");
+ }
+
+ passStruct1ByteIntx10_a0 = a0;
+ passStruct1ByteIntx10_a1 = a1;
+ passStruct1ByteIntx10_a2 = a2;
+ passStruct1ByteIntx10_a3 = a3;
+ passStruct1ByteIntx10_a4 = a4;
+ passStruct1ByteIntx10_a5 = a5;
+ passStruct1ByteIntx10_a6 = a6;
+ passStruct1ByteIntx10_a7 = a7;
+ passStruct1ByteIntx10_a8 = a8;
+ passStruct1ByteIntx10_a9 = a9;
+
+ final result = passStruct1ByteIntx10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct1ByteIntx10AfterCallback() {
+ final result = passStruct1ByteIntx10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(5, result);
+}
+
+typedef PassStruct3BytesIntx10Type = Int64 Function(
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct3BytesInt passStruct3BytesIntx10_a0 = Struct3BytesInt();
+Struct3BytesInt passStruct3BytesIntx10_a1 = Struct3BytesInt();
+Struct3BytesInt passStruct3BytesIntx10_a2 = Struct3BytesInt();
+Struct3BytesInt passStruct3BytesIntx10_a3 = Struct3BytesInt();
+Struct3BytesInt passStruct3BytesIntx10_a4 = Struct3BytesInt();
+Struct3BytesInt passStruct3BytesIntx10_a5 = Struct3BytesInt();
+Struct3BytesInt passStruct3BytesIntx10_a6 = Struct3BytesInt();
+Struct3BytesInt passStruct3BytesIntx10_a7 = Struct3BytesInt();
+Struct3BytesInt passStruct3BytesIntx10_a8 = Struct3BytesInt();
+Struct3BytesInt passStruct3BytesIntx10_a9 = Struct3BytesInt();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct3BytesIntx10Result = 0;
+
+int passStruct3BytesIntx10CalculateResult() {
+ int result = 0;
+
+ result += passStruct3BytesIntx10_a0.a0;
+ result += passStruct3BytesIntx10_a0.a1;
+ result += passStruct3BytesIntx10_a1.a0;
+ result += passStruct3BytesIntx10_a1.a1;
+ result += passStruct3BytesIntx10_a2.a0;
+ result += passStruct3BytesIntx10_a2.a1;
+ result += passStruct3BytesIntx10_a3.a0;
+ result += passStruct3BytesIntx10_a3.a1;
+ result += passStruct3BytesIntx10_a4.a0;
+ result += passStruct3BytesIntx10_a4.a1;
+ result += passStruct3BytesIntx10_a5.a0;
+ result += passStruct3BytesIntx10_a5.a1;
+ result += passStruct3BytesIntx10_a6.a0;
+ result += passStruct3BytesIntx10_a6.a1;
+ result += passStruct3BytesIntx10_a7.a0;
+ result += passStruct3BytesIntx10_a7.a1;
+ result += passStruct3BytesIntx10_a8.a0;
+ result += passStruct3BytesIntx10_a8.a1;
+ result += passStruct3BytesIntx10_a9.a0;
+ result += passStruct3BytesIntx10_a9.a1;
+
+ passStruct3BytesIntx10Result = result;
+
+ return result;
+}
+
+/// Not a multiple of word size, not a power of two.
+/// 10 struct arguments will exhaust available registers.
+int passStruct3BytesIntx10(
+ Struct3BytesInt a0,
+ Struct3BytesInt a1,
+ Struct3BytesInt a2,
+ Struct3BytesInt a3,
+ Struct3BytesInt a4,
+ Struct3BytesInt a5,
+ Struct3BytesInt a6,
+ Struct3BytesInt a7,
+ Struct3BytesInt a8,
+ Struct3BytesInt a9) {
+ print(
+ "passStruct3BytesIntx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct3BytesIntx10 throwing on purpuse!");
+ }
+
+ passStruct3BytesIntx10_a0 = a0;
+ passStruct3BytesIntx10_a1 = a1;
+ passStruct3BytesIntx10_a2 = a2;
+ passStruct3BytesIntx10_a3 = a3;
+ passStruct3BytesIntx10_a4 = a4;
+ passStruct3BytesIntx10_a5 = a5;
+ passStruct3BytesIntx10_a6 = a6;
+ passStruct3BytesIntx10_a7 = a7;
+ passStruct3BytesIntx10_a8 = a8;
+ passStruct3BytesIntx10_a9 = a9;
+
+ final result = passStruct3BytesIntx10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct3BytesIntx10AfterCallback() {
+ final result = passStruct3BytesIntx10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(10, result);
+}
+
+typedef PassStruct4BytesHomogeneousInt16x10Type = Int64 Function(
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16);
+
+// Global variables to be able to test inputs after callback returned.
+Struct4BytesHomogeneousInt16 passStruct4BytesHomogeneousInt16x10_a0 =
+ Struct4BytesHomogeneousInt16();
+Struct4BytesHomogeneousInt16 passStruct4BytesHomogeneousInt16x10_a1 =
+ Struct4BytesHomogeneousInt16();
+Struct4BytesHomogeneousInt16 passStruct4BytesHomogeneousInt16x10_a2 =
+ Struct4BytesHomogeneousInt16();
+Struct4BytesHomogeneousInt16 passStruct4BytesHomogeneousInt16x10_a3 =
+ Struct4BytesHomogeneousInt16();
+Struct4BytesHomogeneousInt16 passStruct4BytesHomogeneousInt16x10_a4 =
+ Struct4BytesHomogeneousInt16();
+Struct4BytesHomogeneousInt16 passStruct4BytesHomogeneousInt16x10_a5 =
+ Struct4BytesHomogeneousInt16();
+Struct4BytesHomogeneousInt16 passStruct4BytesHomogeneousInt16x10_a6 =
+ Struct4BytesHomogeneousInt16();
+Struct4BytesHomogeneousInt16 passStruct4BytesHomogeneousInt16x10_a7 =
+ Struct4BytesHomogeneousInt16();
+Struct4BytesHomogeneousInt16 passStruct4BytesHomogeneousInt16x10_a8 =
+ Struct4BytesHomogeneousInt16();
+Struct4BytesHomogeneousInt16 passStruct4BytesHomogeneousInt16x10_a9 =
+ Struct4BytesHomogeneousInt16();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct4BytesHomogeneousInt16x10Result = 0;
+
+int passStruct4BytesHomogeneousInt16x10CalculateResult() {
+ int result = 0;
+
+ result += passStruct4BytesHomogeneousInt16x10_a0.a0;
+ result += passStruct4BytesHomogeneousInt16x10_a0.a1;
+ result += passStruct4BytesHomogeneousInt16x10_a1.a0;
+ result += passStruct4BytesHomogeneousInt16x10_a1.a1;
+ result += passStruct4BytesHomogeneousInt16x10_a2.a0;
+ result += passStruct4BytesHomogeneousInt16x10_a2.a1;
+ result += passStruct4BytesHomogeneousInt16x10_a3.a0;
+ result += passStruct4BytesHomogeneousInt16x10_a3.a1;
+ result += passStruct4BytesHomogeneousInt16x10_a4.a0;
+ result += passStruct4BytesHomogeneousInt16x10_a4.a1;
+ result += passStruct4BytesHomogeneousInt16x10_a5.a0;
+ result += passStruct4BytesHomogeneousInt16x10_a5.a1;
+ result += passStruct4BytesHomogeneousInt16x10_a6.a0;
+ result += passStruct4BytesHomogeneousInt16x10_a6.a1;
+ result += passStruct4BytesHomogeneousInt16x10_a7.a0;
+ result += passStruct4BytesHomogeneousInt16x10_a7.a1;
+ result += passStruct4BytesHomogeneousInt16x10_a8.a0;
+ result += passStruct4BytesHomogeneousInt16x10_a8.a1;
+ result += passStruct4BytesHomogeneousInt16x10_a9.a0;
+ result += passStruct4BytesHomogeneousInt16x10_a9.a1;
+
+ passStruct4BytesHomogeneousInt16x10Result = result;
+
+ return result;
+}
+
+/// Exactly word size on 32-bit architectures.
+/// 10 struct arguments will exhaust available registers.
+int passStruct4BytesHomogeneousInt16x10(
+ Struct4BytesHomogeneousInt16 a0,
+ Struct4BytesHomogeneousInt16 a1,
+ Struct4BytesHomogeneousInt16 a2,
+ Struct4BytesHomogeneousInt16 a3,
+ Struct4BytesHomogeneousInt16 a4,
+ Struct4BytesHomogeneousInt16 a5,
+ Struct4BytesHomogeneousInt16 a6,
+ Struct4BytesHomogeneousInt16 a7,
+ Struct4BytesHomogeneousInt16 a8,
+ Struct4BytesHomogeneousInt16 a9) {
+ print(
+ "passStruct4BytesHomogeneousInt16x10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct4BytesHomogeneousInt16x10 throwing on purpuse!");
+ }
+
+ passStruct4BytesHomogeneousInt16x10_a0 = a0;
+ passStruct4BytesHomogeneousInt16x10_a1 = a1;
+ passStruct4BytesHomogeneousInt16x10_a2 = a2;
+ passStruct4BytesHomogeneousInt16x10_a3 = a3;
+ passStruct4BytesHomogeneousInt16x10_a4 = a4;
+ passStruct4BytesHomogeneousInt16x10_a5 = a5;
+ passStruct4BytesHomogeneousInt16x10_a6 = a6;
+ passStruct4BytesHomogeneousInt16x10_a7 = a7;
+ passStruct4BytesHomogeneousInt16x10_a8 = a8;
+ passStruct4BytesHomogeneousInt16x10_a9 = a9;
+
+ final result = passStruct4BytesHomogeneousInt16x10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct4BytesHomogeneousInt16x10AfterCallback() {
+ final result = passStruct4BytesHomogeneousInt16x10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(10, result);
+}
+
+typedef PassStruct7BytesIntx10Type = Int64 Function(
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct7BytesInt passStruct7BytesIntx10_a0 = Struct7BytesInt();
+Struct7BytesInt passStruct7BytesIntx10_a1 = Struct7BytesInt();
+Struct7BytesInt passStruct7BytesIntx10_a2 = Struct7BytesInt();
+Struct7BytesInt passStruct7BytesIntx10_a3 = Struct7BytesInt();
+Struct7BytesInt passStruct7BytesIntx10_a4 = Struct7BytesInt();
+Struct7BytesInt passStruct7BytesIntx10_a5 = Struct7BytesInt();
+Struct7BytesInt passStruct7BytesIntx10_a6 = Struct7BytesInt();
+Struct7BytesInt passStruct7BytesIntx10_a7 = Struct7BytesInt();
+Struct7BytesInt passStruct7BytesIntx10_a8 = Struct7BytesInt();
+Struct7BytesInt passStruct7BytesIntx10_a9 = Struct7BytesInt();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct7BytesIntx10Result = 0;
+
+int passStruct7BytesIntx10CalculateResult() {
+ int result = 0;
+
+ result += passStruct7BytesIntx10_a0.a0;
+ result += passStruct7BytesIntx10_a0.a1;
+ result += passStruct7BytesIntx10_a0.a2;
+ result += passStruct7BytesIntx10_a1.a0;
+ result += passStruct7BytesIntx10_a1.a1;
+ result += passStruct7BytesIntx10_a1.a2;
+ result += passStruct7BytesIntx10_a2.a0;
+ result += passStruct7BytesIntx10_a2.a1;
+ result += passStruct7BytesIntx10_a2.a2;
+ result += passStruct7BytesIntx10_a3.a0;
+ result += passStruct7BytesIntx10_a3.a1;
+ result += passStruct7BytesIntx10_a3.a2;
+ result += passStruct7BytesIntx10_a4.a0;
+ result += passStruct7BytesIntx10_a4.a1;
+ result += passStruct7BytesIntx10_a4.a2;
+ result += passStruct7BytesIntx10_a5.a0;
+ result += passStruct7BytesIntx10_a5.a1;
+ result += passStruct7BytesIntx10_a5.a2;
+ result += passStruct7BytesIntx10_a6.a0;
+ result += passStruct7BytesIntx10_a6.a1;
+ result += passStruct7BytesIntx10_a6.a2;
+ result += passStruct7BytesIntx10_a7.a0;
+ result += passStruct7BytesIntx10_a7.a1;
+ result += passStruct7BytesIntx10_a7.a2;
+ result += passStruct7BytesIntx10_a8.a0;
+ result += passStruct7BytesIntx10_a8.a1;
+ result += passStruct7BytesIntx10_a8.a2;
+ result += passStruct7BytesIntx10_a9.a0;
+ result += passStruct7BytesIntx10_a9.a1;
+ result += passStruct7BytesIntx10_a9.a2;
+
+ passStruct7BytesIntx10Result = result;
+
+ return result;
+}
+
+/// Sub word size on 64 bit architectures.
+/// 10 struct arguments will exhaust available registers.
+int passStruct7BytesIntx10(
+ Struct7BytesInt a0,
+ Struct7BytesInt a1,
+ Struct7BytesInt a2,
+ Struct7BytesInt a3,
+ Struct7BytesInt a4,
+ Struct7BytesInt a5,
+ Struct7BytesInt a6,
+ Struct7BytesInt a7,
+ Struct7BytesInt a8,
+ Struct7BytesInt a9) {
+ print(
+ "passStruct7BytesIntx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct7BytesIntx10 throwing on purpuse!");
+ }
+
+ passStruct7BytesIntx10_a0 = a0;
+ passStruct7BytesIntx10_a1 = a1;
+ passStruct7BytesIntx10_a2 = a2;
+ passStruct7BytesIntx10_a3 = a3;
+ passStruct7BytesIntx10_a4 = a4;
+ passStruct7BytesIntx10_a5 = a5;
+ passStruct7BytesIntx10_a6 = a6;
+ passStruct7BytesIntx10_a7 = a7;
+ passStruct7BytesIntx10_a8 = a8;
+ passStruct7BytesIntx10_a9 = a9;
+
+ final result = passStruct7BytesIntx10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct7BytesIntx10AfterCallback() {
+ final result = passStruct7BytesIntx10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(15, result);
+}
+
+typedef PassStruct8BytesIntx10Type = Int64 Function(
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct8BytesInt passStruct8BytesIntx10_a0 = Struct8BytesInt();
+Struct8BytesInt passStruct8BytesIntx10_a1 = Struct8BytesInt();
+Struct8BytesInt passStruct8BytesIntx10_a2 = Struct8BytesInt();
+Struct8BytesInt passStruct8BytesIntx10_a3 = Struct8BytesInt();
+Struct8BytesInt passStruct8BytesIntx10_a4 = Struct8BytesInt();
+Struct8BytesInt passStruct8BytesIntx10_a5 = Struct8BytesInt();
+Struct8BytesInt passStruct8BytesIntx10_a6 = Struct8BytesInt();
+Struct8BytesInt passStruct8BytesIntx10_a7 = Struct8BytesInt();
+Struct8BytesInt passStruct8BytesIntx10_a8 = Struct8BytesInt();
+Struct8BytesInt passStruct8BytesIntx10_a9 = Struct8BytesInt();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct8BytesIntx10Result = 0;
+
+int passStruct8BytesIntx10CalculateResult() {
+ int result = 0;
+
+ result += passStruct8BytesIntx10_a0.a0;
+ result += passStruct8BytesIntx10_a0.a1;
+ result += passStruct8BytesIntx10_a0.a2;
+ result += passStruct8BytesIntx10_a1.a0;
+ result += passStruct8BytesIntx10_a1.a1;
+ result += passStruct8BytesIntx10_a1.a2;
+ result += passStruct8BytesIntx10_a2.a0;
+ result += passStruct8BytesIntx10_a2.a1;
+ result += passStruct8BytesIntx10_a2.a2;
+ result += passStruct8BytesIntx10_a3.a0;
+ result += passStruct8BytesIntx10_a3.a1;
+ result += passStruct8BytesIntx10_a3.a2;
+ result += passStruct8BytesIntx10_a4.a0;
+ result += passStruct8BytesIntx10_a4.a1;
+ result += passStruct8BytesIntx10_a4.a2;
+ result += passStruct8BytesIntx10_a5.a0;
+ result += passStruct8BytesIntx10_a5.a1;
+ result += passStruct8BytesIntx10_a5.a2;
+ result += passStruct8BytesIntx10_a6.a0;
+ result += passStruct8BytesIntx10_a6.a1;
+ result += passStruct8BytesIntx10_a6.a2;
+ result += passStruct8BytesIntx10_a7.a0;
+ result += passStruct8BytesIntx10_a7.a1;
+ result += passStruct8BytesIntx10_a7.a2;
+ result += passStruct8BytesIntx10_a8.a0;
+ result += passStruct8BytesIntx10_a8.a1;
+ result += passStruct8BytesIntx10_a8.a2;
+ result += passStruct8BytesIntx10_a9.a0;
+ result += passStruct8BytesIntx10_a9.a1;
+ result += passStruct8BytesIntx10_a9.a2;
+
+ passStruct8BytesIntx10Result = result;
+
+ return result;
+}
+
+/// Exactly word size struct on 64bit architectures.
+/// 10 struct arguments will exhaust available registers.
+int passStruct8BytesIntx10(
+ Struct8BytesInt a0,
+ Struct8BytesInt a1,
+ Struct8BytesInt a2,
+ Struct8BytesInt a3,
+ Struct8BytesInt a4,
+ Struct8BytesInt a5,
+ Struct8BytesInt a6,
+ Struct8BytesInt a7,
+ Struct8BytesInt a8,
+ Struct8BytesInt a9) {
+ print(
+ "passStruct8BytesIntx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct8BytesIntx10 throwing on purpuse!");
+ }
+
+ passStruct8BytesIntx10_a0 = a0;
+ passStruct8BytesIntx10_a1 = a1;
+ passStruct8BytesIntx10_a2 = a2;
+ passStruct8BytesIntx10_a3 = a3;
+ passStruct8BytesIntx10_a4 = a4;
+ passStruct8BytesIntx10_a5 = a5;
+ passStruct8BytesIntx10_a6 = a6;
+ passStruct8BytesIntx10_a7 = a7;
+ passStruct8BytesIntx10_a8 = a8;
+ passStruct8BytesIntx10_a9 = a9;
+
+ final result = passStruct8BytesIntx10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct8BytesIntx10AfterCallback() {
+ final result = passStruct8BytesIntx10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(15, result);
+}
+
+typedef PassStruct8BytesHomogeneousFloatx10Type = Float Function(
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat);
+
+// Global variables to be able to test inputs after callback returned.
+Struct8BytesHomogeneousFloat passStruct8BytesHomogeneousFloatx10_a0 =
+ Struct8BytesHomogeneousFloat();
+Struct8BytesHomogeneousFloat passStruct8BytesHomogeneousFloatx10_a1 =
+ Struct8BytesHomogeneousFloat();
+Struct8BytesHomogeneousFloat passStruct8BytesHomogeneousFloatx10_a2 =
+ Struct8BytesHomogeneousFloat();
+Struct8BytesHomogeneousFloat passStruct8BytesHomogeneousFloatx10_a3 =
+ Struct8BytesHomogeneousFloat();
+Struct8BytesHomogeneousFloat passStruct8BytesHomogeneousFloatx10_a4 =
+ Struct8BytesHomogeneousFloat();
+Struct8BytesHomogeneousFloat passStruct8BytesHomogeneousFloatx10_a5 =
+ Struct8BytesHomogeneousFloat();
+Struct8BytesHomogeneousFloat passStruct8BytesHomogeneousFloatx10_a6 =
+ Struct8BytesHomogeneousFloat();
+Struct8BytesHomogeneousFloat passStruct8BytesHomogeneousFloatx10_a7 =
+ Struct8BytesHomogeneousFloat();
+Struct8BytesHomogeneousFloat passStruct8BytesHomogeneousFloatx10_a8 =
+ Struct8BytesHomogeneousFloat();
+Struct8BytesHomogeneousFloat passStruct8BytesHomogeneousFloatx10_a9 =
+ Struct8BytesHomogeneousFloat();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct8BytesHomogeneousFloatx10Result = 0.0;
+
+double passStruct8BytesHomogeneousFloatx10CalculateResult() {
+ double result = 0;
+
+ result += passStruct8BytesHomogeneousFloatx10_a0.a0;
+ result += passStruct8BytesHomogeneousFloatx10_a0.a1;
+ result += passStruct8BytesHomogeneousFloatx10_a1.a0;
+ result += passStruct8BytesHomogeneousFloatx10_a1.a1;
+ result += passStruct8BytesHomogeneousFloatx10_a2.a0;
+ result += passStruct8BytesHomogeneousFloatx10_a2.a1;
+ result += passStruct8BytesHomogeneousFloatx10_a3.a0;
+ result += passStruct8BytesHomogeneousFloatx10_a3.a1;
+ result += passStruct8BytesHomogeneousFloatx10_a4.a0;
+ result += passStruct8BytesHomogeneousFloatx10_a4.a1;
+ result += passStruct8BytesHomogeneousFloatx10_a5.a0;
+ result += passStruct8BytesHomogeneousFloatx10_a5.a1;
+ result += passStruct8BytesHomogeneousFloatx10_a6.a0;
+ result += passStruct8BytesHomogeneousFloatx10_a6.a1;
+ result += passStruct8BytesHomogeneousFloatx10_a7.a0;
+ result += passStruct8BytesHomogeneousFloatx10_a7.a1;
+ result += passStruct8BytesHomogeneousFloatx10_a8.a0;
+ result += passStruct8BytesHomogeneousFloatx10_a8.a1;
+ result += passStruct8BytesHomogeneousFloatx10_a9.a0;
+ result += passStruct8BytesHomogeneousFloatx10_a9.a1;
+
+ passStruct8BytesHomogeneousFloatx10Result = result;
+
+ return result;
+}
+
+/// Arguments passed in FP registers as long as they fit.
+/// 10 struct arguments will exhaust available registers.
+double passStruct8BytesHomogeneousFloatx10(
+ Struct8BytesHomogeneousFloat a0,
+ Struct8BytesHomogeneousFloat a1,
+ Struct8BytesHomogeneousFloat a2,
+ Struct8BytesHomogeneousFloat a3,
+ Struct8BytesHomogeneousFloat a4,
+ Struct8BytesHomogeneousFloat a5,
+ Struct8BytesHomogeneousFloat a6,
+ Struct8BytesHomogeneousFloat a7,
+ Struct8BytesHomogeneousFloat a8,
+ Struct8BytesHomogeneousFloat a9) {
+ print(
+ "passStruct8BytesHomogeneousFloatx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct8BytesHomogeneousFloatx10 throwing on purpuse!");
+ }
+
+ passStruct8BytesHomogeneousFloatx10_a0 = a0;
+ passStruct8BytesHomogeneousFloatx10_a1 = a1;
+ passStruct8BytesHomogeneousFloatx10_a2 = a2;
+ passStruct8BytesHomogeneousFloatx10_a3 = a3;
+ passStruct8BytesHomogeneousFloatx10_a4 = a4;
+ passStruct8BytesHomogeneousFloatx10_a5 = a5;
+ passStruct8BytesHomogeneousFloatx10_a6 = a6;
+ passStruct8BytesHomogeneousFloatx10_a7 = a7;
+ passStruct8BytesHomogeneousFloatx10_a8 = a8;
+ passStruct8BytesHomogeneousFloatx10_a9 = a9;
+
+ final result = passStruct8BytesHomogeneousFloatx10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct8BytesHomogeneousFloatx10AfterCallback() {
+ final result = passStruct8BytesHomogeneousFloatx10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(10.0, result);
+}
+
+typedef PassStruct8BytesMixedx10Type = Float Function(
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed);
+
+// Global variables to be able to test inputs after callback returned.
+Struct8BytesMixed passStruct8BytesMixedx10_a0 = Struct8BytesMixed();
+Struct8BytesMixed passStruct8BytesMixedx10_a1 = Struct8BytesMixed();
+Struct8BytesMixed passStruct8BytesMixedx10_a2 = Struct8BytesMixed();
+Struct8BytesMixed passStruct8BytesMixedx10_a3 = Struct8BytesMixed();
+Struct8BytesMixed passStruct8BytesMixedx10_a4 = Struct8BytesMixed();
+Struct8BytesMixed passStruct8BytesMixedx10_a5 = Struct8BytesMixed();
+Struct8BytesMixed passStruct8BytesMixedx10_a6 = Struct8BytesMixed();
+Struct8BytesMixed passStruct8BytesMixedx10_a7 = Struct8BytesMixed();
+Struct8BytesMixed passStruct8BytesMixedx10_a8 = Struct8BytesMixed();
+Struct8BytesMixed passStruct8BytesMixedx10_a9 = Struct8BytesMixed();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct8BytesMixedx10Result = 0.0;
+
+double passStruct8BytesMixedx10CalculateResult() {
+ double result = 0;
+
+ result += passStruct8BytesMixedx10_a0.a0;
+ result += passStruct8BytesMixedx10_a0.a1;
+ result += passStruct8BytesMixedx10_a0.a2;
+ result += passStruct8BytesMixedx10_a1.a0;
+ result += passStruct8BytesMixedx10_a1.a1;
+ result += passStruct8BytesMixedx10_a1.a2;
+ result += passStruct8BytesMixedx10_a2.a0;
+ result += passStruct8BytesMixedx10_a2.a1;
+ result += passStruct8BytesMixedx10_a2.a2;
+ result += passStruct8BytesMixedx10_a3.a0;
+ result += passStruct8BytesMixedx10_a3.a1;
+ result += passStruct8BytesMixedx10_a3.a2;
+ result += passStruct8BytesMixedx10_a4.a0;
+ result += passStruct8BytesMixedx10_a4.a1;
+ result += passStruct8BytesMixedx10_a4.a2;
+ result += passStruct8BytesMixedx10_a5.a0;
+ result += passStruct8BytesMixedx10_a5.a1;
+ result += passStruct8BytesMixedx10_a5.a2;
+ result += passStruct8BytesMixedx10_a6.a0;
+ result += passStruct8BytesMixedx10_a6.a1;
+ result += passStruct8BytesMixedx10_a6.a2;
+ result += passStruct8BytesMixedx10_a7.a0;
+ result += passStruct8BytesMixedx10_a7.a1;
+ result += passStruct8BytesMixedx10_a7.a2;
+ result += passStruct8BytesMixedx10_a8.a0;
+ result += passStruct8BytesMixedx10_a8.a1;
+ result += passStruct8BytesMixedx10_a8.a2;
+ result += passStruct8BytesMixedx10_a9.a0;
+ result += passStruct8BytesMixedx10_a9.a1;
+ result += passStruct8BytesMixedx10_a9.a2;
+
+ passStruct8BytesMixedx10Result = result;
+
+ return result;
+}
+
+/// On x64, arguments go in int registers because it is not only float.
+/// 10 struct arguments will exhaust available registers.
+double passStruct8BytesMixedx10(
+ Struct8BytesMixed a0,
+ Struct8BytesMixed a1,
+ Struct8BytesMixed a2,
+ Struct8BytesMixed a3,
+ Struct8BytesMixed a4,
+ Struct8BytesMixed a5,
+ Struct8BytesMixed a6,
+ Struct8BytesMixed a7,
+ Struct8BytesMixed a8,
+ Struct8BytesMixed a9) {
+ print(
+ "passStruct8BytesMixedx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct8BytesMixedx10 throwing on purpuse!");
+ }
+
+ passStruct8BytesMixedx10_a0 = a0;
+ passStruct8BytesMixedx10_a1 = a1;
+ passStruct8BytesMixedx10_a2 = a2;
+ passStruct8BytesMixedx10_a3 = a3;
+ passStruct8BytesMixedx10_a4 = a4;
+ passStruct8BytesMixedx10_a5 = a5;
+ passStruct8BytesMixedx10_a6 = a6;
+ passStruct8BytesMixedx10_a7 = a7;
+ passStruct8BytesMixedx10_a8 = a8;
+ passStruct8BytesMixedx10_a9 = a9;
+
+ final result = passStruct8BytesMixedx10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct8BytesMixedx10AfterCallback() {
+ final result = passStruct8BytesMixedx10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(15.0, result);
+}
+
+typedef PassStruct9BytesIntx10Type = Int64 Function(
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct9BytesInt passStruct9BytesIntx10_a0 = Struct9BytesInt();
+Struct9BytesInt passStruct9BytesIntx10_a1 = Struct9BytesInt();
+Struct9BytesInt passStruct9BytesIntx10_a2 = Struct9BytesInt();
+Struct9BytesInt passStruct9BytesIntx10_a3 = Struct9BytesInt();
+Struct9BytesInt passStruct9BytesIntx10_a4 = Struct9BytesInt();
+Struct9BytesInt passStruct9BytesIntx10_a5 = Struct9BytesInt();
+Struct9BytesInt passStruct9BytesIntx10_a6 = Struct9BytesInt();
+Struct9BytesInt passStruct9BytesIntx10_a7 = Struct9BytesInt();
+Struct9BytesInt passStruct9BytesIntx10_a8 = Struct9BytesInt();
+Struct9BytesInt passStruct9BytesIntx10_a9 = Struct9BytesInt();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct9BytesIntx10Result = 0;
+
+int passStruct9BytesIntx10CalculateResult() {
+ int result = 0;
+
+ result += passStruct9BytesIntx10_a0.a0;
+ result += passStruct9BytesIntx10_a0.a1;
+ result += passStruct9BytesIntx10_a1.a0;
+ result += passStruct9BytesIntx10_a1.a1;
+ result += passStruct9BytesIntx10_a2.a0;
+ result += passStruct9BytesIntx10_a2.a1;
+ result += passStruct9BytesIntx10_a3.a0;
+ result += passStruct9BytesIntx10_a3.a1;
+ result += passStruct9BytesIntx10_a4.a0;
+ result += passStruct9BytesIntx10_a4.a1;
+ result += passStruct9BytesIntx10_a5.a0;
+ result += passStruct9BytesIntx10_a5.a1;
+ result += passStruct9BytesIntx10_a6.a0;
+ result += passStruct9BytesIntx10_a6.a1;
+ result += passStruct9BytesIntx10_a7.a0;
+ result += passStruct9BytesIntx10_a7.a1;
+ result += passStruct9BytesIntx10_a8.a0;
+ result += passStruct9BytesIntx10_a8.a1;
+ result += passStruct9BytesIntx10_a9.a0;
+ result += passStruct9BytesIntx10_a9.a1;
+
+ passStruct9BytesIntx10Result = result;
+
+ return result;
+}
+
+/// Argument is a single byte over a multiple of word size.
+/// 10 struct arguments will exhaust available registers.
+/// Tests upper bytes in the integer registers that are partly filled.
+/// Tests stack alignment of non word size stack arguments.
+int passStruct9BytesIntx10(
+ Struct9BytesInt a0,
+ Struct9BytesInt a1,
+ Struct9BytesInt a2,
+ Struct9BytesInt a3,
+ Struct9BytesInt a4,
+ Struct9BytesInt a5,
+ Struct9BytesInt a6,
+ Struct9BytesInt a7,
+ Struct9BytesInt a8,
+ Struct9BytesInt a9) {
+ print(
+ "passStruct9BytesIntx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct9BytesIntx10 throwing on purpuse!");
+ }
+
+ passStruct9BytesIntx10_a0 = a0;
+ passStruct9BytesIntx10_a1 = a1;
+ passStruct9BytesIntx10_a2 = a2;
+ passStruct9BytesIntx10_a3 = a3;
+ passStruct9BytesIntx10_a4 = a4;
+ passStruct9BytesIntx10_a5 = a5;
+ passStruct9BytesIntx10_a6 = a6;
+ passStruct9BytesIntx10_a7 = a7;
+ passStruct9BytesIntx10_a8 = a8;
+ passStruct9BytesIntx10_a9 = a9;
+
+ final result = passStruct9BytesIntx10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct9BytesIntx10AfterCallback() {
+ final result = passStruct9BytesIntx10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(10, result);
+}
+
+typedef PassStruct9BytesHomogeneousUint82x10Type = Int64 Function(
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82);
+
+// Global variables to be able to test inputs after callback returned.
+Struct9BytesHomogeneousUint82 passStruct9BytesHomogeneousUint82x10_a0 =
+ Struct9BytesHomogeneousUint82();
+Struct9BytesHomogeneousUint82 passStruct9BytesHomogeneousUint82x10_a1 =
+ Struct9BytesHomogeneousUint82();
+Struct9BytesHomogeneousUint82 passStruct9BytesHomogeneousUint82x10_a2 =
+ Struct9BytesHomogeneousUint82();
+Struct9BytesHomogeneousUint82 passStruct9BytesHomogeneousUint82x10_a3 =
+ Struct9BytesHomogeneousUint82();
+Struct9BytesHomogeneousUint82 passStruct9BytesHomogeneousUint82x10_a4 =
+ Struct9BytesHomogeneousUint82();
+Struct9BytesHomogeneousUint82 passStruct9BytesHomogeneousUint82x10_a5 =
+ Struct9BytesHomogeneousUint82();
+Struct9BytesHomogeneousUint82 passStruct9BytesHomogeneousUint82x10_a6 =
+ Struct9BytesHomogeneousUint82();
+Struct9BytesHomogeneousUint82 passStruct9BytesHomogeneousUint82x10_a7 =
+ Struct9BytesHomogeneousUint82();
+Struct9BytesHomogeneousUint82 passStruct9BytesHomogeneousUint82x10_a8 =
+ Struct9BytesHomogeneousUint82();
+Struct9BytesHomogeneousUint82 passStruct9BytesHomogeneousUint82x10_a9 =
+ Struct9BytesHomogeneousUint82();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct9BytesHomogeneousUint82x10Result = 0;
+
+int passStruct9BytesHomogeneousUint82x10CalculateResult() {
+ int result = 0;
+
+ result += passStruct9BytesHomogeneousUint82x10_a0.a0;
+ result += passStruct9BytesHomogeneousUint82x10_a0.a1;
+ result += passStruct9BytesHomogeneousUint82x10_a0.a2;
+ result += passStruct9BytesHomogeneousUint82x10_a0.a3;
+ result += passStruct9BytesHomogeneousUint82x10_a0.a4;
+ result += passStruct9BytesHomogeneousUint82x10_a0.a5;
+ result += passStruct9BytesHomogeneousUint82x10_a0.a6;
+ result += passStruct9BytesHomogeneousUint82x10_a0.a7;
+ result += passStruct9BytesHomogeneousUint82x10_a0.a8;
+ result += passStruct9BytesHomogeneousUint82x10_a1.a0;
+ result += passStruct9BytesHomogeneousUint82x10_a1.a1;
+ result += passStruct9BytesHomogeneousUint82x10_a1.a2;
+ result += passStruct9BytesHomogeneousUint82x10_a1.a3;
+ result += passStruct9BytesHomogeneousUint82x10_a1.a4;
+ result += passStruct9BytesHomogeneousUint82x10_a1.a5;
+ result += passStruct9BytesHomogeneousUint82x10_a1.a6;
+ result += passStruct9BytesHomogeneousUint82x10_a1.a7;
+ result += passStruct9BytesHomogeneousUint82x10_a1.a8;
+ result += passStruct9BytesHomogeneousUint82x10_a2.a0;
+ result += passStruct9BytesHomogeneousUint82x10_a2.a1;
+ result += passStruct9BytesHomogeneousUint82x10_a2.a2;
+ result += passStruct9BytesHomogeneousUint82x10_a2.a3;
+ result += passStruct9BytesHomogeneousUint82x10_a2.a4;
+ result += passStruct9BytesHomogeneousUint82x10_a2.a5;
+ result += passStruct9BytesHomogeneousUint82x10_a2.a6;
+ result += passStruct9BytesHomogeneousUint82x10_a2.a7;
+ result += passStruct9BytesHomogeneousUint82x10_a2.a8;
+ result += passStruct9BytesHomogeneousUint82x10_a3.a0;
+ result += passStruct9BytesHomogeneousUint82x10_a3.a1;
+ result += passStruct9BytesHomogeneousUint82x10_a3.a2;
+ result += passStruct9BytesHomogeneousUint82x10_a3.a3;
+ result += passStruct9BytesHomogeneousUint82x10_a3.a4;
+ result += passStruct9BytesHomogeneousUint82x10_a3.a5;
+ result += passStruct9BytesHomogeneousUint82x10_a3.a6;
+ result += passStruct9BytesHomogeneousUint82x10_a3.a7;
+ result += passStruct9BytesHomogeneousUint82x10_a3.a8;
+ result += passStruct9BytesHomogeneousUint82x10_a4.a0;
+ result += passStruct9BytesHomogeneousUint82x10_a4.a1;
+ result += passStruct9BytesHomogeneousUint82x10_a4.a2;
+ result += passStruct9BytesHomogeneousUint82x10_a4.a3;
+ result += passStruct9BytesHomogeneousUint82x10_a4.a4;
+ result += passStruct9BytesHomogeneousUint82x10_a4.a5;
+ result += passStruct9BytesHomogeneousUint82x10_a4.a6;
+ result += passStruct9BytesHomogeneousUint82x10_a4.a7;
+ result += passStruct9BytesHomogeneousUint82x10_a4.a8;
+ result += passStruct9BytesHomogeneousUint82x10_a5.a0;
+ result += passStruct9BytesHomogeneousUint82x10_a5.a1;
+ result += passStruct9BytesHomogeneousUint82x10_a5.a2;
+ result += passStruct9BytesHomogeneousUint82x10_a5.a3;
+ result += passStruct9BytesHomogeneousUint82x10_a5.a4;
+ result += passStruct9BytesHomogeneousUint82x10_a5.a5;
+ result += passStruct9BytesHomogeneousUint82x10_a5.a6;
+ result += passStruct9BytesHomogeneousUint82x10_a5.a7;
+ result += passStruct9BytesHomogeneousUint82x10_a5.a8;
+ result += passStruct9BytesHomogeneousUint82x10_a6.a0;
+ result += passStruct9BytesHomogeneousUint82x10_a6.a1;
+ result += passStruct9BytesHomogeneousUint82x10_a6.a2;
+ result += passStruct9BytesHomogeneousUint82x10_a6.a3;
+ result += passStruct9BytesHomogeneousUint82x10_a6.a4;
+ result += passStruct9BytesHomogeneousUint82x10_a6.a5;
+ result += passStruct9BytesHomogeneousUint82x10_a6.a6;
+ result += passStruct9BytesHomogeneousUint82x10_a6.a7;
+ result += passStruct9BytesHomogeneousUint82x10_a6.a8;
+ result += passStruct9BytesHomogeneousUint82x10_a7.a0;
+ result += passStruct9BytesHomogeneousUint82x10_a7.a1;
+ result += passStruct9BytesHomogeneousUint82x10_a7.a2;
+ result += passStruct9BytesHomogeneousUint82x10_a7.a3;
+ result += passStruct9BytesHomogeneousUint82x10_a7.a4;
+ result += passStruct9BytesHomogeneousUint82x10_a7.a5;
+ result += passStruct9BytesHomogeneousUint82x10_a7.a6;
+ result += passStruct9BytesHomogeneousUint82x10_a7.a7;
+ result += passStruct9BytesHomogeneousUint82x10_a7.a8;
+ result += passStruct9BytesHomogeneousUint82x10_a8.a0;
+ result += passStruct9BytesHomogeneousUint82x10_a8.a1;
+ result += passStruct9BytesHomogeneousUint82x10_a8.a2;
+ result += passStruct9BytesHomogeneousUint82x10_a8.a3;
+ result += passStruct9BytesHomogeneousUint82x10_a8.a4;
+ result += passStruct9BytesHomogeneousUint82x10_a8.a5;
+ result += passStruct9BytesHomogeneousUint82x10_a8.a6;
+ result += passStruct9BytesHomogeneousUint82x10_a8.a7;
+ result += passStruct9BytesHomogeneousUint82x10_a8.a8;
+ result += passStruct9BytesHomogeneousUint82x10_a9.a0;
+ result += passStruct9BytesHomogeneousUint82x10_a9.a1;
+ result += passStruct9BytesHomogeneousUint82x10_a9.a2;
+ result += passStruct9BytesHomogeneousUint82x10_a9.a3;
+ result += passStruct9BytesHomogeneousUint82x10_a9.a4;
+ result += passStruct9BytesHomogeneousUint82x10_a9.a5;
+ result += passStruct9BytesHomogeneousUint82x10_a9.a6;
+ result += passStruct9BytesHomogeneousUint82x10_a9.a7;
+ result += passStruct9BytesHomogeneousUint82x10_a9.a8;
+
+ passStruct9BytesHomogeneousUint82x10Result = result;
+
+ return result;
+}
+
+/// Argument is a single byte over a multiple of word size.
+/// 10 struct arguments will exhaust available registers.
+/// Struct only has 1-byte aligned fields to test struct alignment itself.
+///
+int passStruct9BytesHomogeneousUint82x10(
+ Struct9BytesHomogeneousUint82 a0,
+ Struct9BytesHomogeneousUint82 a1,
+ Struct9BytesHomogeneousUint82 a2,
+ Struct9BytesHomogeneousUint82 a3,
+ Struct9BytesHomogeneousUint82 a4,
+ Struct9BytesHomogeneousUint82 a5,
+ Struct9BytesHomogeneousUint82 a6,
+ Struct9BytesHomogeneousUint82 a7,
+ Struct9BytesHomogeneousUint82 a8,
+ Struct9BytesHomogeneousUint82 a9) {
+ print(
+ "passStruct9BytesHomogeneousUint82x10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassStruct9BytesHomogeneousUint82x10 throwing on purpuse!");
+ }
+
+ passStruct9BytesHomogeneousUint82x10_a0 = a0;
+ passStruct9BytesHomogeneousUint82x10_a1 = a1;
+ passStruct9BytesHomogeneousUint82x10_a2 = a2;
+ passStruct9BytesHomogeneousUint82x10_a3 = a3;
+ passStruct9BytesHomogeneousUint82x10_a4 = a4;
+ passStruct9BytesHomogeneousUint82x10_a5 = a5;
+ passStruct9BytesHomogeneousUint82x10_a6 = a6;
+ passStruct9BytesHomogeneousUint82x10_a7 = a7;
+ passStruct9BytesHomogeneousUint82x10_a8 = a8;
+ passStruct9BytesHomogeneousUint82x10_a9 = a9;
+
+ final result = passStruct9BytesHomogeneousUint82x10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct9BytesHomogeneousUint82x10AfterCallback() {
+ final result = passStruct9BytesHomogeneousUint82x10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(4095, result);
+}
+
+typedef PassStruct12BytesHomogeneousFloatx6Type = Float Function(
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat);
+
+// Global variables to be able to test inputs after callback returned.
+Struct12BytesHomogeneousFloat passStruct12BytesHomogeneousFloatx6_a0 =
+ Struct12BytesHomogeneousFloat();
+Struct12BytesHomogeneousFloat passStruct12BytesHomogeneousFloatx6_a1 =
+ Struct12BytesHomogeneousFloat();
+Struct12BytesHomogeneousFloat passStruct12BytesHomogeneousFloatx6_a2 =
+ Struct12BytesHomogeneousFloat();
+Struct12BytesHomogeneousFloat passStruct12BytesHomogeneousFloatx6_a3 =
+ Struct12BytesHomogeneousFloat();
+Struct12BytesHomogeneousFloat passStruct12BytesHomogeneousFloatx6_a4 =
+ Struct12BytesHomogeneousFloat();
+Struct12BytesHomogeneousFloat passStruct12BytesHomogeneousFloatx6_a5 =
+ Struct12BytesHomogeneousFloat();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct12BytesHomogeneousFloatx6Result = 0.0;
+
+double passStruct12BytesHomogeneousFloatx6CalculateResult() {
+ double result = 0;
+
+ result += passStruct12BytesHomogeneousFloatx6_a0.a0;
+ result += passStruct12BytesHomogeneousFloatx6_a0.a1;
+ result += passStruct12BytesHomogeneousFloatx6_a0.a2;
+ result += passStruct12BytesHomogeneousFloatx6_a1.a0;
+ result += passStruct12BytesHomogeneousFloatx6_a1.a1;
+ result += passStruct12BytesHomogeneousFloatx6_a1.a2;
+ result += passStruct12BytesHomogeneousFloatx6_a2.a0;
+ result += passStruct12BytesHomogeneousFloatx6_a2.a1;
+ result += passStruct12BytesHomogeneousFloatx6_a2.a2;
+ result += passStruct12BytesHomogeneousFloatx6_a3.a0;
+ result += passStruct12BytesHomogeneousFloatx6_a3.a1;
+ result += passStruct12BytesHomogeneousFloatx6_a3.a2;
+ result += passStruct12BytesHomogeneousFloatx6_a4.a0;
+ result += passStruct12BytesHomogeneousFloatx6_a4.a1;
+ result += passStruct12BytesHomogeneousFloatx6_a4.a2;
+ result += passStruct12BytesHomogeneousFloatx6_a5.a0;
+ result += passStruct12BytesHomogeneousFloatx6_a5.a1;
+ result += passStruct12BytesHomogeneousFloatx6_a5.a2;
+
+ passStruct12BytesHomogeneousFloatx6Result = result;
+
+ return result;
+}
+
+/// Arguments in FPU registers on arm hardfp and arm64.
+/// Struct arguments will exhaust available registers, and leave some empty.
+/// The last argument is to test whether arguments are backfilled.
+double passStruct12BytesHomogeneousFloatx6(
+ Struct12BytesHomogeneousFloat a0,
+ Struct12BytesHomogeneousFloat a1,
+ Struct12BytesHomogeneousFloat a2,
+ Struct12BytesHomogeneousFloat a3,
+ Struct12BytesHomogeneousFloat a4,
+ Struct12BytesHomogeneousFloat a5) {
+ print(
+ "passStruct12BytesHomogeneousFloatx6(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct12BytesHomogeneousFloatx6 throwing on purpuse!");
+ }
+
+ passStruct12BytesHomogeneousFloatx6_a0 = a0;
+ passStruct12BytesHomogeneousFloatx6_a1 = a1;
+ passStruct12BytesHomogeneousFloatx6_a2 = a2;
+ passStruct12BytesHomogeneousFloatx6_a3 = a3;
+ passStruct12BytesHomogeneousFloatx6_a4 = a4;
+ passStruct12BytesHomogeneousFloatx6_a5 = a5;
+
+ final result = passStruct12BytesHomogeneousFloatx6CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct12BytesHomogeneousFloatx6AfterCallback() {
+ final result = passStruct12BytesHomogeneousFloatx6CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(9.0, result);
+}
+
+typedef PassStruct16BytesHomogeneousFloatx5Type = Float Function(
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat);
+
+// Global variables to be able to test inputs after callback returned.
+Struct16BytesHomogeneousFloat passStruct16BytesHomogeneousFloatx5_a0 =
+ Struct16BytesHomogeneousFloat();
+Struct16BytesHomogeneousFloat passStruct16BytesHomogeneousFloatx5_a1 =
+ Struct16BytesHomogeneousFloat();
+Struct16BytesHomogeneousFloat passStruct16BytesHomogeneousFloatx5_a2 =
+ Struct16BytesHomogeneousFloat();
+Struct16BytesHomogeneousFloat passStruct16BytesHomogeneousFloatx5_a3 =
+ Struct16BytesHomogeneousFloat();
+Struct16BytesHomogeneousFloat passStruct16BytesHomogeneousFloatx5_a4 =
+ Struct16BytesHomogeneousFloat();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct16BytesHomogeneousFloatx5Result = 0.0;
+
+double passStruct16BytesHomogeneousFloatx5CalculateResult() {
+ double result = 0;
+
+ result += passStruct16BytesHomogeneousFloatx5_a0.a0;
+ result += passStruct16BytesHomogeneousFloatx5_a0.a1;
+ result += passStruct16BytesHomogeneousFloatx5_a0.a2;
+ result += passStruct16BytesHomogeneousFloatx5_a0.a3;
+ result += passStruct16BytesHomogeneousFloatx5_a1.a0;
+ result += passStruct16BytesHomogeneousFloatx5_a1.a1;
+ result += passStruct16BytesHomogeneousFloatx5_a1.a2;
+ result += passStruct16BytesHomogeneousFloatx5_a1.a3;
+ result += passStruct16BytesHomogeneousFloatx5_a2.a0;
+ result += passStruct16BytesHomogeneousFloatx5_a2.a1;
+ result += passStruct16BytesHomogeneousFloatx5_a2.a2;
+ result += passStruct16BytesHomogeneousFloatx5_a2.a3;
+ result += passStruct16BytesHomogeneousFloatx5_a3.a0;
+ result += passStruct16BytesHomogeneousFloatx5_a3.a1;
+ result += passStruct16BytesHomogeneousFloatx5_a3.a2;
+ result += passStruct16BytesHomogeneousFloatx5_a3.a3;
+ result += passStruct16BytesHomogeneousFloatx5_a4.a0;
+ result += passStruct16BytesHomogeneousFloatx5_a4.a1;
+ result += passStruct16BytesHomogeneousFloatx5_a4.a2;
+ result += passStruct16BytesHomogeneousFloatx5_a4.a3;
+
+ passStruct16BytesHomogeneousFloatx5Result = result;
+
+ return result;
+}
+
+/// On Linux x64 argument is transferred on stack because it is over 16 bytes.
+/// Arguments in FPU registers on arm hardfp and arm64.
+/// 5 struct arguments will exhaust available registers.
+double passStruct16BytesHomogeneousFloatx5(
+ Struct16BytesHomogeneousFloat a0,
+ Struct16BytesHomogeneousFloat a1,
+ Struct16BytesHomogeneousFloat a2,
+ Struct16BytesHomogeneousFloat a3,
+ Struct16BytesHomogeneousFloat a4) {
+ print(
+ "passStruct16BytesHomogeneousFloatx5(${a0}, ${a1}, ${a2}, ${a3}, ${a4})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct16BytesHomogeneousFloatx5 throwing on purpuse!");
+ }
+
+ passStruct16BytesHomogeneousFloatx5_a0 = a0;
+ passStruct16BytesHomogeneousFloatx5_a1 = a1;
+ passStruct16BytesHomogeneousFloatx5_a2 = a2;
+ passStruct16BytesHomogeneousFloatx5_a3 = a3;
+ passStruct16BytesHomogeneousFloatx5_a4 = a4;
+
+ final result = passStruct16BytesHomogeneousFloatx5CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct16BytesHomogeneousFloatx5AfterCallback() {
+ final result = passStruct16BytesHomogeneousFloatx5CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(10.0, result);
+}
+
+typedef PassStruct16BytesMixedx10Type = Double Function(
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed);
+
+// Global variables to be able to test inputs after callback returned.
+Struct16BytesMixed passStruct16BytesMixedx10_a0 = Struct16BytesMixed();
+Struct16BytesMixed passStruct16BytesMixedx10_a1 = Struct16BytesMixed();
+Struct16BytesMixed passStruct16BytesMixedx10_a2 = Struct16BytesMixed();
+Struct16BytesMixed passStruct16BytesMixedx10_a3 = Struct16BytesMixed();
+Struct16BytesMixed passStruct16BytesMixedx10_a4 = Struct16BytesMixed();
+Struct16BytesMixed passStruct16BytesMixedx10_a5 = Struct16BytesMixed();
+Struct16BytesMixed passStruct16BytesMixedx10_a6 = Struct16BytesMixed();
+Struct16BytesMixed passStruct16BytesMixedx10_a7 = Struct16BytesMixed();
+Struct16BytesMixed passStruct16BytesMixedx10_a8 = Struct16BytesMixed();
+Struct16BytesMixed passStruct16BytesMixedx10_a9 = Struct16BytesMixed();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct16BytesMixedx10Result = 0.0;
+
+double passStruct16BytesMixedx10CalculateResult() {
+ double result = 0;
+
+ result += passStruct16BytesMixedx10_a0.a0;
+ result += passStruct16BytesMixedx10_a0.a1;
+ result += passStruct16BytesMixedx10_a1.a0;
+ result += passStruct16BytesMixedx10_a1.a1;
+ result += passStruct16BytesMixedx10_a2.a0;
+ result += passStruct16BytesMixedx10_a2.a1;
+ result += passStruct16BytesMixedx10_a3.a0;
+ result += passStruct16BytesMixedx10_a3.a1;
+ result += passStruct16BytesMixedx10_a4.a0;
+ result += passStruct16BytesMixedx10_a4.a1;
+ result += passStruct16BytesMixedx10_a5.a0;
+ result += passStruct16BytesMixedx10_a5.a1;
+ result += passStruct16BytesMixedx10_a6.a0;
+ result += passStruct16BytesMixedx10_a6.a1;
+ result += passStruct16BytesMixedx10_a7.a0;
+ result += passStruct16BytesMixedx10_a7.a1;
+ result += passStruct16BytesMixedx10_a8.a0;
+ result += passStruct16BytesMixedx10_a8.a1;
+ result += passStruct16BytesMixedx10_a9.a0;
+ result += passStruct16BytesMixedx10_a9.a1;
+
+ passStruct16BytesMixedx10Result = result;
+
+ return result;
+}
+
+/// On x64, arguments are split over FP and int registers.
+/// On x64, it will exhaust the integer registers with the 6th argument.
+/// The rest goes on the stack.
+/// On arm, arguments are 8 byte aligned.
+double passStruct16BytesMixedx10(
+ Struct16BytesMixed a0,
+ Struct16BytesMixed a1,
+ Struct16BytesMixed a2,
+ Struct16BytesMixed a3,
+ Struct16BytesMixed a4,
+ Struct16BytesMixed a5,
+ Struct16BytesMixed a6,
+ Struct16BytesMixed a7,
+ Struct16BytesMixed a8,
+ Struct16BytesMixed a9) {
+ print(
+ "passStruct16BytesMixedx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct16BytesMixedx10 throwing on purpuse!");
+ }
+
+ passStruct16BytesMixedx10_a0 = a0;
+ passStruct16BytesMixedx10_a1 = a1;
+ passStruct16BytesMixedx10_a2 = a2;
+ passStruct16BytesMixedx10_a3 = a3;
+ passStruct16BytesMixedx10_a4 = a4;
+ passStruct16BytesMixedx10_a5 = a5;
+ passStruct16BytesMixedx10_a6 = a6;
+ passStruct16BytesMixedx10_a7 = a7;
+ passStruct16BytesMixedx10_a8 = a8;
+ passStruct16BytesMixedx10_a9 = a9;
+
+ final result = passStruct16BytesMixedx10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct16BytesMixedx10AfterCallback() {
+ final result = passStruct16BytesMixedx10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(10.0, result);
+}
+
+typedef PassStruct16BytesMixed2x10Type = Float Function(
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2);
+
+// Global variables to be able to test inputs after callback returned.
+Struct16BytesMixed2 passStruct16BytesMixed2x10_a0 = Struct16BytesMixed2();
+Struct16BytesMixed2 passStruct16BytesMixed2x10_a1 = Struct16BytesMixed2();
+Struct16BytesMixed2 passStruct16BytesMixed2x10_a2 = Struct16BytesMixed2();
+Struct16BytesMixed2 passStruct16BytesMixed2x10_a3 = Struct16BytesMixed2();
+Struct16BytesMixed2 passStruct16BytesMixed2x10_a4 = Struct16BytesMixed2();
+Struct16BytesMixed2 passStruct16BytesMixed2x10_a5 = Struct16BytesMixed2();
+Struct16BytesMixed2 passStruct16BytesMixed2x10_a6 = Struct16BytesMixed2();
+Struct16BytesMixed2 passStruct16BytesMixed2x10_a7 = Struct16BytesMixed2();
+Struct16BytesMixed2 passStruct16BytesMixed2x10_a8 = Struct16BytesMixed2();
+Struct16BytesMixed2 passStruct16BytesMixed2x10_a9 = Struct16BytesMixed2();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct16BytesMixed2x10Result = 0.0;
+
+double passStruct16BytesMixed2x10CalculateResult() {
+ double result = 0;
+
+ result += passStruct16BytesMixed2x10_a0.a0;
+ result += passStruct16BytesMixed2x10_a0.a1;
+ result += passStruct16BytesMixed2x10_a0.a2;
+ result += passStruct16BytesMixed2x10_a0.a3;
+ result += passStruct16BytesMixed2x10_a1.a0;
+ result += passStruct16BytesMixed2x10_a1.a1;
+ result += passStruct16BytesMixed2x10_a1.a2;
+ result += passStruct16BytesMixed2x10_a1.a3;
+ result += passStruct16BytesMixed2x10_a2.a0;
+ result += passStruct16BytesMixed2x10_a2.a1;
+ result += passStruct16BytesMixed2x10_a2.a2;
+ result += passStruct16BytesMixed2x10_a2.a3;
+ result += passStruct16BytesMixed2x10_a3.a0;
+ result += passStruct16BytesMixed2x10_a3.a1;
+ result += passStruct16BytesMixed2x10_a3.a2;
+ result += passStruct16BytesMixed2x10_a3.a3;
+ result += passStruct16BytesMixed2x10_a4.a0;
+ result += passStruct16BytesMixed2x10_a4.a1;
+ result += passStruct16BytesMixed2x10_a4.a2;
+ result += passStruct16BytesMixed2x10_a4.a3;
+ result += passStruct16BytesMixed2x10_a5.a0;
+ result += passStruct16BytesMixed2x10_a5.a1;
+ result += passStruct16BytesMixed2x10_a5.a2;
+ result += passStruct16BytesMixed2x10_a5.a3;
+ result += passStruct16BytesMixed2x10_a6.a0;
+ result += passStruct16BytesMixed2x10_a6.a1;
+ result += passStruct16BytesMixed2x10_a6.a2;
+ result += passStruct16BytesMixed2x10_a6.a3;
+ result += passStruct16BytesMixed2x10_a7.a0;
+ result += passStruct16BytesMixed2x10_a7.a1;
+ result += passStruct16BytesMixed2x10_a7.a2;
+ result += passStruct16BytesMixed2x10_a7.a3;
+ result += passStruct16BytesMixed2x10_a8.a0;
+ result += passStruct16BytesMixed2x10_a8.a1;
+ result += passStruct16BytesMixed2x10_a8.a2;
+ result += passStruct16BytesMixed2x10_a8.a3;
+ result += passStruct16BytesMixed2x10_a9.a0;
+ result += passStruct16BytesMixed2x10_a9.a1;
+ result += passStruct16BytesMixed2x10_a9.a2;
+ result += passStruct16BytesMixed2x10_a9.a3;
+
+ passStruct16BytesMixed2x10Result = result;
+
+ return result;
+}
+
+/// On x64, arguments are split over FP and int registers.
+/// On x64, it will exhaust the integer registers with the 6th argument.
+/// The rest goes on the stack.
+/// On arm, arguments are 4 byte aligned.
+double passStruct16BytesMixed2x10(
+ Struct16BytesMixed2 a0,
+ Struct16BytesMixed2 a1,
+ Struct16BytesMixed2 a2,
+ Struct16BytesMixed2 a3,
+ Struct16BytesMixed2 a4,
+ Struct16BytesMixed2 a5,
+ Struct16BytesMixed2 a6,
+ Struct16BytesMixed2 a7,
+ Struct16BytesMixed2 a8,
+ Struct16BytesMixed2 a9) {
+ print(
+ "passStruct16BytesMixed2x10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct16BytesMixed2x10 throwing on purpuse!");
+ }
+
+ passStruct16BytesMixed2x10_a0 = a0;
+ passStruct16BytesMixed2x10_a1 = a1;
+ passStruct16BytesMixed2x10_a2 = a2;
+ passStruct16BytesMixed2x10_a3 = a3;
+ passStruct16BytesMixed2x10_a4 = a4;
+ passStruct16BytesMixed2x10_a5 = a5;
+ passStruct16BytesMixed2x10_a6 = a6;
+ passStruct16BytesMixed2x10_a7 = a7;
+ passStruct16BytesMixed2x10_a8 = a8;
+ passStruct16BytesMixed2x10_a9 = a9;
+
+ final result = passStruct16BytesMixed2x10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct16BytesMixed2x10AfterCallback() {
+ final result = passStruct16BytesMixed2x10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(20.0, result);
+}
+
+typedef PassStruct17BytesIntx10Type = Int64 Function(
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct17BytesInt passStruct17BytesIntx10_a0 = Struct17BytesInt();
+Struct17BytesInt passStruct17BytesIntx10_a1 = Struct17BytesInt();
+Struct17BytesInt passStruct17BytesIntx10_a2 = Struct17BytesInt();
+Struct17BytesInt passStruct17BytesIntx10_a3 = Struct17BytesInt();
+Struct17BytesInt passStruct17BytesIntx10_a4 = Struct17BytesInt();
+Struct17BytesInt passStruct17BytesIntx10_a5 = Struct17BytesInt();
+Struct17BytesInt passStruct17BytesIntx10_a6 = Struct17BytesInt();
+Struct17BytesInt passStruct17BytesIntx10_a7 = Struct17BytesInt();
+Struct17BytesInt passStruct17BytesIntx10_a8 = Struct17BytesInt();
+Struct17BytesInt passStruct17BytesIntx10_a9 = Struct17BytesInt();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct17BytesIntx10Result = 0;
+
+int passStruct17BytesIntx10CalculateResult() {
+ int result = 0;
+
+ result += passStruct17BytesIntx10_a0.a0;
+ result += passStruct17BytesIntx10_a0.a1;
+ result += passStruct17BytesIntx10_a0.a2;
+ result += passStruct17BytesIntx10_a1.a0;
+ result += passStruct17BytesIntx10_a1.a1;
+ result += passStruct17BytesIntx10_a1.a2;
+ result += passStruct17BytesIntx10_a2.a0;
+ result += passStruct17BytesIntx10_a2.a1;
+ result += passStruct17BytesIntx10_a2.a2;
+ result += passStruct17BytesIntx10_a3.a0;
+ result += passStruct17BytesIntx10_a3.a1;
+ result += passStruct17BytesIntx10_a3.a2;
+ result += passStruct17BytesIntx10_a4.a0;
+ result += passStruct17BytesIntx10_a4.a1;
+ result += passStruct17BytesIntx10_a4.a2;
+ result += passStruct17BytesIntx10_a5.a0;
+ result += passStruct17BytesIntx10_a5.a1;
+ result += passStruct17BytesIntx10_a5.a2;
+ result += passStruct17BytesIntx10_a6.a0;
+ result += passStruct17BytesIntx10_a6.a1;
+ result += passStruct17BytesIntx10_a6.a2;
+ result += passStruct17BytesIntx10_a7.a0;
+ result += passStruct17BytesIntx10_a7.a1;
+ result += passStruct17BytesIntx10_a7.a2;
+ result += passStruct17BytesIntx10_a8.a0;
+ result += passStruct17BytesIntx10_a8.a1;
+ result += passStruct17BytesIntx10_a8.a2;
+ result += passStruct17BytesIntx10_a9.a0;
+ result += passStruct17BytesIntx10_a9.a1;
+ result += passStruct17BytesIntx10_a9.a2;
+
+ passStruct17BytesIntx10Result = result;
+
+ return result;
+}
+
+/// Arguments are passed as pointer to copy on arm64.
+/// Tests that the memory allocated for copies are rounded up to word size.
+int passStruct17BytesIntx10(
+ Struct17BytesInt a0,
+ Struct17BytesInt a1,
+ Struct17BytesInt a2,
+ Struct17BytesInt a3,
+ Struct17BytesInt a4,
+ Struct17BytesInt a5,
+ Struct17BytesInt a6,
+ Struct17BytesInt a7,
+ Struct17BytesInt a8,
+ Struct17BytesInt a9) {
+ print(
+ "passStruct17BytesIntx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct17BytesIntx10 throwing on purpuse!");
+ }
+
+ passStruct17BytesIntx10_a0 = a0;
+ passStruct17BytesIntx10_a1 = a1;
+ passStruct17BytesIntx10_a2 = a2;
+ passStruct17BytesIntx10_a3 = a3;
+ passStruct17BytesIntx10_a4 = a4;
+ passStruct17BytesIntx10_a5 = a5;
+ passStruct17BytesIntx10_a6 = a6;
+ passStruct17BytesIntx10_a7 = a7;
+ passStruct17BytesIntx10_a8 = a8;
+ passStruct17BytesIntx10_a9 = a9;
+
+ final result = passStruct17BytesIntx10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct17BytesIntx10AfterCallback() {
+ final result = passStruct17BytesIntx10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(15, result);
+}
+
+typedef PassStruct19BytesHomogeneousUint8x10Type = Int64 Function(
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8);
+
+// Global variables to be able to test inputs after callback returned.
+Struct19BytesHomogeneousUint8 passStruct19BytesHomogeneousUint8x10_a0 =
+ Struct19BytesHomogeneousUint8();
+Struct19BytesHomogeneousUint8 passStruct19BytesHomogeneousUint8x10_a1 =
+ Struct19BytesHomogeneousUint8();
+Struct19BytesHomogeneousUint8 passStruct19BytesHomogeneousUint8x10_a2 =
+ Struct19BytesHomogeneousUint8();
+Struct19BytesHomogeneousUint8 passStruct19BytesHomogeneousUint8x10_a3 =
+ Struct19BytesHomogeneousUint8();
+Struct19BytesHomogeneousUint8 passStruct19BytesHomogeneousUint8x10_a4 =
+ Struct19BytesHomogeneousUint8();
+Struct19BytesHomogeneousUint8 passStruct19BytesHomogeneousUint8x10_a5 =
+ Struct19BytesHomogeneousUint8();
+Struct19BytesHomogeneousUint8 passStruct19BytesHomogeneousUint8x10_a6 =
+ Struct19BytesHomogeneousUint8();
+Struct19BytesHomogeneousUint8 passStruct19BytesHomogeneousUint8x10_a7 =
+ Struct19BytesHomogeneousUint8();
+Struct19BytesHomogeneousUint8 passStruct19BytesHomogeneousUint8x10_a8 =
+ Struct19BytesHomogeneousUint8();
+Struct19BytesHomogeneousUint8 passStruct19BytesHomogeneousUint8x10_a9 =
+ Struct19BytesHomogeneousUint8();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct19BytesHomogeneousUint8x10Result = 0;
+
+int passStruct19BytesHomogeneousUint8x10CalculateResult() {
+ int result = 0;
+
+ result += passStruct19BytesHomogeneousUint8x10_a0.a0;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a1;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a2;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a3;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a4;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a5;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a6;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a7;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a8;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a9;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a10;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a11;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a12;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a13;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a14;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a15;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a16;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a17;
+ result += passStruct19BytesHomogeneousUint8x10_a0.a18;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a0;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a1;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a2;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a3;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a4;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a5;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a6;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a7;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a8;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a9;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a10;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a11;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a12;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a13;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a14;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a15;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a16;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a17;
+ result += passStruct19BytesHomogeneousUint8x10_a1.a18;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a0;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a1;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a2;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a3;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a4;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a5;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a6;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a7;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a8;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a9;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a10;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a11;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a12;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a13;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a14;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a15;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a16;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a17;
+ result += passStruct19BytesHomogeneousUint8x10_a2.a18;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a0;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a1;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a2;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a3;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a4;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a5;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a6;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a7;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a8;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a9;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a10;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a11;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a12;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a13;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a14;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a15;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a16;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a17;
+ result += passStruct19BytesHomogeneousUint8x10_a3.a18;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a0;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a1;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a2;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a3;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a4;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a5;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a6;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a7;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a8;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a9;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a10;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a11;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a12;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a13;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a14;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a15;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a16;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a17;
+ result += passStruct19BytesHomogeneousUint8x10_a4.a18;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a0;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a1;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a2;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a3;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a4;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a5;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a6;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a7;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a8;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a9;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a10;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a11;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a12;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a13;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a14;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a15;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a16;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a17;
+ result += passStruct19BytesHomogeneousUint8x10_a5.a18;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a0;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a1;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a2;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a3;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a4;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a5;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a6;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a7;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a8;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a9;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a10;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a11;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a12;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a13;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a14;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a15;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a16;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a17;
+ result += passStruct19BytesHomogeneousUint8x10_a6.a18;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a0;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a1;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a2;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a3;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a4;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a5;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a6;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a7;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a8;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a9;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a10;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a11;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a12;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a13;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a14;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a15;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a16;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a17;
+ result += passStruct19BytesHomogeneousUint8x10_a7.a18;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a0;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a1;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a2;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a3;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a4;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a5;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a6;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a7;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a8;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a9;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a10;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a11;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a12;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a13;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a14;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a15;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a16;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a17;
+ result += passStruct19BytesHomogeneousUint8x10_a8.a18;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a0;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a1;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a2;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a3;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a4;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a5;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a6;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a7;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a8;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a9;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a10;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a11;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a12;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a13;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a14;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a15;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a16;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a17;
+ result += passStruct19BytesHomogeneousUint8x10_a9.a18;
+
+ passStruct19BytesHomogeneousUint8x10Result = result;
+
+ return result;
+}
+
+/// The minimum alignment of this struct is only 1 byte based on its fields.
+/// Test that the memory backing these structs is extended to the right size.
+///
+int passStruct19BytesHomogeneousUint8x10(
+ Struct19BytesHomogeneousUint8 a0,
+ Struct19BytesHomogeneousUint8 a1,
+ Struct19BytesHomogeneousUint8 a2,
+ Struct19BytesHomogeneousUint8 a3,
+ Struct19BytesHomogeneousUint8 a4,
+ Struct19BytesHomogeneousUint8 a5,
+ Struct19BytesHomogeneousUint8 a6,
+ Struct19BytesHomogeneousUint8 a7,
+ Struct19BytesHomogeneousUint8 a8,
+ Struct19BytesHomogeneousUint8 a9) {
+ print(
+ "passStruct19BytesHomogeneousUint8x10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassStruct19BytesHomogeneousUint8x10 throwing on purpuse!");
+ }
+
+ passStruct19BytesHomogeneousUint8x10_a0 = a0;
+ passStruct19BytesHomogeneousUint8x10_a1 = a1;
+ passStruct19BytesHomogeneousUint8x10_a2 = a2;
+ passStruct19BytesHomogeneousUint8x10_a3 = a3;
+ passStruct19BytesHomogeneousUint8x10_a4 = a4;
+ passStruct19BytesHomogeneousUint8x10_a5 = a5;
+ passStruct19BytesHomogeneousUint8x10_a6 = a6;
+ passStruct19BytesHomogeneousUint8x10_a7 = a7;
+ passStruct19BytesHomogeneousUint8x10_a8 = a8;
+ passStruct19BytesHomogeneousUint8x10_a9 = a9;
+
+ final result = passStruct19BytesHomogeneousUint8x10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct19BytesHomogeneousUint8x10AfterCallback() {
+ final result = passStruct19BytesHomogeneousUint8x10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(18145, result);
+}
+
+typedef PassStruct20BytesHomogeneousInt32x10Type = Int32 Function(
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32);
+
+// Global variables to be able to test inputs after callback returned.
+Struct20BytesHomogeneousInt32 passStruct20BytesHomogeneousInt32x10_a0 =
+ Struct20BytesHomogeneousInt32();
+Struct20BytesHomogeneousInt32 passStruct20BytesHomogeneousInt32x10_a1 =
+ Struct20BytesHomogeneousInt32();
+Struct20BytesHomogeneousInt32 passStruct20BytesHomogeneousInt32x10_a2 =
+ Struct20BytesHomogeneousInt32();
+Struct20BytesHomogeneousInt32 passStruct20BytesHomogeneousInt32x10_a3 =
+ Struct20BytesHomogeneousInt32();
+Struct20BytesHomogeneousInt32 passStruct20BytesHomogeneousInt32x10_a4 =
+ Struct20BytesHomogeneousInt32();
+Struct20BytesHomogeneousInt32 passStruct20BytesHomogeneousInt32x10_a5 =
+ Struct20BytesHomogeneousInt32();
+Struct20BytesHomogeneousInt32 passStruct20BytesHomogeneousInt32x10_a6 =
+ Struct20BytesHomogeneousInt32();
+Struct20BytesHomogeneousInt32 passStruct20BytesHomogeneousInt32x10_a7 =
+ Struct20BytesHomogeneousInt32();
+Struct20BytesHomogeneousInt32 passStruct20BytesHomogeneousInt32x10_a8 =
+ Struct20BytesHomogeneousInt32();
+Struct20BytesHomogeneousInt32 passStruct20BytesHomogeneousInt32x10_a9 =
+ Struct20BytesHomogeneousInt32();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct20BytesHomogeneousInt32x10Result = 0;
+
+int passStruct20BytesHomogeneousInt32x10CalculateResult() {
+ int result = 0;
+
+ result += passStruct20BytesHomogeneousInt32x10_a0.a0;
+ result += passStruct20BytesHomogeneousInt32x10_a0.a1;
+ result += passStruct20BytesHomogeneousInt32x10_a0.a2;
+ result += passStruct20BytesHomogeneousInt32x10_a0.a3;
+ result += passStruct20BytesHomogeneousInt32x10_a0.a4;
+ result += passStruct20BytesHomogeneousInt32x10_a1.a0;
+ result += passStruct20BytesHomogeneousInt32x10_a1.a1;
+ result += passStruct20BytesHomogeneousInt32x10_a1.a2;
+ result += passStruct20BytesHomogeneousInt32x10_a1.a3;
+ result += passStruct20BytesHomogeneousInt32x10_a1.a4;
+ result += passStruct20BytesHomogeneousInt32x10_a2.a0;
+ result += passStruct20BytesHomogeneousInt32x10_a2.a1;
+ result += passStruct20BytesHomogeneousInt32x10_a2.a2;
+ result += passStruct20BytesHomogeneousInt32x10_a2.a3;
+ result += passStruct20BytesHomogeneousInt32x10_a2.a4;
+ result += passStruct20BytesHomogeneousInt32x10_a3.a0;
+ result += passStruct20BytesHomogeneousInt32x10_a3.a1;
+ result += passStruct20BytesHomogeneousInt32x10_a3.a2;
+ result += passStruct20BytesHomogeneousInt32x10_a3.a3;
+ result += passStruct20BytesHomogeneousInt32x10_a3.a4;
+ result += passStruct20BytesHomogeneousInt32x10_a4.a0;
+ result += passStruct20BytesHomogeneousInt32x10_a4.a1;
+ result += passStruct20BytesHomogeneousInt32x10_a4.a2;
+ result += passStruct20BytesHomogeneousInt32x10_a4.a3;
+ result += passStruct20BytesHomogeneousInt32x10_a4.a4;
+ result += passStruct20BytesHomogeneousInt32x10_a5.a0;
+ result += passStruct20BytesHomogeneousInt32x10_a5.a1;
+ result += passStruct20BytesHomogeneousInt32x10_a5.a2;
+ result += passStruct20BytesHomogeneousInt32x10_a5.a3;
+ result += passStruct20BytesHomogeneousInt32x10_a5.a4;
+ result += passStruct20BytesHomogeneousInt32x10_a6.a0;
+ result += passStruct20BytesHomogeneousInt32x10_a6.a1;
+ result += passStruct20BytesHomogeneousInt32x10_a6.a2;
+ result += passStruct20BytesHomogeneousInt32x10_a6.a3;
+ result += passStruct20BytesHomogeneousInt32x10_a6.a4;
+ result += passStruct20BytesHomogeneousInt32x10_a7.a0;
+ result += passStruct20BytesHomogeneousInt32x10_a7.a1;
+ result += passStruct20BytesHomogeneousInt32x10_a7.a2;
+ result += passStruct20BytesHomogeneousInt32x10_a7.a3;
+ result += passStruct20BytesHomogeneousInt32x10_a7.a4;
+ result += passStruct20BytesHomogeneousInt32x10_a8.a0;
+ result += passStruct20BytesHomogeneousInt32x10_a8.a1;
+ result += passStruct20BytesHomogeneousInt32x10_a8.a2;
+ result += passStruct20BytesHomogeneousInt32x10_a8.a3;
+ result += passStruct20BytesHomogeneousInt32x10_a8.a4;
+ result += passStruct20BytesHomogeneousInt32x10_a9.a0;
+ result += passStruct20BytesHomogeneousInt32x10_a9.a1;
+ result += passStruct20BytesHomogeneousInt32x10_a9.a2;
+ result += passStruct20BytesHomogeneousInt32x10_a9.a3;
+ result += passStruct20BytesHomogeneousInt32x10_a9.a4;
+
+ passStruct20BytesHomogeneousInt32x10Result = result;
+
+ return result;
+}
+
+/// Argument too big to go into integer registers on arm64.
+/// The arguments are passed as pointers to copies.
+/// The amount of arguments exhausts the number of integer registers, such that
+/// pointers to copies are also passed on the stack.
+int passStruct20BytesHomogeneousInt32x10(
+ Struct20BytesHomogeneousInt32 a0,
+ Struct20BytesHomogeneousInt32 a1,
+ Struct20BytesHomogeneousInt32 a2,
+ Struct20BytesHomogeneousInt32 a3,
+ Struct20BytesHomogeneousInt32 a4,
+ Struct20BytesHomogeneousInt32 a5,
+ Struct20BytesHomogeneousInt32 a6,
+ Struct20BytesHomogeneousInt32 a7,
+ Struct20BytesHomogeneousInt32 a8,
+ Struct20BytesHomogeneousInt32 a9) {
+ print(
+ "passStruct20BytesHomogeneousInt32x10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassStruct20BytesHomogeneousInt32x10 throwing on purpuse!");
+ }
+
+ passStruct20BytesHomogeneousInt32x10_a0 = a0;
+ passStruct20BytesHomogeneousInt32x10_a1 = a1;
+ passStruct20BytesHomogeneousInt32x10_a2 = a2;
+ passStruct20BytesHomogeneousInt32x10_a3 = a3;
+ passStruct20BytesHomogeneousInt32x10_a4 = a4;
+ passStruct20BytesHomogeneousInt32x10_a5 = a5;
+ passStruct20BytesHomogeneousInt32x10_a6 = a6;
+ passStruct20BytesHomogeneousInt32x10_a7 = a7;
+ passStruct20BytesHomogeneousInt32x10_a8 = a8;
+ passStruct20BytesHomogeneousInt32x10_a9 = a9;
+
+ final result = passStruct20BytesHomogeneousInt32x10CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct20BytesHomogeneousInt32x10AfterCallback() {
+ final result = passStruct20BytesHomogeneousInt32x10CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(25, result);
+}
+
+typedef PassStruct20BytesHomogeneousFloatType = Float Function(
+ Struct20BytesHomogeneousFloat);
+
+// Global variables to be able to test inputs after callback returned.
+Struct20BytesHomogeneousFloat passStruct20BytesHomogeneousFloat_a0 =
+ Struct20BytesHomogeneousFloat();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct20BytesHomogeneousFloatResult = 0.0;
+
+double passStruct20BytesHomogeneousFloatCalculateResult() {
+ double result = 0;
+
+ result += passStruct20BytesHomogeneousFloat_a0.a0;
+ result += passStruct20BytesHomogeneousFloat_a0.a1;
+ result += passStruct20BytesHomogeneousFloat_a0.a2;
+ result += passStruct20BytesHomogeneousFloat_a0.a3;
+ result += passStruct20BytesHomogeneousFloat_a0.a4;
+
+ passStruct20BytesHomogeneousFloatResult = result;
+
+ return result;
+}
+
+/// Argument too big to go into FPU registers in hardfp and arm64.
+double passStruct20BytesHomogeneousFloat(Struct20BytesHomogeneousFloat a0) {
+ print("passStruct20BytesHomogeneousFloat(${a0})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct20BytesHomogeneousFloat throwing on purpuse!");
+ }
+
+ passStruct20BytesHomogeneousFloat_a0 = a0;
+
+ final result = passStruct20BytesHomogeneousFloatCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct20BytesHomogeneousFloatAfterCallback() {
+ final result = passStruct20BytesHomogeneousFloatCalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(-3.0, result);
+}
+
+typedef PassStruct32BytesHomogeneousDoublex5Type = Double Function(
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble);
+
+// Global variables to be able to test inputs after callback returned.
+Struct32BytesHomogeneousDouble passStruct32BytesHomogeneousDoublex5_a0 =
+ Struct32BytesHomogeneousDouble();
+Struct32BytesHomogeneousDouble passStruct32BytesHomogeneousDoublex5_a1 =
+ Struct32BytesHomogeneousDouble();
+Struct32BytesHomogeneousDouble passStruct32BytesHomogeneousDoublex5_a2 =
+ Struct32BytesHomogeneousDouble();
+Struct32BytesHomogeneousDouble passStruct32BytesHomogeneousDoublex5_a3 =
+ Struct32BytesHomogeneousDouble();
+Struct32BytesHomogeneousDouble passStruct32BytesHomogeneousDoublex5_a4 =
+ Struct32BytesHomogeneousDouble();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct32BytesHomogeneousDoublex5Result = 0.0;
+
+double passStruct32BytesHomogeneousDoublex5CalculateResult() {
+ double result = 0;
+
+ result += passStruct32BytesHomogeneousDoublex5_a0.a0;
+ result += passStruct32BytesHomogeneousDoublex5_a0.a1;
+ result += passStruct32BytesHomogeneousDoublex5_a0.a2;
+ result += passStruct32BytesHomogeneousDoublex5_a0.a3;
+ result += passStruct32BytesHomogeneousDoublex5_a1.a0;
+ result += passStruct32BytesHomogeneousDoublex5_a1.a1;
+ result += passStruct32BytesHomogeneousDoublex5_a1.a2;
+ result += passStruct32BytesHomogeneousDoublex5_a1.a3;
+ result += passStruct32BytesHomogeneousDoublex5_a2.a0;
+ result += passStruct32BytesHomogeneousDoublex5_a2.a1;
+ result += passStruct32BytesHomogeneousDoublex5_a2.a2;
+ result += passStruct32BytesHomogeneousDoublex5_a2.a3;
+ result += passStruct32BytesHomogeneousDoublex5_a3.a0;
+ result += passStruct32BytesHomogeneousDoublex5_a3.a1;
+ result += passStruct32BytesHomogeneousDoublex5_a3.a2;
+ result += passStruct32BytesHomogeneousDoublex5_a3.a3;
+ result += passStruct32BytesHomogeneousDoublex5_a4.a0;
+ result += passStruct32BytesHomogeneousDoublex5_a4.a1;
+ result += passStruct32BytesHomogeneousDoublex5_a4.a2;
+ result += passStruct32BytesHomogeneousDoublex5_a4.a3;
+
+ passStruct32BytesHomogeneousDoublex5Result = result;
+
+ return result;
+}
+
+/// Arguments in FPU registers on arm64.
+/// 5 struct arguments will exhaust available registers.
+double passStruct32BytesHomogeneousDoublex5(
+ Struct32BytesHomogeneousDouble a0,
+ Struct32BytesHomogeneousDouble a1,
+ Struct32BytesHomogeneousDouble a2,
+ Struct32BytesHomogeneousDouble a3,
+ Struct32BytesHomogeneousDouble a4) {
+ print(
+ "passStruct32BytesHomogeneousDoublex5(${a0}, ${a1}, ${a2}, ${a3}, ${a4})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassStruct32BytesHomogeneousDoublex5 throwing on purpuse!");
+ }
+
+ passStruct32BytesHomogeneousDoublex5_a0 = a0;
+ passStruct32BytesHomogeneousDoublex5_a1 = a1;
+ passStruct32BytesHomogeneousDoublex5_a2 = a2;
+ passStruct32BytesHomogeneousDoublex5_a3 = a3;
+ passStruct32BytesHomogeneousDoublex5_a4 = a4;
+
+ final result = passStruct32BytesHomogeneousDoublex5CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct32BytesHomogeneousDoublex5AfterCallback() {
+ final result = passStruct32BytesHomogeneousDoublex5CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(10.0, result);
+}
+
+typedef PassStruct40BytesHomogeneousDoubleType = Double Function(
+ Struct40BytesHomogeneousDouble);
+
+// Global variables to be able to test inputs after callback returned.
+Struct40BytesHomogeneousDouble passStruct40BytesHomogeneousDouble_a0 =
+ Struct40BytesHomogeneousDouble();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct40BytesHomogeneousDoubleResult = 0.0;
+
+double passStruct40BytesHomogeneousDoubleCalculateResult() {
+ double result = 0;
+
+ result += passStruct40BytesHomogeneousDouble_a0.a0;
+ result += passStruct40BytesHomogeneousDouble_a0.a1;
+ result += passStruct40BytesHomogeneousDouble_a0.a2;
+ result += passStruct40BytesHomogeneousDouble_a0.a3;
+ result += passStruct40BytesHomogeneousDouble_a0.a4;
+
+ passStruct40BytesHomogeneousDoubleResult = result;
+
+ return result;
+}
+
+/// Argument too big to go into FPU registers in arm64.
+double passStruct40BytesHomogeneousDouble(Struct40BytesHomogeneousDouble a0) {
+ print("passStruct40BytesHomogeneousDouble(${a0})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStruct40BytesHomogeneousDouble throwing on purpuse!");
+ }
+
+ passStruct40BytesHomogeneousDouble_a0 = a0;
+
+ final result = passStruct40BytesHomogeneousDoubleCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct40BytesHomogeneousDoubleAfterCallback() {
+ final result = passStruct40BytesHomogeneousDoubleCalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(-3.0, result);
+}
+
+typedef PassStruct1024BytesHomogeneousUint64Type = Uint64 Function(
+ Struct1024BytesHomogeneousUint64);
+
+// Global variables to be able to test inputs after callback returned.
+Struct1024BytesHomogeneousUint64 passStruct1024BytesHomogeneousUint64_a0 =
+ Struct1024BytesHomogeneousUint64();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct1024BytesHomogeneousUint64Result = 0;
+
+int passStruct1024BytesHomogeneousUint64CalculateResult() {
+ int result = 0;
+
+ result += passStruct1024BytesHomogeneousUint64_a0.a0;
+ result += passStruct1024BytesHomogeneousUint64_a0.a1;
+ result += passStruct1024BytesHomogeneousUint64_a0.a2;
+ result += passStruct1024BytesHomogeneousUint64_a0.a3;
+ result += passStruct1024BytesHomogeneousUint64_a0.a4;
+ result += passStruct1024BytesHomogeneousUint64_a0.a5;
+ result += passStruct1024BytesHomogeneousUint64_a0.a6;
+ result += passStruct1024BytesHomogeneousUint64_a0.a7;
+ result += passStruct1024BytesHomogeneousUint64_a0.a8;
+ result += passStruct1024BytesHomogeneousUint64_a0.a9;
+ result += passStruct1024BytesHomogeneousUint64_a0.a10;
+ result += passStruct1024BytesHomogeneousUint64_a0.a11;
+ result += passStruct1024BytesHomogeneousUint64_a0.a12;
+ result += passStruct1024BytesHomogeneousUint64_a0.a13;
+ result += passStruct1024BytesHomogeneousUint64_a0.a14;
+ result += passStruct1024BytesHomogeneousUint64_a0.a15;
+ result += passStruct1024BytesHomogeneousUint64_a0.a16;
+ result += passStruct1024BytesHomogeneousUint64_a0.a17;
+ result += passStruct1024BytesHomogeneousUint64_a0.a18;
+ result += passStruct1024BytesHomogeneousUint64_a0.a19;
+ result += passStruct1024BytesHomogeneousUint64_a0.a20;
+ result += passStruct1024BytesHomogeneousUint64_a0.a21;
+ result += passStruct1024BytesHomogeneousUint64_a0.a22;
+ result += passStruct1024BytesHomogeneousUint64_a0.a23;
+ result += passStruct1024BytesHomogeneousUint64_a0.a24;
+ result += passStruct1024BytesHomogeneousUint64_a0.a25;
+ result += passStruct1024BytesHomogeneousUint64_a0.a26;
+ result += passStruct1024BytesHomogeneousUint64_a0.a27;
+ result += passStruct1024BytesHomogeneousUint64_a0.a28;
+ result += passStruct1024BytesHomogeneousUint64_a0.a29;
+ result += passStruct1024BytesHomogeneousUint64_a0.a30;
+ result += passStruct1024BytesHomogeneousUint64_a0.a31;
+ result += passStruct1024BytesHomogeneousUint64_a0.a32;
+ result += passStruct1024BytesHomogeneousUint64_a0.a33;
+ result += passStruct1024BytesHomogeneousUint64_a0.a34;
+ result += passStruct1024BytesHomogeneousUint64_a0.a35;
+ result += passStruct1024BytesHomogeneousUint64_a0.a36;
+ result += passStruct1024BytesHomogeneousUint64_a0.a37;
+ result += passStruct1024BytesHomogeneousUint64_a0.a38;
+ result += passStruct1024BytesHomogeneousUint64_a0.a39;
+ result += passStruct1024BytesHomogeneousUint64_a0.a40;
+ result += passStruct1024BytesHomogeneousUint64_a0.a41;
+ result += passStruct1024BytesHomogeneousUint64_a0.a42;
+ result += passStruct1024BytesHomogeneousUint64_a0.a43;
+ result += passStruct1024BytesHomogeneousUint64_a0.a44;
+ result += passStruct1024BytesHomogeneousUint64_a0.a45;
+ result += passStruct1024BytesHomogeneousUint64_a0.a46;
+ result += passStruct1024BytesHomogeneousUint64_a0.a47;
+ result += passStruct1024BytesHomogeneousUint64_a0.a48;
+ result += passStruct1024BytesHomogeneousUint64_a0.a49;
+ result += passStruct1024BytesHomogeneousUint64_a0.a50;
+ result += passStruct1024BytesHomogeneousUint64_a0.a51;
+ result += passStruct1024BytesHomogeneousUint64_a0.a52;
+ result += passStruct1024BytesHomogeneousUint64_a0.a53;
+ result += passStruct1024BytesHomogeneousUint64_a0.a54;
+ result += passStruct1024BytesHomogeneousUint64_a0.a55;
+ result += passStruct1024BytesHomogeneousUint64_a0.a56;
+ result += passStruct1024BytesHomogeneousUint64_a0.a57;
+ result += passStruct1024BytesHomogeneousUint64_a0.a58;
+ result += passStruct1024BytesHomogeneousUint64_a0.a59;
+ result += passStruct1024BytesHomogeneousUint64_a0.a60;
+ result += passStruct1024BytesHomogeneousUint64_a0.a61;
+ result += passStruct1024BytesHomogeneousUint64_a0.a62;
+ result += passStruct1024BytesHomogeneousUint64_a0.a63;
+ result += passStruct1024BytesHomogeneousUint64_a0.a64;
+ result += passStruct1024BytesHomogeneousUint64_a0.a65;
+ result += passStruct1024BytesHomogeneousUint64_a0.a66;
+ result += passStruct1024BytesHomogeneousUint64_a0.a67;
+ result += passStruct1024BytesHomogeneousUint64_a0.a68;
+ result += passStruct1024BytesHomogeneousUint64_a0.a69;
+ result += passStruct1024BytesHomogeneousUint64_a0.a70;
+ result += passStruct1024BytesHomogeneousUint64_a0.a71;
+ result += passStruct1024BytesHomogeneousUint64_a0.a72;
+ result += passStruct1024BytesHomogeneousUint64_a0.a73;
+ result += passStruct1024BytesHomogeneousUint64_a0.a74;
+ result += passStruct1024BytesHomogeneousUint64_a0.a75;
+ result += passStruct1024BytesHomogeneousUint64_a0.a76;
+ result += passStruct1024BytesHomogeneousUint64_a0.a77;
+ result += passStruct1024BytesHomogeneousUint64_a0.a78;
+ result += passStruct1024BytesHomogeneousUint64_a0.a79;
+ result += passStruct1024BytesHomogeneousUint64_a0.a80;
+ result += passStruct1024BytesHomogeneousUint64_a0.a81;
+ result += passStruct1024BytesHomogeneousUint64_a0.a82;
+ result += passStruct1024BytesHomogeneousUint64_a0.a83;
+ result += passStruct1024BytesHomogeneousUint64_a0.a84;
+ result += passStruct1024BytesHomogeneousUint64_a0.a85;
+ result += passStruct1024BytesHomogeneousUint64_a0.a86;
+ result += passStruct1024BytesHomogeneousUint64_a0.a87;
+ result += passStruct1024BytesHomogeneousUint64_a0.a88;
+ result += passStruct1024BytesHomogeneousUint64_a0.a89;
+ result += passStruct1024BytesHomogeneousUint64_a0.a90;
+ result += passStruct1024BytesHomogeneousUint64_a0.a91;
+ result += passStruct1024BytesHomogeneousUint64_a0.a92;
+ result += passStruct1024BytesHomogeneousUint64_a0.a93;
+ result += passStruct1024BytesHomogeneousUint64_a0.a94;
+ result += passStruct1024BytesHomogeneousUint64_a0.a95;
+ result += passStruct1024BytesHomogeneousUint64_a0.a96;
+ result += passStruct1024BytesHomogeneousUint64_a0.a97;
+ result += passStruct1024BytesHomogeneousUint64_a0.a98;
+ result += passStruct1024BytesHomogeneousUint64_a0.a99;
+ result += passStruct1024BytesHomogeneousUint64_a0.a100;
+ result += passStruct1024BytesHomogeneousUint64_a0.a101;
+ result += passStruct1024BytesHomogeneousUint64_a0.a102;
+ result += passStruct1024BytesHomogeneousUint64_a0.a103;
+ result += passStruct1024BytesHomogeneousUint64_a0.a104;
+ result += passStruct1024BytesHomogeneousUint64_a0.a105;
+ result += passStruct1024BytesHomogeneousUint64_a0.a106;
+ result += passStruct1024BytesHomogeneousUint64_a0.a107;
+ result += passStruct1024BytesHomogeneousUint64_a0.a108;
+ result += passStruct1024BytesHomogeneousUint64_a0.a109;
+ result += passStruct1024BytesHomogeneousUint64_a0.a110;
+ result += passStruct1024BytesHomogeneousUint64_a0.a111;
+ result += passStruct1024BytesHomogeneousUint64_a0.a112;
+ result += passStruct1024BytesHomogeneousUint64_a0.a113;
+ result += passStruct1024BytesHomogeneousUint64_a0.a114;
+ result += passStruct1024BytesHomogeneousUint64_a0.a115;
+ result += passStruct1024BytesHomogeneousUint64_a0.a116;
+ result += passStruct1024BytesHomogeneousUint64_a0.a117;
+ result += passStruct1024BytesHomogeneousUint64_a0.a118;
+ result += passStruct1024BytesHomogeneousUint64_a0.a119;
+ result += passStruct1024BytesHomogeneousUint64_a0.a120;
+ result += passStruct1024BytesHomogeneousUint64_a0.a121;
+ result += passStruct1024BytesHomogeneousUint64_a0.a122;
+ result += passStruct1024BytesHomogeneousUint64_a0.a123;
+ result += passStruct1024BytesHomogeneousUint64_a0.a124;
+ result += passStruct1024BytesHomogeneousUint64_a0.a125;
+ result += passStruct1024BytesHomogeneousUint64_a0.a126;
+ result += passStruct1024BytesHomogeneousUint64_a0.a127;
+
+ passStruct1024BytesHomogeneousUint64Result = result;
+
+ return result;
+}
+
+/// Test 1kb struct.
+int passStruct1024BytesHomogeneousUint64(Struct1024BytesHomogeneousUint64 a0) {
+ print("passStruct1024BytesHomogeneousUint64(${a0})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassStruct1024BytesHomogeneousUint64 throwing on purpuse!");
+ }
+
+ passStruct1024BytesHomogeneousUint64_a0 = a0;
+
+ final result = passStruct1024BytesHomogeneousUint64CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct1024BytesHomogeneousUint64AfterCallback() {
+ final result = passStruct1024BytesHomogeneousUint64CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(8256, result);
+}
+
+typedef PassFloatStruct16BytesHomogeneousFloatFloatStruct1Type = Float Function(
+ Float,
+ Struct16BytesHomogeneousFloat,
+ Float,
+ Struct16BytesHomogeneousFloat,
+ Float,
+ Struct16BytesHomogeneousFloat,
+ Float,
+ Struct16BytesHomogeneousFloat,
+ Float);
+
+// Global variables to be able to test inputs after callback returned.
+double passFloatStruct16BytesHomogeneousFloatFloatStruct1_a0 = 0.0;
+Struct16BytesHomogeneousFloat
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a1 =
+ Struct16BytesHomogeneousFloat();
+double passFloatStruct16BytesHomogeneousFloatFloatStruct1_a2 = 0.0;
+Struct16BytesHomogeneousFloat
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a3 =
+ Struct16BytesHomogeneousFloat();
+double passFloatStruct16BytesHomogeneousFloatFloatStruct1_a4 = 0.0;
+Struct16BytesHomogeneousFloat
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a5 =
+ Struct16BytesHomogeneousFloat();
+double passFloatStruct16BytesHomogeneousFloatFloatStruct1_a6 = 0.0;
+Struct16BytesHomogeneousFloat
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a7 =
+ Struct16BytesHomogeneousFloat();
+double passFloatStruct16BytesHomogeneousFloatFloatStruct1_a8 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+double passFloatStruct16BytesHomogeneousFloatFloatStruct1Result = 0.0;
+
+double passFloatStruct16BytesHomogeneousFloatFloatStruct1CalculateResult() {
+ double result = 0;
+
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a0;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a1.a0;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a1.a1;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a1.a2;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a1.a3;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a2;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a3.a0;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a3.a1;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a3.a2;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a3.a3;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a4;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a5.a0;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a5.a1;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a5.a2;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a5.a3;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a6;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a7.a0;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a7.a1;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a7.a2;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a7.a3;
+ result += passFloatStruct16BytesHomogeneousFloatFloatStruct1_a8;
+
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1Result = result;
+
+ return result;
+}
+
+/// Tests the alignment of structs in FPU registers and backfilling.
+double passFloatStruct16BytesHomogeneousFloatFloatStruct1(
+ double a0,
+ Struct16BytesHomogeneousFloat a1,
+ double a2,
+ Struct16BytesHomogeneousFloat a3,
+ double a4,
+ Struct16BytesHomogeneousFloat a5,
+ double a6,
+ Struct16BytesHomogeneousFloat a7,
+ double a8) {
+ print(
+ "passFloatStruct16BytesHomogeneousFloatFloatStruct1(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassFloatStruct16BytesHomogeneousFloatFloatStruct1 throwing on purpuse!");
+ }
+
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a0 = a0;
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a1 = a1;
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a2 = a2;
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a3 = a3;
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a4 = a4;
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a5 = a5;
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a6 = a6;
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a7 = a7;
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1_a8 = a8;
+
+ final result =
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passFloatStruct16BytesHomogeneousFloatFloatStruct1AfterCallback() {
+ final result =
+ passFloatStruct16BytesHomogeneousFloatFloatStruct1CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(-11.0, result);
+}
+
+typedef PassFloatStruct32BytesHomogeneousDoubleFloatStructType
+ = Double Function(
+ Float,
+ Struct32BytesHomogeneousDouble,
+ Float,
+ Struct32BytesHomogeneousDouble,
+ Float,
+ Struct32BytesHomogeneousDouble,
+ Float,
+ Struct32BytesHomogeneousDouble,
+ Float);
+
+// Global variables to be able to test inputs after callback returned.
+double passFloatStruct32BytesHomogeneousDoubleFloatStruct_a0 = 0.0;
+Struct32BytesHomogeneousDouble
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a1 =
+ Struct32BytesHomogeneousDouble();
+double passFloatStruct32BytesHomogeneousDoubleFloatStruct_a2 = 0.0;
+Struct32BytesHomogeneousDouble
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a3 =
+ Struct32BytesHomogeneousDouble();
+double passFloatStruct32BytesHomogeneousDoubleFloatStruct_a4 = 0.0;
+Struct32BytesHomogeneousDouble
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a5 =
+ Struct32BytesHomogeneousDouble();
+double passFloatStruct32BytesHomogeneousDoubleFloatStruct_a6 = 0.0;
+Struct32BytesHomogeneousDouble
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a7 =
+ Struct32BytesHomogeneousDouble();
+double passFloatStruct32BytesHomogeneousDoubleFloatStruct_a8 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+double passFloatStruct32BytesHomogeneousDoubleFloatStructResult = 0.0;
+
+double passFloatStruct32BytesHomogeneousDoubleFloatStructCalculateResult() {
+ double result = 0;
+
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a0;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a1.a0;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a1.a1;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a1.a2;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a1.a3;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a2;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a3.a0;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a3.a1;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a3.a2;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a3.a3;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a4;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a5.a0;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a5.a1;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a5.a2;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a5.a3;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a6;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a7.a0;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a7.a1;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a7.a2;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a7.a3;
+ result += passFloatStruct32BytesHomogeneousDoubleFloatStruct_a8;
+
+ passFloatStruct32BytesHomogeneousDoubleFloatStructResult = result;
+
+ return result;
+}
+
+/// Tests the alignment of structs in FPU registers and backfilling.
+double passFloatStruct32BytesHomogeneousDoubleFloatStruct(
+ double a0,
+ Struct32BytesHomogeneousDouble a1,
+ double a2,
+ Struct32BytesHomogeneousDouble a3,
+ double a4,
+ Struct32BytesHomogeneousDouble a5,
+ double a6,
+ Struct32BytesHomogeneousDouble a7,
+ double a8) {
+ print(
+ "passFloatStruct32BytesHomogeneousDoubleFloatStruct(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassFloatStruct32BytesHomogeneousDoubleFloatStruct throwing on purpuse!");
+ }
+
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a0 = a0;
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a1 = a1;
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a2 = a2;
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a3 = a3;
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a4 = a4;
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a5 = a5;
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a6 = a6;
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a7 = a7;
+ passFloatStruct32BytesHomogeneousDoubleFloatStruct_a8 = a8;
+
+ final result =
+ passFloatStruct32BytesHomogeneousDoubleFloatStructCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passFloatStruct32BytesHomogeneousDoubleFloatStructAfterCallback() {
+ final result =
+ passFloatStruct32BytesHomogeneousDoubleFloatStructCalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(-11.0, result);
+}
+
+typedef PassInt8Struct16BytesMixedInt8Struct16BytesMixedInType
+ = Double Function(Int8, Struct16BytesMixed, Int8, Struct16BytesMixed, Int8,
+ Struct16BytesMixed, Int8, Struct16BytesMixed, Int8);
+
+// Global variables to be able to test inputs after callback returned.
+int passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a0 = 0;
+Struct16BytesMixed passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a1 =
+ Struct16BytesMixed();
+int passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a2 = 0;
+Struct16BytesMixed passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a3 =
+ Struct16BytesMixed();
+int passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a4 = 0;
+Struct16BytesMixed passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a5 =
+ Struct16BytesMixed();
+int passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a6 = 0;
+Struct16BytesMixed passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a7 =
+ Struct16BytesMixed();
+int passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a8 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+double passInt8Struct16BytesMixedInt8Struct16BytesMixedInResult = 0.0;
+
+double passInt8Struct16BytesMixedInt8Struct16BytesMixedInCalculateResult() {
+ double result = 0;
+
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a0;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a1.a0;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a1.a1;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a2;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a3.a0;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a3.a1;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a4;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a5.a0;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a5.a1;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a6;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a7.a0;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a7.a1;
+ result += passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a8;
+
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedInResult = result;
+
+ return result;
+}
+
+/// Tests the alignment of structs in integers registers and on the stack.
+/// Arm32 aligns this struct at 8.
+/// Also, arm32 allocates the second struct partially in registers, partially
+/// on stack.
+/// Test backfilling of integer registers.
+double passInt8Struct16BytesMixedInt8Struct16BytesMixedIn(
+ int a0,
+ Struct16BytesMixed a1,
+ int a2,
+ Struct16BytesMixed a3,
+ int a4,
+ Struct16BytesMixed a5,
+ int a6,
+ Struct16BytesMixed a7,
+ int a8) {
+ print(
+ "passInt8Struct16BytesMixedInt8Struct16BytesMixedIn(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassInt8Struct16BytesMixedInt8Struct16BytesMixedIn throwing on purpuse!");
+ }
+
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a0 = a0;
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a1 = a1;
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a2 = a2;
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a3 = a3;
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a4 = a4;
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a5 = a5;
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a6 = a6;
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a7 = a7;
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedIn_a8 = a8;
+
+ final result =
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedInCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passInt8Struct16BytesMixedInt8Struct16BytesMixedInAfterCallback() {
+ final result =
+ passInt8Struct16BytesMixedInt8Struct16BytesMixedInCalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(-7.0, result);
+}
+
+typedef PassDoublex6Struct16BytesMixedx4Int32Type = Double Function(
+ Double,
+ Double,
+ Double,
+ Double,
+ Double,
+ Double,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Int32);
+
+// Global variables to be able to test inputs after callback returned.
+double passDoublex6Struct16BytesMixedx4Int32_a0 = 0.0;
+double passDoublex6Struct16BytesMixedx4Int32_a1 = 0.0;
+double passDoublex6Struct16BytesMixedx4Int32_a2 = 0.0;
+double passDoublex6Struct16BytesMixedx4Int32_a3 = 0.0;
+double passDoublex6Struct16BytesMixedx4Int32_a4 = 0.0;
+double passDoublex6Struct16BytesMixedx4Int32_a5 = 0.0;
+Struct16BytesMixed passDoublex6Struct16BytesMixedx4Int32_a6 =
+ Struct16BytesMixed();
+Struct16BytesMixed passDoublex6Struct16BytesMixedx4Int32_a7 =
+ Struct16BytesMixed();
+Struct16BytesMixed passDoublex6Struct16BytesMixedx4Int32_a8 =
+ Struct16BytesMixed();
+Struct16BytesMixed passDoublex6Struct16BytesMixedx4Int32_a9 =
+ Struct16BytesMixed();
+int passDoublex6Struct16BytesMixedx4Int32_a10 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+double passDoublex6Struct16BytesMixedx4Int32Result = 0.0;
+
+double passDoublex6Struct16BytesMixedx4Int32CalculateResult() {
+ double result = 0;
+
+ result += passDoublex6Struct16BytesMixedx4Int32_a0;
+ result += passDoublex6Struct16BytesMixedx4Int32_a1;
+ result += passDoublex6Struct16BytesMixedx4Int32_a2;
+ result += passDoublex6Struct16BytesMixedx4Int32_a3;
+ result += passDoublex6Struct16BytesMixedx4Int32_a4;
+ result += passDoublex6Struct16BytesMixedx4Int32_a5;
+ result += passDoublex6Struct16BytesMixedx4Int32_a6.a0;
+ result += passDoublex6Struct16BytesMixedx4Int32_a6.a1;
+ result += passDoublex6Struct16BytesMixedx4Int32_a7.a0;
+ result += passDoublex6Struct16BytesMixedx4Int32_a7.a1;
+ result += passDoublex6Struct16BytesMixedx4Int32_a8.a0;
+ result += passDoublex6Struct16BytesMixedx4Int32_a8.a1;
+ result += passDoublex6Struct16BytesMixedx4Int32_a9.a0;
+ result += passDoublex6Struct16BytesMixedx4Int32_a9.a1;
+ result += passDoublex6Struct16BytesMixedx4Int32_a10;
+
+ passDoublex6Struct16BytesMixedx4Int32Result = result;
+
+ return result;
+}
+
+/// On Linux x64, it will exhaust xmm registers first, after 6 doubles and 2
+/// structs. The rest of the structs will go on the stack.
+/// The int will be backfilled into the int register.
+double passDoublex6Struct16BytesMixedx4Int32(
+ double a0,
+ double a1,
+ double a2,
+ double a3,
+ double a4,
+ double a5,
+ Struct16BytesMixed a6,
+ Struct16BytesMixed a7,
+ Struct16BytesMixed a8,
+ Struct16BytesMixed a9,
+ int a10) {
+ print(
+ "passDoublex6Struct16BytesMixedx4Int32(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9}, ${a10})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassDoublex6Struct16BytesMixedx4Int32 throwing on purpuse!");
+ }
+
+ passDoublex6Struct16BytesMixedx4Int32_a0 = a0;
+ passDoublex6Struct16BytesMixedx4Int32_a1 = a1;
+ passDoublex6Struct16BytesMixedx4Int32_a2 = a2;
+ passDoublex6Struct16BytesMixedx4Int32_a3 = a3;
+ passDoublex6Struct16BytesMixedx4Int32_a4 = a4;
+ passDoublex6Struct16BytesMixedx4Int32_a5 = a5;
+ passDoublex6Struct16BytesMixedx4Int32_a6 = a6;
+ passDoublex6Struct16BytesMixedx4Int32_a7 = a7;
+ passDoublex6Struct16BytesMixedx4Int32_a8 = a8;
+ passDoublex6Struct16BytesMixedx4Int32_a9 = a9;
+ passDoublex6Struct16BytesMixedx4Int32_a10 = a10;
+
+ final result = passDoublex6Struct16BytesMixedx4Int32CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passDoublex6Struct16BytesMixedx4Int32AfterCallback() {
+ final result = passDoublex6Struct16BytesMixedx4Int32CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(-8.0, result);
+}
+
+typedef PassInt32x4Struct16BytesMixedx4DoubleType = Double Function(
+ Int32,
+ Int32,
+ Int32,
+ Int32,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Double);
+
+// Global variables to be able to test inputs after callback returned.
+int passInt32x4Struct16BytesMixedx4Double_a0 = 0;
+int passInt32x4Struct16BytesMixedx4Double_a1 = 0;
+int passInt32x4Struct16BytesMixedx4Double_a2 = 0;
+int passInt32x4Struct16BytesMixedx4Double_a3 = 0;
+Struct16BytesMixed passInt32x4Struct16BytesMixedx4Double_a4 =
+ Struct16BytesMixed();
+Struct16BytesMixed passInt32x4Struct16BytesMixedx4Double_a5 =
+ Struct16BytesMixed();
+Struct16BytesMixed passInt32x4Struct16BytesMixedx4Double_a6 =
+ Struct16BytesMixed();
+Struct16BytesMixed passInt32x4Struct16BytesMixedx4Double_a7 =
+ Struct16BytesMixed();
+double passInt32x4Struct16BytesMixedx4Double_a8 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+double passInt32x4Struct16BytesMixedx4DoubleResult = 0.0;
+
+double passInt32x4Struct16BytesMixedx4DoubleCalculateResult() {
+ double result = 0;
+
+ result += passInt32x4Struct16BytesMixedx4Double_a0;
+ result += passInt32x4Struct16BytesMixedx4Double_a1;
+ result += passInt32x4Struct16BytesMixedx4Double_a2;
+ result += passInt32x4Struct16BytesMixedx4Double_a3;
+ result += passInt32x4Struct16BytesMixedx4Double_a4.a0;
+ result += passInt32x4Struct16BytesMixedx4Double_a4.a1;
+ result += passInt32x4Struct16BytesMixedx4Double_a5.a0;
+ result += passInt32x4Struct16BytesMixedx4Double_a5.a1;
+ result += passInt32x4Struct16BytesMixedx4Double_a6.a0;
+ result += passInt32x4Struct16BytesMixedx4Double_a6.a1;
+ result += passInt32x4Struct16BytesMixedx4Double_a7.a0;
+ result += passInt32x4Struct16BytesMixedx4Double_a7.a1;
+ result += passInt32x4Struct16BytesMixedx4Double_a8;
+
+ passInt32x4Struct16BytesMixedx4DoubleResult = result;
+
+ return result;
+}
+
+/// On Linux x64, it will exhaust int registers first.
+/// The rest of the structs will go on the stack.
+/// The double will be backfilled into the xmm register.
+double passInt32x4Struct16BytesMixedx4Double(
+ int a0,
+ int a1,
+ int a2,
+ int a3,
+ Struct16BytesMixed a4,
+ Struct16BytesMixed a5,
+ Struct16BytesMixed a6,
+ Struct16BytesMixed a7,
+ double a8) {
+ print(
+ "passInt32x4Struct16BytesMixedx4Double(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassInt32x4Struct16BytesMixedx4Double throwing on purpuse!");
+ }
+
+ passInt32x4Struct16BytesMixedx4Double_a0 = a0;
+ passInt32x4Struct16BytesMixedx4Double_a1 = a1;
+ passInt32x4Struct16BytesMixedx4Double_a2 = a2;
+ passInt32x4Struct16BytesMixedx4Double_a3 = a3;
+ passInt32x4Struct16BytesMixedx4Double_a4 = a4;
+ passInt32x4Struct16BytesMixedx4Double_a5 = a5;
+ passInt32x4Struct16BytesMixedx4Double_a6 = a6;
+ passInt32x4Struct16BytesMixedx4Double_a7 = a7;
+ passInt32x4Struct16BytesMixedx4Double_a8 = a8;
+
+ final result = passInt32x4Struct16BytesMixedx4DoubleCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passInt32x4Struct16BytesMixedx4DoubleAfterCallback() {
+ final result = passInt32x4Struct16BytesMixedx4DoubleCalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(-7.0, result);
+}
+
+typedef PassStruct40BytesHomogeneousDoubleStruct4BytesHomoType
+ = Double Function(Struct40BytesHomogeneousDouble,
+ Struct4BytesHomogeneousInt16, Struct8BytesHomogeneousFloat);
+
+// Global variables to be able to test inputs after callback returned.
+Struct40BytesHomogeneousDouble
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a0 =
+ Struct40BytesHomogeneousDouble();
+Struct4BytesHomogeneousInt16
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a1 =
+ Struct4BytesHomogeneousInt16();
+Struct8BytesHomogeneousFloat
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a2 =
+ Struct8BytesHomogeneousFloat();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct40BytesHomogeneousDoubleStruct4BytesHomoResult = 0.0;
+
+double passStruct40BytesHomogeneousDoubleStruct4BytesHomoCalculateResult() {
+ double result = 0;
+
+ result += passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a0.a0;
+ result += passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a0.a1;
+ result += passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a0.a2;
+ result += passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a0.a3;
+ result += passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a0.a4;
+ result += passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a1.a0;
+ result += passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a1.a1;
+ result += passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a2.a0;
+ result += passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a2.a1;
+
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomoResult = result;
+
+ return result;
+}
+
+/// On various architectures, first struct is allocated on stack.
+/// Check that the other two arguments are allocated on registers.
+double passStruct40BytesHomogeneousDoubleStruct4BytesHomo(
+ Struct40BytesHomogeneousDouble a0,
+ Struct4BytesHomogeneousInt16 a1,
+ Struct8BytesHomogeneousFloat a2) {
+ print(
+ "passStruct40BytesHomogeneousDoubleStruct4BytesHomo(${a0}, ${a1}, ${a2})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassStruct40BytesHomogeneousDoubleStruct4BytesHomo throwing on purpuse!");
+ }
+
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a0 = a0;
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a1 = a1;
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomo_a2 = a2;
+
+ final result =
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomoCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStruct40BytesHomogeneousDoubleStruct4BytesHomoAfterCallback() {
+ final result =
+ passStruct40BytesHomogeneousDoubleStruct4BytesHomoCalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.approxEquals(-5.0, result);
+}
+
+typedef PassStructAlignmentInt16Type = Int64 Function(StructAlignmentInt16);
+
+// Global variables to be able to test inputs after callback returned.
+StructAlignmentInt16 passStructAlignmentInt16_a0 = StructAlignmentInt16();
+
+// Result variable also global, so we can delete it after the callback.
+int passStructAlignmentInt16Result = 0;
+
+int passStructAlignmentInt16CalculateResult() {
+ int result = 0;
+
+ result += passStructAlignmentInt16_a0.a0;
+ result += passStructAlignmentInt16_a0.a1;
+ result += passStructAlignmentInt16_a0.a2;
+
+ passStructAlignmentInt16Result = result;
+
+ return result;
+}
+
+/// Test alignment and padding of 16 byte int within struct.
+int passStructAlignmentInt16(StructAlignmentInt16 a0) {
+ print("passStructAlignmentInt16(${a0})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStructAlignmentInt16 throwing on purpuse!");
+ }
+
+ passStructAlignmentInt16_a0 = a0;
+
+ final result = passStructAlignmentInt16CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStructAlignmentInt16AfterCallback() {
+ final result = passStructAlignmentInt16CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(-2, result);
+}
+
+typedef PassStructAlignmentInt32Type = Int64 Function(StructAlignmentInt32);
+
+// Global variables to be able to test inputs after callback returned.
+StructAlignmentInt32 passStructAlignmentInt32_a0 = StructAlignmentInt32();
+
+// Result variable also global, so we can delete it after the callback.
+int passStructAlignmentInt32Result = 0;
+
+int passStructAlignmentInt32CalculateResult() {
+ int result = 0;
+
+ result += passStructAlignmentInt32_a0.a0;
+ result += passStructAlignmentInt32_a0.a1;
+ result += passStructAlignmentInt32_a0.a2;
+
+ passStructAlignmentInt32Result = result;
+
+ return result;
+}
+
+/// Test alignment and padding of 32 byte int within struct.
+int passStructAlignmentInt32(StructAlignmentInt32 a0) {
+ print("passStructAlignmentInt32(${a0})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStructAlignmentInt32 throwing on purpuse!");
+ }
+
+ passStructAlignmentInt32_a0 = a0;
+
+ final result = passStructAlignmentInt32CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStructAlignmentInt32AfterCallback() {
+ final result = passStructAlignmentInt32CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(-2, result);
+}
+
+typedef PassStructAlignmentInt64Type = Int64 Function(StructAlignmentInt64);
+
+// Global variables to be able to test inputs after callback returned.
+StructAlignmentInt64 passStructAlignmentInt64_a0 = StructAlignmentInt64();
+
+// Result variable also global, so we can delete it after the callback.
+int passStructAlignmentInt64Result = 0;
+
+int passStructAlignmentInt64CalculateResult() {
+ int result = 0;
+
+ result += passStructAlignmentInt64_a0.a0;
+ result += passStructAlignmentInt64_a0.a1;
+ result += passStructAlignmentInt64_a0.a2;
+
+ passStructAlignmentInt64Result = result;
+
+ return result;
+}
+
+/// Test alignment and padding of 64 byte int within struct.
+int passStructAlignmentInt64(StructAlignmentInt64 a0) {
+ print("passStructAlignmentInt64(${a0})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("PassStructAlignmentInt64 throwing on purpuse!");
+ }
+
+ passStructAlignmentInt64_a0 = a0;
+
+ final result = passStructAlignmentInt64CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passStructAlignmentInt64AfterCallback() {
+ final result = passStructAlignmentInt64CalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(-2, result);
+}
+
+typedef ReturnStruct1ByteIntType = Struct1ByteInt Function(Int8);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct1ByteInt_a0 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct1ByteInt returnStruct1ByteIntResult = Struct1ByteInt();
+
+Struct1ByteInt returnStruct1ByteIntCalculateResult() {
+ Struct1ByteInt result = allocate<Struct1ByteInt>().ref;
+
+ result.a0 = returnStruct1ByteInt_a0;
+
+ returnStruct1ByteIntResult = result;
+
+ return result;
+}
+
+/// Smallest struct with data.
+Struct1ByteInt returnStruct1ByteInt(int a0) {
+ print("returnStruct1ByteInt(${a0})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct1ByteInt throwing on purpuse!");
+ }
+
+ returnStruct1ByteInt_a0 = a0;
+
+ final result = returnStruct1ByteIntCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct1ByteIntAfterCallback() {
+ free(returnStruct1ByteIntResult.addressOf);
+
+ final result = returnStruct1ByteIntCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct1ByteIntResult.addressOf);
+}
+
+typedef ReturnStruct3BytesIntType = Struct3BytesInt Function(Int16, Int8);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct3BytesInt_a0 = 0;
+int returnStruct3BytesInt_a1 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct3BytesInt returnStruct3BytesIntResult = Struct3BytesInt();
+
+Struct3BytesInt returnStruct3BytesIntCalculateResult() {
+ Struct3BytesInt result = allocate<Struct3BytesInt>().ref;
+
+ result.a0 = returnStruct3BytesInt_a0;
+ result.a1 = returnStruct3BytesInt_a1;
+
+ returnStruct3BytesIntResult = result;
+
+ return result;
+}
+
+/// Smaller than word size return value on all architectures.
+Struct3BytesInt returnStruct3BytesInt(int a0, int a1) {
+ print("returnStruct3BytesInt(${a0}, ${a1})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct3BytesInt throwing on purpuse!");
+ }
+
+ returnStruct3BytesInt_a0 = a0;
+ returnStruct3BytesInt_a1 = a1;
+
+ final result = returnStruct3BytesIntCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct3BytesIntAfterCallback() {
+ free(returnStruct3BytesIntResult.addressOf);
+
+ final result = returnStruct3BytesIntCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct3BytesIntResult.addressOf);
+}
+
+typedef ReturnStruct4BytesHomogeneousInt16Type = Struct4BytesHomogeneousInt16
+ Function(Int16, Int16);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct4BytesHomogeneousInt16_a0 = 0;
+int returnStruct4BytesHomogeneousInt16_a1 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct4BytesHomogeneousInt16 returnStruct4BytesHomogeneousInt16Result =
+ Struct4BytesHomogeneousInt16();
+
+Struct4BytesHomogeneousInt16
+ returnStruct4BytesHomogeneousInt16CalculateResult() {
+ Struct4BytesHomogeneousInt16 result =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+
+ result.a0 = returnStruct4BytesHomogeneousInt16_a0;
+ result.a1 = returnStruct4BytesHomogeneousInt16_a1;
+
+ returnStruct4BytesHomogeneousInt16Result = result;
+
+ return result;
+}
+
+/// Word size return value on 32 bit architectures..
+Struct4BytesHomogeneousInt16 returnStruct4BytesHomogeneousInt16(
+ int a0, int a1) {
+ print("returnStruct4BytesHomogeneousInt16(${a0}, ${a1})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct4BytesHomogeneousInt16 throwing on purpuse!");
+ }
+
+ returnStruct4BytesHomogeneousInt16_a0 = a0;
+ returnStruct4BytesHomogeneousInt16_a1 = a1;
+
+ final result = returnStruct4BytesHomogeneousInt16CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct4BytesHomogeneousInt16AfterCallback() {
+ free(returnStruct4BytesHomogeneousInt16Result.addressOf);
+
+ final result = returnStruct4BytesHomogeneousInt16CalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct4BytesHomogeneousInt16Result.addressOf);
+}
+
+typedef ReturnStruct7BytesIntType = Struct7BytesInt Function(
+ Int32, Int16, Int8);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct7BytesInt_a0 = 0;
+int returnStruct7BytesInt_a1 = 0;
+int returnStruct7BytesInt_a2 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct7BytesInt returnStruct7BytesIntResult = Struct7BytesInt();
+
+Struct7BytesInt returnStruct7BytesIntCalculateResult() {
+ Struct7BytesInt result = allocate<Struct7BytesInt>().ref;
+
+ result.a0 = returnStruct7BytesInt_a0;
+ result.a1 = returnStruct7BytesInt_a1;
+ result.a2 = returnStruct7BytesInt_a2;
+
+ returnStruct7BytesIntResult = result;
+
+ return result;
+}
+
+/// Non-wordsize return value.
+Struct7BytesInt returnStruct7BytesInt(int a0, int a1, int a2) {
+ print("returnStruct7BytesInt(${a0}, ${a1}, ${a2})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct7BytesInt throwing on purpuse!");
+ }
+
+ returnStruct7BytesInt_a0 = a0;
+ returnStruct7BytesInt_a1 = a1;
+ returnStruct7BytesInt_a2 = a2;
+
+ final result = returnStruct7BytesIntCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct7BytesIntAfterCallback() {
+ free(returnStruct7BytesIntResult.addressOf);
+
+ final result = returnStruct7BytesIntCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct7BytesIntResult.addressOf);
+}
+
+typedef ReturnStruct8BytesIntType = Struct8BytesInt Function(
+ Int16, Int16, Int32);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct8BytesInt_a0 = 0;
+int returnStruct8BytesInt_a1 = 0;
+int returnStruct8BytesInt_a2 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct8BytesInt returnStruct8BytesIntResult = Struct8BytesInt();
+
+Struct8BytesInt returnStruct8BytesIntCalculateResult() {
+ Struct8BytesInt result = allocate<Struct8BytesInt>().ref;
+
+ result.a0 = returnStruct8BytesInt_a0;
+ result.a1 = returnStruct8BytesInt_a1;
+ result.a2 = returnStruct8BytesInt_a2;
+
+ returnStruct8BytesIntResult = result;
+
+ return result;
+}
+
+/// Return value in integer registers on many architectures.
+Struct8BytesInt returnStruct8BytesInt(int a0, int a1, int a2) {
+ print("returnStruct8BytesInt(${a0}, ${a1}, ${a2})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct8BytesInt throwing on purpuse!");
+ }
+
+ returnStruct8BytesInt_a0 = a0;
+ returnStruct8BytesInt_a1 = a1;
+ returnStruct8BytesInt_a2 = a2;
+
+ final result = returnStruct8BytesIntCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct8BytesIntAfterCallback() {
+ free(returnStruct8BytesIntResult.addressOf);
+
+ final result = returnStruct8BytesIntCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct8BytesIntResult.addressOf);
+}
+
+typedef ReturnStruct8BytesHomogeneousFloatType = Struct8BytesHomogeneousFloat
+ Function(Float, Float);
+
+// Global variables to be able to test inputs after callback returned.
+double returnStruct8BytesHomogeneousFloat_a0 = 0.0;
+double returnStruct8BytesHomogeneousFloat_a1 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct8BytesHomogeneousFloat returnStruct8BytesHomogeneousFloatResult =
+ Struct8BytesHomogeneousFloat();
+
+Struct8BytesHomogeneousFloat
+ returnStruct8BytesHomogeneousFloatCalculateResult() {
+ Struct8BytesHomogeneousFloat result =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+
+ result.a0 = returnStruct8BytesHomogeneousFloat_a0;
+ result.a1 = returnStruct8BytesHomogeneousFloat_a1;
+
+ returnStruct8BytesHomogeneousFloatResult = result;
+
+ return result;
+}
+
+/// Return value in FP registers on many architectures.
+Struct8BytesHomogeneousFloat returnStruct8BytesHomogeneousFloat(
+ double a0, double a1) {
+ print("returnStruct8BytesHomogeneousFloat(${a0}, ${a1})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct8BytesHomogeneousFloat throwing on purpuse!");
+ }
+
+ returnStruct8BytesHomogeneousFloat_a0 = a0;
+ returnStruct8BytesHomogeneousFloat_a1 = a1;
+
+ final result = returnStruct8BytesHomogeneousFloatCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct8BytesHomogeneousFloatAfterCallback() {
+ free(returnStruct8BytesHomogeneousFloatResult.addressOf);
+
+ final result = returnStruct8BytesHomogeneousFloatCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct8BytesHomogeneousFloatResult.addressOf);
+}
+
+typedef ReturnStruct8BytesMixedType = Struct8BytesMixed Function(
+ Float, Int16, Int16);
+
+// Global variables to be able to test inputs after callback returned.
+double returnStruct8BytesMixed_a0 = 0.0;
+int returnStruct8BytesMixed_a1 = 0;
+int returnStruct8BytesMixed_a2 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct8BytesMixed returnStruct8BytesMixedResult = Struct8BytesMixed();
+
+Struct8BytesMixed returnStruct8BytesMixedCalculateResult() {
+ Struct8BytesMixed result = allocate<Struct8BytesMixed>().ref;
+
+ result.a0 = returnStruct8BytesMixed_a0;
+ result.a1 = returnStruct8BytesMixed_a1;
+ result.a2 = returnStruct8BytesMixed_a2;
+
+ returnStruct8BytesMixedResult = result;
+
+ return result;
+}
+
+/// Return value split over FP and integer register in x64.
+Struct8BytesMixed returnStruct8BytesMixed(double a0, int a1, int a2) {
+ print("returnStruct8BytesMixed(${a0}, ${a1}, ${a2})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct8BytesMixed throwing on purpuse!");
+ }
+
+ returnStruct8BytesMixed_a0 = a0;
+ returnStruct8BytesMixed_a1 = a1;
+ returnStruct8BytesMixed_a2 = a2;
+
+ final result = returnStruct8BytesMixedCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct8BytesMixedAfterCallback() {
+ free(returnStruct8BytesMixedResult.addressOf);
+
+ final result = returnStruct8BytesMixedCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct8BytesMixedResult.addressOf);
+}
+
+typedef ReturnStruct9BytesIntType = Struct9BytesInt Function(Int64, Int8);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct9BytesInt_a0 = 0;
+int returnStruct9BytesInt_a1 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct9BytesInt returnStruct9BytesIntResult = Struct9BytesInt();
+
+Struct9BytesInt returnStruct9BytesIntCalculateResult() {
+ Struct9BytesInt result = allocate<Struct9BytesInt>().ref;
+
+ result.a0 = returnStruct9BytesInt_a0;
+ result.a1 = returnStruct9BytesInt_a1;
+
+ returnStruct9BytesIntResult = result;
+
+ return result;
+}
+
+/// Return value in two integer registers on x64.
+/// The second register only contains a single byte.
+Struct9BytesInt returnStruct9BytesInt(int a0, int a1) {
+ print("returnStruct9BytesInt(${a0}, ${a1})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct9BytesInt throwing on purpuse!");
+ }
+
+ returnStruct9BytesInt_a0 = a0;
+ returnStruct9BytesInt_a1 = a1;
+
+ final result = returnStruct9BytesIntCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct9BytesIntAfterCallback() {
+ free(returnStruct9BytesIntResult.addressOf);
+
+ final result = returnStruct9BytesIntCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct9BytesIntResult.addressOf);
+}
+
+typedef ReturnStruct9BytesHomogeneousUint82Type = Struct9BytesHomogeneousUint82
+ Function(Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct9BytesHomogeneousUint82_a0 = 0;
+int returnStruct9BytesHomogeneousUint82_a1 = 0;
+int returnStruct9BytesHomogeneousUint82_a2 = 0;
+int returnStruct9BytesHomogeneousUint82_a3 = 0;
+int returnStruct9BytesHomogeneousUint82_a4 = 0;
+int returnStruct9BytesHomogeneousUint82_a5 = 0;
+int returnStruct9BytesHomogeneousUint82_a6 = 0;
+int returnStruct9BytesHomogeneousUint82_a7 = 0;
+int returnStruct9BytesHomogeneousUint82_a8 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct9BytesHomogeneousUint82 returnStruct9BytesHomogeneousUint82Result =
+ Struct9BytesHomogeneousUint82();
+
+Struct9BytesHomogeneousUint82
+ returnStruct9BytesHomogeneousUint82CalculateResult() {
+ Struct9BytesHomogeneousUint82 result =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+
+ result.a0 = returnStruct9BytesHomogeneousUint82_a0;
+ result.a1 = returnStruct9BytesHomogeneousUint82_a1;
+ result.a2 = returnStruct9BytesHomogeneousUint82_a2;
+ result.a3 = returnStruct9BytesHomogeneousUint82_a3;
+ result.a4 = returnStruct9BytesHomogeneousUint82_a4;
+ result.a5 = returnStruct9BytesHomogeneousUint82_a5;
+ result.a6 = returnStruct9BytesHomogeneousUint82_a6;
+ result.a7 = returnStruct9BytesHomogeneousUint82_a7;
+ result.a8 = returnStruct9BytesHomogeneousUint82_a8;
+
+ returnStruct9BytesHomogeneousUint82Result = result;
+
+ return result;
+}
+
+/// The minimum alignment of this struct is only 1 byte based on its fields.
+/// Test that the memory backing these structs is the right size and that
+/// dart:ffi trampolines do not write outside this size.
+Struct9BytesHomogeneousUint82 returnStruct9BytesHomogeneousUint82(
+ int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) {
+ print(
+ "returnStruct9BytesHomogeneousUint82(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct9BytesHomogeneousUint82 throwing on purpuse!");
+ }
+
+ returnStruct9BytesHomogeneousUint82_a0 = a0;
+ returnStruct9BytesHomogeneousUint82_a1 = a1;
+ returnStruct9BytesHomogeneousUint82_a2 = a2;
+ returnStruct9BytesHomogeneousUint82_a3 = a3;
+ returnStruct9BytesHomogeneousUint82_a4 = a4;
+ returnStruct9BytesHomogeneousUint82_a5 = a5;
+ returnStruct9BytesHomogeneousUint82_a6 = a6;
+ returnStruct9BytesHomogeneousUint82_a7 = a7;
+ returnStruct9BytesHomogeneousUint82_a8 = a8;
+
+ final result = returnStruct9BytesHomogeneousUint82CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct9BytesHomogeneousUint82AfterCallback() {
+ free(returnStruct9BytesHomogeneousUint82Result.addressOf);
+
+ final result = returnStruct9BytesHomogeneousUint82CalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct9BytesHomogeneousUint82Result.addressOf);
+}
+
+typedef ReturnStruct12BytesHomogeneousFloatType = Struct12BytesHomogeneousFloat
+ Function(Float, Float, Float);
+
+// Global variables to be able to test inputs after callback returned.
+double returnStruct12BytesHomogeneousFloat_a0 = 0.0;
+double returnStruct12BytesHomogeneousFloat_a1 = 0.0;
+double returnStruct12BytesHomogeneousFloat_a2 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct12BytesHomogeneousFloat returnStruct12BytesHomogeneousFloatResult =
+ Struct12BytesHomogeneousFloat();
+
+Struct12BytesHomogeneousFloat
+ returnStruct12BytesHomogeneousFloatCalculateResult() {
+ Struct12BytesHomogeneousFloat result =
+ allocate<Struct12BytesHomogeneousFloat>().ref;
+
+ result.a0 = returnStruct12BytesHomogeneousFloat_a0;
+ result.a1 = returnStruct12BytesHomogeneousFloat_a1;
+ result.a2 = returnStruct12BytesHomogeneousFloat_a2;
+
+ returnStruct12BytesHomogeneousFloatResult = result;
+
+ return result;
+}
+
+/// Return value in FPU registers, but does not use all registers on arm hardfp
+/// and arm64.
+Struct12BytesHomogeneousFloat returnStruct12BytesHomogeneousFloat(
+ double a0, double a1, double a2) {
+ print("returnStruct12BytesHomogeneousFloat(${a0}, ${a1}, ${a2})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct12BytesHomogeneousFloat throwing on purpuse!");
+ }
+
+ returnStruct12BytesHomogeneousFloat_a0 = a0;
+ returnStruct12BytesHomogeneousFloat_a1 = a1;
+ returnStruct12BytesHomogeneousFloat_a2 = a2;
+
+ final result = returnStruct12BytesHomogeneousFloatCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct12BytesHomogeneousFloatAfterCallback() {
+ free(returnStruct12BytesHomogeneousFloatResult.addressOf);
+
+ final result = returnStruct12BytesHomogeneousFloatCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct12BytesHomogeneousFloatResult.addressOf);
+}
+
+typedef ReturnStruct16BytesHomogeneousFloatType = Struct16BytesHomogeneousFloat
+ Function(Float, Float, Float, Float);
+
+// Global variables to be able to test inputs after callback returned.
+double returnStruct16BytesHomogeneousFloat_a0 = 0.0;
+double returnStruct16BytesHomogeneousFloat_a1 = 0.0;
+double returnStruct16BytesHomogeneousFloat_a2 = 0.0;
+double returnStruct16BytesHomogeneousFloat_a3 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct16BytesHomogeneousFloat returnStruct16BytesHomogeneousFloatResult =
+ Struct16BytesHomogeneousFloat();
+
+Struct16BytesHomogeneousFloat
+ returnStruct16BytesHomogeneousFloatCalculateResult() {
+ Struct16BytesHomogeneousFloat result =
+ allocate<Struct16BytesHomogeneousFloat>().ref;
+
+ result.a0 = returnStruct16BytesHomogeneousFloat_a0;
+ result.a1 = returnStruct16BytesHomogeneousFloat_a1;
+ result.a2 = returnStruct16BytesHomogeneousFloat_a2;
+ result.a3 = returnStruct16BytesHomogeneousFloat_a3;
+
+ returnStruct16BytesHomogeneousFloatResult = result;
+
+ return result;
+}
+
+/// Return value in FPU registers on arm hardfp and arm64.
+Struct16BytesHomogeneousFloat returnStruct16BytesHomogeneousFloat(
+ double a0, double a1, double a2, double a3) {
+ print("returnStruct16BytesHomogeneousFloat(${a0}, ${a1}, ${a2}, ${a3})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct16BytesHomogeneousFloat throwing on purpuse!");
+ }
+
+ returnStruct16BytesHomogeneousFloat_a0 = a0;
+ returnStruct16BytesHomogeneousFloat_a1 = a1;
+ returnStruct16BytesHomogeneousFloat_a2 = a2;
+ returnStruct16BytesHomogeneousFloat_a3 = a3;
+
+ final result = returnStruct16BytesHomogeneousFloatCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct16BytesHomogeneousFloatAfterCallback() {
+ free(returnStruct16BytesHomogeneousFloatResult.addressOf);
+
+ final result = returnStruct16BytesHomogeneousFloatCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct16BytesHomogeneousFloatResult.addressOf);
+}
+
+typedef ReturnStruct16BytesMixedType = Struct16BytesMixed Function(
+ Double, Int64);
+
+// Global variables to be able to test inputs after callback returned.
+double returnStruct16BytesMixed_a0 = 0.0;
+int returnStruct16BytesMixed_a1 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct16BytesMixed returnStruct16BytesMixedResult = Struct16BytesMixed();
+
+Struct16BytesMixed returnStruct16BytesMixedCalculateResult() {
+ Struct16BytesMixed result = allocate<Struct16BytesMixed>().ref;
+
+ result.a0 = returnStruct16BytesMixed_a0;
+ result.a1 = returnStruct16BytesMixed_a1;
+
+ returnStruct16BytesMixedResult = result;
+
+ return result;
+}
+
+/// Return value split over FP and integer register in x64.
+Struct16BytesMixed returnStruct16BytesMixed(double a0, int a1) {
+ print("returnStruct16BytesMixed(${a0}, ${a1})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct16BytesMixed throwing on purpuse!");
+ }
+
+ returnStruct16BytesMixed_a0 = a0;
+ returnStruct16BytesMixed_a1 = a1;
+
+ final result = returnStruct16BytesMixedCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct16BytesMixedAfterCallback() {
+ free(returnStruct16BytesMixedResult.addressOf);
+
+ final result = returnStruct16BytesMixedCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct16BytesMixedResult.addressOf);
+}
+
+typedef ReturnStruct16BytesMixed2Type = Struct16BytesMixed2 Function(
+ Float, Float, Float, Int32);
+
+// Global variables to be able to test inputs after callback returned.
+double returnStruct16BytesMixed2_a0 = 0.0;
+double returnStruct16BytesMixed2_a1 = 0.0;
+double returnStruct16BytesMixed2_a2 = 0.0;
+int returnStruct16BytesMixed2_a3 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct16BytesMixed2 returnStruct16BytesMixed2Result = Struct16BytesMixed2();
+
+Struct16BytesMixed2 returnStruct16BytesMixed2CalculateResult() {
+ Struct16BytesMixed2 result = allocate<Struct16BytesMixed2>().ref;
+
+ result.a0 = returnStruct16BytesMixed2_a0;
+ result.a1 = returnStruct16BytesMixed2_a1;
+ result.a2 = returnStruct16BytesMixed2_a2;
+ result.a3 = returnStruct16BytesMixed2_a3;
+
+ returnStruct16BytesMixed2Result = result;
+
+ return result;
+}
+
+/// Return value split over FP and integer register in x64.
+/// The integer register contains half float half int.
+Struct16BytesMixed2 returnStruct16BytesMixed2(
+ double a0, double a1, double a2, int a3) {
+ print("returnStruct16BytesMixed2(${a0}, ${a1}, ${a2}, ${a3})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct16BytesMixed2 throwing on purpuse!");
+ }
+
+ returnStruct16BytesMixed2_a0 = a0;
+ returnStruct16BytesMixed2_a1 = a1;
+ returnStruct16BytesMixed2_a2 = a2;
+ returnStruct16BytesMixed2_a3 = a3;
+
+ final result = returnStruct16BytesMixed2CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct16BytesMixed2AfterCallback() {
+ free(returnStruct16BytesMixed2Result.addressOf);
+
+ final result = returnStruct16BytesMixed2CalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct16BytesMixed2Result.addressOf);
+}
+
+typedef ReturnStruct17BytesIntType = Struct17BytesInt Function(
+ Int64, Int64, Int8);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct17BytesInt_a0 = 0;
+int returnStruct17BytesInt_a1 = 0;
+int returnStruct17BytesInt_a2 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct17BytesInt returnStruct17BytesIntResult = Struct17BytesInt();
+
+Struct17BytesInt returnStruct17BytesIntCalculateResult() {
+ Struct17BytesInt result = allocate<Struct17BytesInt>().ref;
+
+ result.a0 = returnStruct17BytesInt_a0;
+ result.a1 = returnStruct17BytesInt_a1;
+ result.a2 = returnStruct17BytesInt_a2;
+
+ returnStruct17BytesIntResult = result;
+
+ return result;
+}
+
+/// Rerturn value returned in preallocated space passed by pointer on most ABIs.
+/// Is non word size on purpose, to test that structs are rounded up to word size
+/// on all ABIs.
+Struct17BytesInt returnStruct17BytesInt(int a0, int a1, int a2) {
+ print("returnStruct17BytesInt(${a0}, ${a1}, ${a2})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct17BytesInt throwing on purpuse!");
+ }
+
+ returnStruct17BytesInt_a0 = a0;
+ returnStruct17BytesInt_a1 = a1;
+ returnStruct17BytesInt_a2 = a2;
+
+ final result = returnStruct17BytesIntCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct17BytesIntAfterCallback() {
+ free(returnStruct17BytesIntResult.addressOf);
+
+ final result = returnStruct17BytesIntCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct17BytesIntResult.addressOf);
+}
+
+typedef ReturnStruct19BytesHomogeneousUint8Type
+ = Struct19BytesHomogeneousUint8 Function(
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct19BytesHomogeneousUint8_a0 = 0;
+int returnStruct19BytesHomogeneousUint8_a1 = 0;
+int returnStruct19BytesHomogeneousUint8_a2 = 0;
+int returnStruct19BytesHomogeneousUint8_a3 = 0;
+int returnStruct19BytesHomogeneousUint8_a4 = 0;
+int returnStruct19BytesHomogeneousUint8_a5 = 0;
+int returnStruct19BytesHomogeneousUint8_a6 = 0;
+int returnStruct19BytesHomogeneousUint8_a7 = 0;
+int returnStruct19BytesHomogeneousUint8_a8 = 0;
+int returnStruct19BytesHomogeneousUint8_a9 = 0;
+int returnStruct19BytesHomogeneousUint8_a10 = 0;
+int returnStruct19BytesHomogeneousUint8_a11 = 0;
+int returnStruct19BytesHomogeneousUint8_a12 = 0;
+int returnStruct19BytesHomogeneousUint8_a13 = 0;
+int returnStruct19BytesHomogeneousUint8_a14 = 0;
+int returnStruct19BytesHomogeneousUint8_a15 = 0;
+int returnStruct19BytesHomogeneousUint8_a16 = 0;
+int returnStruct19BytesHomogeneousUint8_a17 = 0;
+int returnStruct19BytesHomogeneousUint8_a18 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct19BytesHomogeneousUint8 returnStruct19BytesHomogeneousUint8Result =
+ Struct19BytesHomogeneousUint8();
+
+Struct19BytesHomogeneousUint8
+ returnStruct19BytesHomogeneousUint8CalculateResult() {
+ Struct19BytesHomogeneousUint8 result =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+
+ result.a0 = returnStruct19BytesHomogeneousUint8_a0;
+ result.a1 = returnStruct19BytesHomogeneousUint8_a1;
+ result.a2 = returnStruct19BytesHomogeneousUint8_a2;
+ result.a3 = returnStruct19BytesHomogeneousUint8_a3;
+ result.a4 = returnStruct19BytesHomogeneousUint8_a4;
+ result.a5 = returnStruct19BytesHomogeneousUint8_a5;
+ result.a6 = returnStruct19BytesHomogeneousUint8_a6;
+ result.a7 = returnStruct19BytesHomogeneousUint8_a7;
+ result.a8 = returnStruct19BytesHomogeneousUint8_a8;
+ result.a9 = returnStruct19BytesHomogeneousUint8_a9;
+ result.a10 = returnStruct19BytesHomogeneousUint8_a10;
+ result.a11 = returnStruct19BytesHomogeneousUint8_a11;
+ result.a12 = returnStruct19BytesHomogeneousUint8_a12;
+ result.a13 = returnStruct19BytesHomogeneousUint8_a13;
+ result.a14 = returnStruct19BytesHomogeneousUint8_a14;
+ result.a15 = returnStruct19BytesHomogeneousUint8_a15;
+ result.a16 = returnStruct19BytesHomogeneousUint8_a16;
+ result.a17 = returnStruct19BytesHomogeneousUint8_a17;
+ result.a18 = returnStruct19BytesHomogeneousUint8_a18;
+
+ returnStruct19BytesHomogeneousUint8Result = result;
+
+ return result;
+}
+
+/// The minimum alignment of this struct is only 1 byte based on its fields.
+/// Test that the memory backing these structs is the right size and that
+/// dart:ffi trampolines do not write outside this size.
+Struct19BytesHomogeneousUint8 returnStruct19BytesHomogeneousUint8(
+ int a0,
+ int a1,
+ int a2,
+ int a3,
+ int a4,
+ int a5,
+ int a6,
+ int a7,
+ int a8,
+ int a9,
+ int a10,
+ int a11,
+ int a12,
+ int a13,
+ int a14,
+ int a15,
+ int a16,
+ int a17,
+ int a18) {
+ print(
+ "returnStruct19BytesHomogeneousUint8(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9}, ${a10}, ${a11}, ${a12}, ${a13}, ${a14}, ${a15}, ${a16}, ${a17}, ${a18})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct19BytesHomogeneousUint8 throwing on purpuse!");
+ }
+
+ returnStruct19BytesHomogeneousUint8_a0 = a0;
+ returnStruct19BytesHomogeneousUint8_a1 = a1;
+ returnStruct19BytesHomogeneousUint8_a2 = a2;
+ returnStruct19BytesHomogeneousUint8_a3 = a3;
+ returnStruct19BytesHomogeneousUint8_a4 = a4;
+ returnStruct19BytesHomogeneousUint8_a5 = a5;
+ returnStruct19BytesHomogeneousUint8_a6 = a6;
+ returnStruct19BytesHomogeneousUint8_a7 = a7;
+ returnStruct19BytesHomogeneousUint8_a8 = a8;
+ returnStruct19BytesHomogeneousUint8_a9 = a9;
+ returnStruct19BytesHomogeneousUint8_a10 = a10;
+ returnStruct19BytesHomogeneousUint8_a11 = a11;
+ returnStruct19BytesHomogeneousUint8_a12 = a12;
+ returnStruct19BytesHomogeneousUint8_a13 = a13;
+ returnStruct19BytesHomogeneousUint8_a14 = a14;
+ returnStruct19BytesHomogeneousUint8_a15 = a15;
+ returnStruct19BytesHomogeneousUint8_a16 = a16;
+ returnStruct19BytesHomogeneousUint8_a17 = a17;
+ returnStruct19BytesHomogeneousUint8_a18 = a18;
+
+ final result = returnStruct19BytesHomogeneousUint8CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct19BytesHomogeneousUint8AfterCallback() {
+ free(returnStruct19BytesHomogeneousUint8Result.addressOf);
+
+ final result = returnStruct19BytesHomogeneousUint8CalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct19BytesHomogeneousUint8Result.addressOf);
+}
+
+typedef ReturnStruct20BytesHomogeneousInt32Type = Struct20BytesHomogeneousInt32
+ Function(Int32, Int32, Int32, Int32, Int32);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct20BytesHomogeneousInt32_a0 = 0;
+int returnStruct20BytesHomogeneousInt32_a1 = 0;
+int returnStruct20BytesHomogeneousInt32_a2 = 0;
+int returnStruct20BytesHomogeneousInt32_a3 = 0;
+int returnStruct20BytesHomogeneousInt32_a4 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct20BytesHomogeneousInt32 returnStruct20BytesHomogeneousInt32Result =
+ Struct20BytesHomogeneousInt32();
+
+Struct20BytesHomogeneousInt32
+ returnStruct20BytesHomogeneousInt32CalculateResult() {
+ Struct20BytesHomogeneousInt32 result =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+
+ result.a0 = returnStruct20BytesHomogeneousInt32_a0;
+ result.a1 = returnStruct20BytesHomogeneousInt32_a1;
+ result.a2 = returnStruct20BytesHomogeneousInt32_a2;
+ result.a3 = returnStruct20BytesHomogeneousInt32_a3;
+ result.a4 = returnStruct20BytesHomogeneousInt32_a4;
+
+ returnStruct20BytesHomogeneousInt32Result = result;
+
+ return result;
+}
+
+/// Return value too big to go in cpu registers on arm64.
+Struct20BytesHomogeneousInt32 returnStruct20BytesHomogeneousInt32(
+ int a0, int a1, int a2, int a3, int a4) {
+ print(
+ "returnStruct20BytesHomogeneousInt32(${a0}, ${a1}, ${a2}, ${a3}, ${a4})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct20BytesHomogeneousInt32 throwing on purpuse!");
+ }
+
+ returnStruct20BytesHomogeneousInt32_a0 = a0;
+ returnStruct20BytesHomogeneousInt32_a1 = a1;
+ returnStruct20BytesHomogeneousInt32_a2 = a2;
+ returnStruct20BytesHomogeneousInt32_a3 = a3;
+ returnStruct20BytesHomogeneousInt32_a4 = a4;
+
+ final result = returnStruct20BytesHomogeneousInt32CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct20BytesHomogeneousInt32AfterCallback() {
+ free(returnStruct20BytesHomogeneousInt32Result.addressOf);
+
+ final result = returnStruct20BytesHomogeneousInt32CalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct20BytesHomogeneousInt32Result.addressOf);
+}
+
+typedef ReturnStruct20BytesHomogeneousFloatType = Struct20BytesHomogeneousFloat
+ Function(Float, Float, Float, Float, Float);
+
+// Global variables to be able to test inputs after callback returned.
+double returnStruct20BytesHomogeneousFloat_a0 = 0.0;
+double returnStruct20BytesHomogeneousFloat_a1 = 0.0;
+double returnStruct20BytesHomogeneousFloat_a2 = 0.0;
+double returnStruct20BytesHomogeneousFloat_a3 = 0.0;
+double returnStruct20BytesHomogeneousFloat_a4 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct20BytesHomogeneousFloat returnStruct20BytesHomogeneousFloatResult =
+ Struct20BytesHomogeneousFloat();
+
+Struct20BytesHomogeneousFloat
+ returnStruct20BytesHomogeneousFloatCalculateResult() {
+ Struct20BytesHomogeneousFloat result =
+ allocate<Struct20BytesHomogeneousFloat>().ref;
+
+ result.a0 = returnStruct20BytesHomogeneousFloat_a0;
+ result.a1 = returnStruct20BytesHomogeneousFloat_a1;
+ result.a2 = returnStruct20BytesHomogeneousFloat_a2;
+ result.a3 = returnStruct20BytesHomogeneousFloat_a3;
+ result.a4 = returnStruct20BytesHomogeneousFloat_a4;
+
+ returnStruct20BytesHomogeneousFloatResult = result;
+
+ return result;
+}
+
+/// Return value too big to go in FPU registers on x64, arm hardfp and arm64.
+Struct20BytesHomogeneousFloat returnStruct20BytesHomogeneousFloat(
+ double a0, double a1, double a2, double a3, double a4) {
+ print(
+ "returnStruct20BytesHomogeneousFloat(${a0}, ${a1}, ${a2}, ${a3}, ${a4})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStruct20BytesHomogeneousFloat throwing on purpuse!");
+ }
+
+ returnStruct20BytesHomogeneousFloat_a0 = a0;
+ returnStruct20BytesHomogeneousFloat_a1 = a1;
+ returnStruct20BytesHomogeneousFloat_a2 = a2;
+ returnStruct20BytesHomogeneousFloat_a3 = a3;
+ returnStruct20BytesHomogeneousFloat_a4 = a4;
+
+ final result = returnStruct20BytesHomogeneousFloatCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct20BytesHomogeneousFloatAfterCallback() {
+ free(returnStruct20BytesHomogeneousFloatResult.addressOf);
+
+ final result = returnStruct20BytesHomogeneousFloatCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct20BytesHomogeneousFloatResult.addressOf);
+}
+
+typedef ReturnStruct32BytesHomogeneousDoubleType
+ = Struct32BytesHomogeneousDouble Function(Double, Double, Double, Double);
+
+// Global variables to be able to test inputs after callback returned.
+double returnStruct32BytesHomogeneousDouble_a0 = 0.0;
+double returnStruct32BytesHomogeneousDouble_a1 = 0.0;
+double returnStruct32BytesHomogeneousDouble_a2 = 0.0;
+double returnStruct32BytesHomogeneousDouble_a3 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct32BytesHomogeneousDouble returnStruct32BytesHomogeneousDoubleResult =
+ Struct32BytesHomogeneousDouble();
+
+Struct32BytesHomogeneousDouble
+ returnStruct32BytesHomogeneousDoubleCalculateResult() {
+ Struct32BytesHomogeneousDouble result =
+ allocate<Struct32BytesHomogeneousDouble>().ref;
+
+ result.a0 = returnStruct32BytesHomogeneousDouble_a0;
+ result.a1 = returnStruct32BytesHomogeneousDouble_a1;
+ result.a2 = returnStruct32BytesHomogeneousDouble_a2;
+ result.a3 = returnStruct32BytesHomogeneousDouble_a3;
+
+ returnStruct32BytesHomogeneousDoubleResult = result;
+
+ return result;
+}
+
+/// Return value in FPU registers on arm64.
+Struct32BytesHomogeneousDouble returnStruct32BytesHomogeneousDouble(
+ double a0, double a1, double a2, double a3) {
+ print("returnStruct32BytesHomogeneousDouble(${a0}, ${a1}, ${a2}, ${a3})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "ReturnStruct32BytesHomogeneousDouble throwing on purpuse!");
+ }
+
+ returnStruct32BytesHomogeneousDouble_a0 = a0;
+ returnStruct32BytesHomogeneousDouble_a1 = a1;
+ returnStruct32BytesHomogeneousDouble_a2 = a2;
+ returnStruct32BytesHomogeneousDouble_a3 = a3;
+
+ final result = returnStruct32BytesHomogeneousDoubleCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct32BytesHomogeneousDoubleAfterCallback() {
+ free(returnStruct32BytesHomogeneousDoubleResult.addressOf);
+
+ final result = returnStruct32BytesHomogeneousDoubleCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct32BytesHomogeneousDoubleResult.addressOf);
+}
+
+typedef ReturnStruct40BytesHomogeneousDoubleType
+ = Struct40BytesHomogeneousDouble Function(
+ Double, Double, Double, Double, Double);
+
+// Global variables to be able to test inputs after callback returned.
+double returnStruct40BytesHomogeneousDouble_a0 = 0.0;
+double returnStruct40BytesHomogeneousDouble_a1 = 0.0;
+double returnStruct40BytesHomogeneousDouble_a2 = 0.0;
+double returnStruct40BytesHomogeneousDouble_a3 = 0.0;
+double returnStruct40BytesHomogeneousDouble_a4 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct40BytesHomogeneousDouble returnStruct40BytesHomogeneousDoubleResult =
+ Struct40BytesHomogeneousDouble();
+
+Struct40BytesHomogeneousDouble
+ returnStruct40BytesHomogeneousDoubleCalculateResult() {
+ Struct40BytesHomogeneousDouble result =
+ allocate<Struct40BytesHomogeneousDouble>().ref;
+
+ result.a0 = returnStruct40BytesHomogeneousDouble_a0;
+ result.a1 = returnStruct40BytesHomogeneousDouble_a1;
+ result.a2 = returnStruct40BytesHomogeneousDouble_a2;
+ result.a3 = returnStruct40BytesHomogeneousDouble_a3;
+ result.a4 = returnStruct40BytesHomogeneousDouble_a4;
+
+ returnStruct40BytesHomogeneousDoubleResult = result;
+
+ return result;
+}
+
+/// Return value too big to go in FPU registers on arm64.
+Struct40BytesHomogeneousDouble returnStruct40BytesHomogeneousDouble(
+ double a0, double a1, double a2, double a3, double a4) {
+ print(
+ "returnStruct40BytesHomogeneousDouble(${a0}, ${a1}, ${a2}, ${a3}, ${a4})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "ReturnStruct40BytesHomogeneousDouble throwing on purpuse!");
+ }
+
+ returnStruct40BytesHomogeneousDouble_a0 = a0;
+ returnStruct40BytesHomogeneousDouble_a1 = a1;
+ returnStruct40BytesHomogeneousDouble_a2 = a2;
+ returnStruct40BytesHomogeneousDouble_a3 = a3;
+ returnStruct40BytesHomogeneousDouble_a4 = a4;
+
+ final result = returnStruct40BytesHomogeneousDoubleCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct40BytesHomogeneousDoubleAfterCallback() {
+ free(returnStruct40BytesHomogeneousDoubleResult.addressOf);
+
+ final result = returnStruct40BytesHomogeneousDoubleCalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct40BytesHomogeneousDoubleResult.addressOf);
+}
+
+typedef ReturnStruct1024BytesHomogeneousUint64Type
+ = Struct1024BytesHomogeneousUint64 Function(
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStruct1024BytesHomogeneousUint64_a0 = 0;
+int returnStruct1024BytesHomogeneousUint64_a1 = 0;
+int returnStruct1024BytesHomogeneousUint64_a2 = 0;
+int returnStruct1024BytesHomogeneousUint64_a3 = 0;
+int returnStruct1024BytesHomogeneousUint64_a4 = 0;
+int returnStruct1024BytesHomogeneousUint64_a5 = 0;
+int returnStruct1024BytesHomogeneousUint64_a6 = 0;
+int returnStruct1024BytesHomogeneousUint64_a7 = 0;
+int returnStruct1024BytesHomogeneousUint64_a8 = 0;
+int returnStruct1024BytesHomogeneousUint64_a9 = 0;
+int returnStruct1024BytesHomogeneousUint64_a10 = 0;
+int returnStruct1024BytesHomogeneousUint64_a11 = 0;
+int returnStruct1024BytesHomogeneousUint64_a12 = 0;
+int returnStruct1024BytesHomogeneousUint64_a13 = 0;
+int returnStruct1024BytesHomogeneousUint64_a14 = 0;
+int returnStruct1024BytesHomogeneousUint64_a15 = 0;
+int returnStruct1024BytesHomogeneousUint64_a16 = 0;
+int returnStruct1024BytesHomogeneousUint64_a17 = 0;
+int returnStruct1024BytesHomogeneousUint64_a18 = 0;
+int returnStruct1024BytesHomogeneousUint64_a19 = 0;
+int returnStruct1024BytesHomogeneousUint64_a20 = 0;
+int returnStruct1024BytesHomogeneousUint64_a21 = 0;
+int returnStruct1024BytesHomogeneousUint64_a22 = 0;
+int returnStruct1024BytesHomogeneousUint64_a23 = 0;
+int returnStruct1024BytesHomogeneousUint64_a24 = 0;
+int returnStruct1024BytesHomogeneousUint64_a25 = 0;
+int returnStruct1024BytesHomogeneousUint64_a26 = 0;
+int returnStruct1024BytesHomogeneousUint64_a27 = 0;
+int returnStruct1024BytesHomogeneousUint64_a28 = 0;
+int returnStruct1024BytesHomogeneousUint64_a29 = 0;
+int returnStruct1024BytesHomogeneousUint64_a30 = 0;
+int returnStruct1024BytesHomogeneousUint64_a31 = 0;
+int returnStruct1024BytesHomogeneousUint64_a32 = 0;
+int returnStruct1024BytesHomogeneousUint64_a33 = 0;
+int returnStruct1024BytesHomogeneousUint64_a34 = 0;
+int returnStruct1024BytesHomogeneousUint64_a35 = 0;
+int returnStruct1024BytesHomogeneousUint64_a36 = 0;
+int returnStruct1024BytesHomogeneousUint64_a37 = 0;
+int returnStruct1024BytesHomogeneousUint64_a38 = 0;
+int returnStruct1024BytesHomogeneousUint64_a39 = 0;
+int returnStruct1024BytesHomogeneousUint64_a40 = 0;
+int returnStruct1024BytesHomogeneousUint64_a41 = 0;
+int returnStruct1024BytesHomogeneousUint64_a42 = 0;
+int returnStruct1024BytesHomogeneousUint64_a43 = 0;
+int returnStruct1024BytesHomogeneousUint64_a44 = 0;
+int returnStruct1024BytesHomogeneousUint64_a45 = 0;
+int returnStruct1024BytesHomogeneousUint64_a46 = 0;
+int returnStruct1024BytesHomogeneousUint64_a47 = 0;
+int returnStruct1024BytesHomogeneousUint64_a48 = 0;
+int returnStruct1024BytesHomogeneousUint64_a49 = 0;
+int returnStruct1024BytesHomogeneousUint64_a50 = 0;
+int returnStruct1024BytesHomogeneousUint64_a51 = 0;
+int returnStruct1024BytesHomogeneousUint64_a52 = 0;
+int returnStruct1024BytesHomogeneousUint64_a53 = 0;
+int returnStruct1024BytesHomogeneousUint64_a54 = 0;
+int returnStruct1024BytesHomogeneousUint64_a55 = 0;
+int returnStruct1024BytesHomogeneousUint64_a56 = 0;
+int returnStruct1024BytesHomogeneousUint64_a57 = 0;
+int returnStruct1024BytesHomogeneousUint64_a58 = 0;
+int returnStruct1024BytesHomogeneousUint64_a59 = 0;
+int returnStruct1024BytesHomogeneousUint64_a60 = 0;
+int returnStruct1024BytesHomogeneousUint64_a61 = 0;
+int returnStruct1024BytesHomogeneousUint64_a62 = 0;
+int returnStruct1024BytesHomogeneousUint64_a63 = 0;
+int returnStruct1024BytesHomogeneousUint64_a64 = 0;
+int returnStruct1024BytesHomogeneousUint64_a65 = 0;
+int returnStruct1024BytesHomogeneousUint64_a66 = 0;
+int returnStruct1024BytesHomogeneousUint64_a67 = 0;
+int returnStruct1024BytesHomogeneousUint64_a68 = 0;
+int returnStruct1024BytesHomogeneousUint64_a69 = 0;
+int returnStruct1024BytesHomogeneousUint64_a70 = 0;
+int returnStruct1024BytesHomogeneousUint64_a71 = 0;
+int returnStruct1024BytesHomogeneousUint64_a72 = 0;
+int returnStruct1024BytesHomogeneousUint64_a73 = 0;
+int returnStruct1024BytesHomogeneousUint64_a74 = 0;
+int returnStruct1024BytesHomogeneousUint64_a75 = 0;
+int returnStruct1024BytesHomogeneousUint64_a76 = 0;
+int returnStruct1024BytesHomogeneousUint64_a77 = 0;
+int returnStruct1024BytesHomogeneousUint64_a78 = 0;
+int returnStruct1024BytesHomogeneousUint64_a79 = 0;
+int returnStruct1024BytesHomogeneousUint64_a80 = 0;
+int returnStruct1024BytesHomogeneousUint64_a81 = 0;
+int returnStruct1024BytesHomogeneousUint64_a82 = 0;
+int returnStruct1024BytesHomogeneousUint64_a83 = 0;
+int returnStruct1024BytesHomogeneousUint64_a84 = 0;
+int returnStruct1024BytesHomogeneousUint64_a85 = 0;
+int returnStruct1024BytesHomogeneousUint64_a86 = 0;
+int returnStruct1024BytesHomogeneousUint64_a87 = 0;
+int returnStruct1024BytesHomogeneousUint64_a88 = 0;
+int returnStruct1024BytesHomogeneousUint64_a89 = 0;
+int returnStruct1024BytesHomogeneousUint64_a90 = 0;
+int returnStruct1024BytesHomogeneousUint64_a91 = 0;
+int returnStruct1024BytesHomogeneousUint64_a92 = 0;
+int returnStruct1024BytesHomogeneousUint64_a93 = 0;
+int returnStruct1024BytesHomogeneousUint64_a94 = 0;
+int returnStruct1024BytesHomogeneousUint64_a95 = 0;
+int returnStruct1024BytesHomogeneousUint64_a96 = 0;
+int returnStruct1024BytesHomogeneousUint64_a97 = 0;
+int returnStruct1024BytesHomogeneousUint64_a98 = 0;
+int returnStruct1024BytesHomogeneousUint64_a99 = 0;
+int returnStruct1024BytesHomogeneousUint64_a100 = 0;
+int returnStruct1024BytesHomogeneousUint64_a101 = 0;
+int returnStruct1024BytesHomogeneousUint64_a102 = 0;
+int returnStruct1024BytesHomogeneousUint64_a103 = 0;
+int returnStruct1024BytesHomogeneousUint64_a104 = 0;
+int returnStruct1024BytesHomogeneousUint64_a105 = 0;
+int returnStruct1024BytesHomogeneousUint64_a106 = 0;
+int returnStruct1024BytesHomogeneousUint64_a107 = 0;
+int returnStruct1024BytesHomogeneousUint64_a108 = 0;
+int returnStruct1024BytesHomogeneousUint64_a109 = 0;
+int returnStruct1024BytesHomogeneousUint64_a110 = 0;
+int returnStruct1024BytesHomogeneousUint64_a111 = 0;
+int returnStruct1024BytesHomogeneousUint64_a112 = 0;
+int returnStruct1024BytesHomogeneousUint64_a113 = 0;
+int returnStruct1024BytesHomogeneousUint64_a114 = 0;
+int returnStruct1024BytesHomogeneousUint64_a115 = 0;
+int returnStruct1024BytesHomogeneousUint64_a116 = 0;
+int returnStruct1024BytesHomogeneousUint64_a117 = 0;
+int returnStruct1024BytesHomogeneousUint64_a118 = 0;
+int returnStruct1024BytesHomogeneousUint64_a119 = 0;
+int returnStruct1024BytesHomogeneousUint64_a120 = 0;
+int returnStruct1024BytesHomogeneousUint64_a121 = 0;
+int returnStruct1024BytesHomogeneousUint64_a122 = 0;
+int returnStruct1024BytesHomogeneousUint64_a123 = 0;
+int returnStruct1024BytesHomogeneousUint64_a124 = 0;
+int returnStruct1024BytesHomogeneousUint64_a125 = 0;
+int returnStruct1024BytesHomogeneousUint64_a126 = 0;
+int returnStruct1024BytesHomogeneousUint64_a127 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct1024BytesHomogeneousUint64 returnStruct1024BytesHomogeneousUint64Result =
+ Struct1024BytesHomogeneousUint64();
+
+Struct1024BytesHomogeneousUint64
+ returnStruct1024BytesHomogeneousUint64CalculateResult() {
+ Struct1024BytesHomogeneousUint64 result =
+ allocate<Struct1024BytesHomogeneousUint64>().ref;
+
+ result.a0 = returnStruct1024BytesHomogeneousUint64_a0;
+ result.a1 = returnStruct1024BytesHomogeneousUint64_a1;
+ result.a2 = returnStruct1024BytesHomogeneousUint64_a2;
+ result.a3 = returnStruct1024BytesHomogeneousUint64_a3;
+ result.a4 = returnStruct1024BytesHomogeneousUint64_a4;
+ result.a5 = returnStruct1024BytesHomogeneousUint64_a5;
+ result.a6 = returnStruct1024BytesHomogeneousUint64_a6;
+ result.a7 = returnStruct1024BytesHomogeneousUint64_a7;
+ result.a8 = returnStruct1024BytesHomogeneousUint64_a8;
+ result.a9 = returnStruct1024BytesHomogeneousUint64_a9;
+ result.a10 = returnStruct1024BytesHomogeneousUint64_a10;
+ result.a11 = returnStruct1024BytesHomogeneousUint64_a11;
+ result.a12 = returnStruct1024BytesHomogeneousUint64_a12;
+ result.a13 = returnStruct1024BytesHomogeneousUint64_a13;
+ result.a14 = returnStruct1024BytesHomogeneousUint64_a14;
+ result.a15 = returnStruct1024BytesHomogeneousUint64_a15;
+ result.a16 = returnStruct1024BytesHomogeneousUint64_a16;
+ result.a17 = returnStruct1024BytesHomogeneousUint64_a17;
+ result.a18 = returnStruct1024BytesHomogeneousUint64_a18;
+ result.a19 = returnStruct1024BytesHomogeneousUint64_a19;
+ result.a20 = returnStruct1024BytesHomogeneousUint64_a20;
+ result.a21 = returnStruct1024BytesHomogeneousUint64_a21;
+ result.a22 = returnStruct1024BytesHomogeneousUint64_a22;
+ result.a23 = returnStruct1024BytesHomogeneousUint64_a23;
+ result.a24 = returnStruct1024BytesHomogeneousUint64_a24;
+ result.a25 = returnStruct1024BytesHomogeneousUint64_a25;
+ result.a26 = returnStruct1024BytesHomogeneousUint64_a26;
+ result.a27 = returnStruct1024BytesHomogeneousUint64_a27;
+ result.a28 = returnStruct1024BytesHomogeneousUint64_a28;
+ result.a29 = returnStruct1024BytesHomogeneousUint64_a29;
+ result.a30 = returnStruct1024BytesHomogeneousUint64_a30;
+ result.a31 = returnStruct1024BytesHomogeneousUint64_a31;
+ result.a32 = returnStruct1024BytesHomogeneousUint64_a32;
+ result.a33 = returnStruct1024BytesHomogeneousUint64_a33;
+ result.a34 = returnStruct1024BytesHomogeneousUint64_a34;
+ result.a35 = returnStruct1024BytesHomogeneousUint64_a35;
+ result.a36 = returnStruct1024BytesHomogeneousUint64_a36;
+ result.a37 = returnStruct1024BytesHomogeneousUint64_a37;
+ result.a38 = returnStruct1024BytesHomogeneousUint64_a38;
+ result.a39 = returnStruct1024BytesHomogeneousUint64_a39;
+ result.a40 = returnStruct1024BytesHomogeneousUint64_a40;
+ result.a41 = returnStruct1024BytesHomogeneousUint64_a41;
+ result.a42 = returnStruct1024BytesHomogeneousUint64_a42;
+ result.a43 = returnStruct1024BytesHomogeneousUint64_a43;
+ result.a44 = returnStruct1024BytesHomogeneousUint64_a44;
+ result.a45 = returnStruct1024BytesHomogeneousUint64_a45;
+ result.a46 = returnStruct1024BytesHomogeneousUint64_a46;
+ result.a47 = returnStruct1024BytesHomogeneousUint64_a47;
+ result.a48 = returnStruct1024BytesHomogeneousUint64_a48;
+ result.a49 = returnStruct1024BytesHomogeneousUint64_a49;
+ result.a50 = returnStruct1024BytesHomogeneousUint64_a50;
+ result.a51 = returnStruct1024BytesHomogeneousUint64_a51;
+ result.a52 = returnStruct1024BytesHomogeneousUint64_a52;
+ result.a53 = returnStruct1024BytesHomogeneousUint64_a53;
+ result.a54 = returnStruct1024BytesHomogeneousUint64_a54;
+ result.a55 = returnStruct1024BytesHomogeneousUint64_a55;
+ result.a56 = returnStruct1024BytesHomogeneousUint64_a56;
+ result.a57 = returnStruct1024BytesHomogeneousUint64_a57;
+ result.a58 = returnStruct1024BytesHomogeneousUint64_a58;
+ result.a59 = returnStruct1024BytesHomogeneousUint64_a59;
+ result.a60 = returnStruct1024BytesHomogeneousUint64_a60;
+ result.a61 = returnStruct1024BytesHomogeneousUint64_a61;
+ result.a62 = returnStruct1024BytesHomogeneousUint64_a62;
+ result.a63 = returnStruct1024BytesHomogeneousUint64_a63;
+ result.a64 = returnStruct1024BytesHomogeneousUint64_a64;
+ result.a65 = returnStruct1024BytesHomogeneousUint64_a65;
+ result.a66 = returnStruct1024BytesHomogeneousUint64_a66;
+ result.a67 = returnStruct1024BytesHomogeneousUint64_a67;
+ result.a68 = returnStruct1024BytesHomogeneousUint64_a68;
+ result.a69 = returnStruct1024BytesHomogeneousUint64_a69;
+ result.a70 = returnStruct1024BytesHomogeneousUint64_a70;
+ result.a71 = returnStruct1024BytesHomogeneousUint64_a71;
+ result.a72 = returnStruct1024BytesHomogeneousUint64_a72;
+ result.a73 = returnStruct1024BytesHomogeneousUint64_a73;
+ result.a74 = returnStruct1024BytesHomogeneousUint64_a74;
+ result.a75 = returnStruct1024BytesHomogeneousUint64_a75;
+ result.a76 = returnStruct1024BytesHomogeneousUint64_a76;
+ result.a77 = returnStruct1024BytesHomogeneousUint64_a77;
+ result.a78 = returnStruct1024BytesHomogeneousUint64_a78;
+ result.a79 = returnStruct1024BytesHomogeneousUint64_a79;
+ result.a80 = returnStruct1024BytesHomogeneousUint64_a80;
+ result.a81 = returnStruct1024BytesHomogeneousUint64_a81;
+ result.a82 = returnStruct1024BytesHomogeneousUint64_a82;
+ result.a83 = returnStruct1024BytesHomogeneousUint64_a83;
+ result.a84 = returnStruct1024BytesHomogeneousUint64_a84;
+ result.a85 = returnStruct1024BytesHomogeneousUint64_a85;
+ result.a86 = returnStruct1024BytesHomogeneousUint64_a86;
+ result.a87 = returnStruct1024BytesHomogeneousUint64_a87;
+ result.a88 = returnStruct1024BytesHomogeneousUint64_a88;
+ result.a89 = returnStruct1024BytesHomogeneousUint64_a89;
+ result.a90 = returnStruct1024BytesHomogeneousUint64_a90;
+ result.a91 = returnStruct1024BytesHomogeneousUint64_a91;
+ result.a92 = returnStruct1024BytesHomogeneousUint64_a92;
+ result.a93 = returnStruct1024BytesHomogeneousUint64_a93;
+ result.a94 = returnStruct1024BytesHomogeneousUint64_a94;
+ result.a95 = returnStruct1024BytesHomogeneousUint64_a95;
+ result.a96 = returnStruct1024BytesHomogeneousUint64_a96;
+ result.a97 = returnStruct1024BytesHomogeneousUint64_a97;
+ result.a98 = returnStruct1024BytesHomogeneousUint64_a98;
+ result.a99 = returnStruct1024BytesHomogeneousUint64_a99;
+ result.a100 = returnStruct1024BytesHomogeneousUint64_a100;
+ result.a101 = returnStruct1024BytesHomogeneousUint64_a101;
+ result.a102 = returnStruct1024BytesHomogeneousUint64_a102;
+ result.a103 = returnStruct1024BytesHomogeneousUint64_a103;
+ result.a104 = returnStruct1024BytesHomogeneousUint64_a104;
+ result.a105 = returnStruct1024BytesHomogeneousUint64_a105;
+ result.a106 = returnStruct1024BytesHomogeneousUint64_a106;
+ result.a107 = returnStruct1024BytesHomogeneousUint64_a107;
+ result.a108 = returnStruct1024BytesHomogeneousUint64_a108;
+ result.a109 = returnStruct1024BytesHomogeneousUint64_a109;
+ result.a110 = returnStruct1024BytesHomogeneousUint64_a110;
+ result.a111 = returnStruct1024BytesHomogeneousUint64_a111;
+ result.a112 = returnStruct1024BytesHomogeneousUint64_a112;
+ result.a113 = returnStruct1024BytesHomogeneousUint64_a113;
+ result.a114 = returnStruct1024BytesHomogeneousUint64_a114;
+ result.a115 = returnStruct1024BytesHomogeneousUint64_a115;
+ result.a116 = returnStruct1024BytesHomogeneousUint64_a116;
+ result.a117 = returnStruct1024BytesHomogeneousUint64_a117;
+ result.a118 = returnStruct1024BytesHomogeneousUint64_a118;
+ result.a119 = returnStruct1024BytesHomogeneousUint64_a119;
+ result.a120 = returnStruct1024BytesHomogeneousUint64_a120;
+ result.a121 = returnStruct1024BytesHomogeneousUint64_a121;
+ result.a122 = returnStruct1024BytesHomogeneousUint64_a122;
+ result.a123 = returnStruct1024BytesHomogeneousUint64_a123;
+ result.a124 = returnStruct1024BytesHomogeneousUint64_a124;
+ result.a125 = returnStruct1024BytesHomogeneousUint64_a125;
+ result.a126 = returnStruct1024BytesHomogeneousUint64_a126;
+ result.a127 = returnStruct1024BytesHomogeneousUint64_a127;
+
+ returnStruct1024BytesHomogeneousUint64Result = result;
+
+ return result;
+}
+
+/// Test 1kb struct.
+Struct1024BytesHomogeneousUint64 returnStruct1024BytesHomogeneousUint64(
+ int a0,
+ int a1,
+ int a2,
+ int a3,
+ int a4,
+ int a5,
+ int a6,
+ int a7,
+ int a8,
+ int a9,
+ int a10,
+ int a11,
+ int a12,
+ int a13,
+ int a14,
+ int a15,
+ int a16,
+ int a17,
+ int a18,
+ int a19,
+ int a20,
+ int a21,
+ int a22,
+ int a23,
+ int a24,
+ int a25,
+ int a26,
+ int a27,
+ int a28,
+ int a29,
+ int a30,
+ int a31,
+ int a32,
+ int a33,
+ int a34,
+ int a35,
+ int a36,
+ int a37,
+ int a38,
+ int a39,
+ int a40,
+ int a41,
+ int a42,
+ int a43,
+ int a44,
+ int a45,
+ int a46,
+ int a47,
+ int a48,
+ int a49,
+ int a50,
+ int a51,
+ int a52,
+ int a53,
+ int a54,
+ int a55,
+ int a56,
+ int a57,
+ int a58,
+ int a59,
+ int a60,
+ int a61,
+ int a62,
+ int a63,
+ int a64,
+ int a65,
+ int a66,
+ int a67,
+ int a68,
+ int a69,
+ int a70,
+ int a71,
+ int a72,
+ int a73,
+ int a74,
+ int a75,
+ int a76,
+ int a77,
+ int a78,
+ int a79,
+ int a80,
+ int a81,
+ int a82,
+ int a83,
+ int a84,
+ int a85,
+ int a86,
+ int a87,
+ int a88,
+ int a89,
+ int a90,
+ int a91,
+ int a92,
+ int a93,
+ int a94,
+ int a95,
+ int a96,
+ int a97,
+ int a98,
+ int a99,
+ int a100,
+ int a101,
+ int a102,
+ int a103,
+ int a104,
+ int a105,
+ int a106,
+ int a107,
+ int a108,
+ int a109,
+ int a110,
+ int a111,
+ int a112,
+ int a113,
+ int a114,
+ int a115,
+ int a116,
+ int a117,
+ int a118,
+ int a119,
+ int a120,
+ int a121,
+ int a122,
+ int a123,
+ int a124,
+ int a125,
+ int a126,
+ int a127) {
+ print(
+ "returnStruct1024BytesHomogeneousUint64(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9}, ${a10}, ${a11}, ${a12}, ${a13}, ${a14}, ${a15}, ${a16}, ${a17}, ${a18}, ${a19}, ${a20}, ${a21}, ${a22}, ${a23}, ${a24}, ${a25}, ${a26}, ${a27}, ${a28}, ${a29}, ${a30}, ${a31}, ${a32}, ${a33}, ${a34}, ${a35}, ${a36}, ${a37}, ${a38}, ${a39}, ${a40}, ${a41}, ${a42}, ${a43}, ${a44}, ${a45}, ${a46}, ${a47}, ${a48}, ${a49}, ${a50}, ${a51}, ${a52}, ${a53}, ${a54}, ${a55}, ${a56}, ${a57}, ${a58}, ${a59}, ${a60}, ${a61}, ${a62}, ${a63}, ${a64}, ${a65}, ${a66}, ${a67}, ${a68}, ${a69}, ${a70}, ${a71}, ${a72}, ${a73}, ${a74}, ${a75}, ${a76}, ${a77}, ${a78}, ${a79}, ${a80}, ${a81}, ${a82}, ${a83}, ${a84}, ${a85}, ${a86}, ${a87}, ${a88}, ${a89}, ${a90}, ${a91}, ${a92}, ${a93}, ${a94}, ${a95}, ${a96}, ${a97}, ${a98}, ${a99}, ${a100}, ${a101}, ${a102}, ${a103}, ${a104}, ${a105}, ${a106}, ${a107}, ${a108}, ${a109}, ${a110}, ${a111}, ${a112}, ${a113}, ${a114}, ${a115}, ${a116}, ${a117}, ${a118}, ${a119}, ${a120}, ${a121}, ${a122}, ${a123}, ${a124}, ${a125}, ${a126}, ${a127})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "ReturnStruct1024BytesHomogeneousUint64 throwing on purpuse!");
+ }
+
+ returnStruct1024BytesHomogeneousUint64_a0 = a0;
+ returnStruct1024BytesHomogeneousUint64_a1 = a1;
+ returnStruct1024BytesHomogeneousUint64_a2 = a2;
+ returnStruct1024BytesHomogeneousUint64_a3 = a3;
+ returnStruct1024BytesHomogeneousUint64_a4 = a4;
+ returnStruct1024BytesHomogeneousUint64_a5 = a5;
+ returnStruct1024BytesHomogeneousUint64_a6 = a6;
+ returnStruct1024BytesHomogeneousUint64_a7 = a7;
+ returnStruct1024BytesHomogeneousUint64_a8 = a8;
+ returnStruct1024BytesHomogeneousUint64_a9 = a9;
+ returnStruct1024BytesHomogeneousUint64_a10 = a10;
+ returnStruct1024BytesHomogeneousUint64_a11 = a11;
+ returnStruct1024BytesHomogeneousUint64_a12 = a12;
+ returnStruct1024BytesHomogeneousUint64_a13 = a13;
+ returnStruct1024BytesHomogeneousUint64_a14 = a14;
+ returnStruct1024BytesHomogeneousUint64_a15 = a15;
+ returnStruct1024BytesHomogeneousUint64_a16 = a16;
+ returnStruct1024BytesHomogeneousUint64_a17 = a17;
+ returnStruct1024BytesHomogeneousUint64_a18 = a18;
+ returnStruct1024BytesHomogeneousUint64_a19 = a19;
+ returnStruct1024BytesHomogeneousUint64_a20 = a20;
+ returnStruct1024BytesHomogeneousUint64_a21 = a21;
+ returnStruct1024BytesHomogeneousUint64_a22 = a22;
+ returnStruct1024BytesHomogeneousUint64_a23 = a23;
+ returnStruct1024BytesHomogeneousUint64_a24 = a24;
+ returnStruct1024BytesHomogeneousUint64_a25 = a25;
+ returnStruct1024BytesHomogeneousUint64_a26 = a26;
+ returnStruct1024BytesHomogeneousUint64_a27 = a27;
+ returnStruct1024BytesHomogeneousUint64_a28 = a28;
+ returnStruct1024BytesHomogeneousUint64_a29 = a29;
+ returnStruct1024BytesHomogeneousUint64_a30 = a30;
+ returnStruct1024BytesHomogeneousUint64_a31 = a31;
+ returnStruct1024BytesHomogeneousUint64_a32 = a32;
+ returnStruct1024BytesHomogeneousUint64_a33 = a33;
+ returnStruct1024BytesHomogeneousUint64_a34 = a34;
+ returnStruct1024BytesHomogeneousUint64_a35 = a35;
+ returnStruct1024BytesHomogeneousUint64_a36 = a36;
+ returnStruct1024BytesHomogeneousUint64_a37 = a37;
+ returnStruct1024BytesHomogeneousUint64_a38 = a38;
+ returnStruct1024BytesHomogeneousUint64_a39 = a39;
+ returnStruct1024BytesHomogeneousUint64_a40 = a40;
+ returnStruct1024BytesHomogeneousUint64_a41 = a41;
+ returnStruct1024BytesHomogeneousUint64_a42 = a42;
+ returnStruct1024BytesHomogeneousUint64_a43 = a43;
+ returnStruct1024BytesHomogeneousUint64_a44 = a44;
+ returnStruct1024BytesHomogeneousUint64_a45 = a45;
+ returnStruct1024BytesHomogeneousUint64_a46 = a46;
+ returnStruct1024BytesHomogeneousUint64_a47 = a47;
+ returnStruct1024BytesHomogeneousUint64_a48 = a48;
+ returnStruct1024BytesHomogeneousUint64_a49 = a49;
+ returnStruct1024BytesHomogeneousUint64_a50 = a50;
+ returnStruct1024BytesHomogeneousUint64_a51 = a51;
+ returnStruct1024BytesHomogeneousUint64_a52 = a52;
+ returnStruct1024BytesHomogeneousUint64_a53 = a53;
+ returnStruct1024BytesHomogeneousUint64_a54 = a54;
+ returnStruct1024BytesHomogeneousUint64_a55 = a55;
+ returnStruct1024BytesHomogeneousUint64_a56 = a56;
+ returnStruct1024BytesHomogeneousUint64_a57 = a57;
+ returnStruct1024BytesHomogeneousUint64_a58 = a58;
+ returnStruct1024BytesHomogeneousUint64_a59 = a59;
+ returnStruct1024BytesHomogeneousUint64_a60 = a60;
+ returnStruct1024BytesHomogeneousUint64_a61 = a61;
+ returnStruct1024BytesHomogeneousUint64_a62 = a62;
+ returnStruct1024BytesHomogeneousUint64_a63 = a63;
+ returnStruct1024BytesHomogeneousUint64_a64 = a64;
+ returnStruct1024BytesHomogeneousUint64_a65 = a65;
+ returnStruct1024BytesHomogeneousUint64_a66 = a66;
+ returnStruct1024BytesHomogeneousUint64_a67 = a67;
+ returnStruct1024BytesHomogeneousUint64_a68 = a68;
+ returnStruct1024BytesHomogeneousUint64_a69 = a69;
+ returnStruct1024BytesHomogeneousUint64_a70 = a70;
+ returnStruct1024BytesHomogeneousUint64_a71 = a71;
+ returnStruct1024BytesHomogeneousUint64_a72 = a72;
+ returnStruct1024BytesHomogeneousUint64_a73 = a73;
+ returnStruct1024BytesHomogeneousUint64_a74 = a74;
+ returnStruct1024BytesHomogeneousUint64_a75 = a75;
+ returnStruct1024BytesHomogeneousUint64_a76 = a76;
+ returnStruct1024BytesHomogeneousUint64_a77 = a77;
+ returnStruct1024BytesHomogeneousUint64_a78 = a78;
+ returnStruct1024BytesHomogeneousUint64_a79 = a79;
+ returnStruct1024BytesHomogeneousUint64_a80 = a80;
+ returnStruct1024BytesHomogeneousUint64_a81 = a81;
+ returnStruct1024BytesHomogeneousUint64_a82 = a82;
+ returnStruct1024BytesHomogeneousUint64_a83 = a83;
+ returnStruct1024BytesHomogeneousUint64_a84 = a84;
+ returnStruct1024BytesHomogeneousUint64_a85 = a85;
+ returnStruct1024BytesHomogeneousUint64_a86 = a86;
+ returnStruct1024BytesHomogeneousUint64_a87 = a87;
+ returnStruct1024BytesHomogeneousUint64_a88 = a88;
+ returnStruct1024BytesHomogeneousUint64_a89 = a89;
+ returnStruct1024BytesHomogeneousUint64_a90 = a90;
+ returnStruct1024BytesHomogeneousUint64_a91 = a91;
+ returnStruct1024BytesHomogeneousUint64_a92 = a92;
+ returnStruct1024BytesHomogeneousUint64_a93 = a93;
+ returnStruct1024BytesHomogeneousUint64_a94 = a94;
+ returnStruct1024BytesHomogeneousUint64_a95 = a95;
+ returnStruct1024BytesHomogeneousUint64_a96 = a96;
+ returnStruct1024BytesHomogeneousUint64_a97 = a97;
+ returnStruct1024BytesHomogeneousUint64_a98 = a98;
+ returnStruct1024BytesHomogeneousUint64_a99 = a99;
+ returnStruct1024BytesHomogeneousUint64_a100 = a100;
+ returnStruct1024BytesHomogeneousUint64_a101 = a101;
+ returnStruct1024BytesHomogeneousUint64_a102 = a102;
+ returnStruct1024BytesHomogeneousUint64_a103 = a103;
+ returnStruct1024BytesHomogeneousUint64_a104 = a104;
+ returnStruct1024BytesHomogeneousUint64_a105 = a105;
+ returnStruct1024BytesHomogeneousUint64_a106 = a106;
+ returnStruct1024BytesHomogeneousUint64_a107 = a107;
+ returnStruct1024BytesHomogeneousUint64_a108 = a108;
+ returnStruct1024BytesHomogeneousUint64_a109 = a109;
+ returnStruct1024BytesHomogeneousUint64_a110 = a110;
+ returnStruct1024BytesHomogeneousUint64_a111 = a111;
+ returnStruct1024BytesHomogeneousUint64_a112 = a112;
+ returnStruct1024BytesHomogeneousUint64_a113 = a113;
+ returnStruct1024BytesHomogeneousUint64_a114 = a114;
+ returnStruct1024BytesHomogeneousUint64_a115 = a115;
+ returnStruct1024BytesHomogeneousUint64_a116 = a116;
+ returnStruct1024BytesHomogeneousUint64_a117 = a117;
+ returnStruct1024BytesHomogeneousUint64_a118 = a118;
+ returnStruct1024BytesHomogeneousUint64_a119 = a119;
+ returnStruct1024BytesHomogeneousUint64_a120 = a120;
+ returnStruct1024BytesHomogeneousUint64_a121 = a121;
+ returnStruct1024BytesHomogeneousUint64_a122 = a122;
+ returnStruct1024BytesHomogeneousUint64_a123 = a123;
+ returnStruct1024BytesHomogeneousUint64_a124 = a124;
+ returnStruct1024BytesHomogeneousUint64_a125 = a125;
+ returnStruct1024BytesHomogeneousUint64_a126 = a126;
+ returnStruct1024BytesHomogeneousUint64_a127 = a127;
+
+ final result = returnStruct1024BytesHomogeneousUint64CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStruct1024BytesHomogeneousUint64AfterCallback() {
+ free(returnStruct1024BytesHomogeneousUint64Result.addressOf);
+
+ final result = returnStruct1024BytesHomogeneousUint64CalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStruct1024BytesHomogeneousUint64Result.addressOf);
+}
+
+typedef ReturnStructArgumentStruct1ByteIntType = Struct1ByteInt Function(
+ Struct1ByteInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct1ByteInt returnStructArgumentStruct1ByteInt_a0 = Struct1ByteInt();
+
+// Result variable also global, so we can delete it after the callback.
+Struct1ByteInt returnStructArgumentStruct1ByteIntResult = Struct1ByteInt();
+
+Struct1ByteInt returnStructArgumentStruct1ByteIntCalculateResult() {
+ Struct1ByteInt result = returnStructArgumentStruct1ByteInt_a0;
+
+ returnStructArgumentStruct1ByteIntResult = result;
+
+ return result;
+}
+
+/// Test that a struct passed in as argument can be returned.
+/// Especially for ffi callbacks.
+/// Struct is passed in int registers in most ABIs.
+Struct1ByteInt returnStructArgumentStruct1ByteInt(Struct1ByteInt a0) {
+ print("returnStructArgumentStruct1ByteInt(${a0})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStructArgumentStruct1ByteInt throwing on purpuse!");
+ }
+
+ returnStructArgumentStruct1ByteInt_a0 = a0;
+
+ final result = returnStructArgumentStruct1ByteIntCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStructArgumentStruct1ByteIntAfterCallback() {
+ final result = returnStructArgumentStruct1ByteIntCalculateResult();
+
+ print("after callback result = $result");
+}
+
+typedef ReturnStructArgumentInt32x8Struct1ByteIntType = Struct1ByteInt Function(
+ Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32, Struct1ByteInt);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStructArgumentInt32x8Struct1ByteInt_a0 = 0;
+int returnStructArgumentInt32x8Struct1ByteInt_a1 = 0;
+int returnStructArgumentInt32x8Struct1ByteInt_a2 = 0;
+int returnStructArgumentInt32x8Struct1ByteInt_a3 = 0;
+int returnStructArgumentInt32x8Struct1ByteInt_a4 = 0;
+int returnStructArgumentInt32x8Struct1ByteInt_a5 = 0;
+int returnStructArgumentInt32x8Struct1ByteInt_a6 = 0;
+int returnStructArgumentInt32x8Struct1ByteInt_a7 = 0;
+Struct1ByteInt returnStructArgumentInt32x8Struct1ByteInt_a8 = Struct1ByteInt();
+
+// Result variable also global, so we can delete it after the callback.
+Struct1ByteInt returnStructArgumentInt32x8Struct1ByteIntResult =
+ Struct1ByteInt();
+
+Struct1ByteInt returnStructArgumentInt32x8Struct1ByteIntCalculateResult() {
+ Struct1ByteInt result = returnStructArgumentInt32x8Struct1ByteInt_a8;
+
+ returnStructArgumentInt32x8Struct1ByteIntResult = result;
+
+ return result;
+}
+
+/// Test that a struct passed in as argument can be returned.
+/// Especially for ffi callbacks.
+/// Struct is passed on stack on all ABIs.
+Struct1ByteInt returnStructArgumentInt32x8Struct1ByteInt(int a0, int a1, int a2,
+ int a3, int a4, int a5, int a6, int a7, Struct1ByteInt a8) {
+ print(
+ "returnStructArgumentInt32x8Struct1ByteInt(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "ReturnStructArgumentInt32x8Struct1ByteInt throwing on purpuse!");
+ }
+
+ returnStructArgumentInt32x8Struct1ByteInt_a0 = a0;
+ returnStructArgumentInt32x8Struct1ByteInt_a1 = a1;
+ returnStructArgumentInt32x8Struct1ByteInt_a2 = a2;
+ returnStructArgumentInt32x8Struct1ByteInt_a3 = a3;
+ returnStructArgumentInt32x8Struct1ByteInt_a4 = a4;
+ returnStructArgumentInt32x8Struct1ByteInt_a5 = a5;
+ returnStructArgumentInt32x8Struct1ByteInt_a6 = a6;
+ returnStructArgumentInt32x8Struct1ByteInt_a7 = a7;
+ returnStructArgumentInt32x8Struct1ByteInt_a8 = a8;
+
+ final result = returnStructArgumentInt32x8Struct1ByteIntCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStructArgumentInt32x8Struct1ByteIntAfterCallback() {
+ final result = returnStructArgumentInt32x8Struct1ByteIntCalculateResult();
+
+ print("after callback result = $result");
+}
+
+typedef ReturnStructArgumentStruct8BytesHomogeneousFloatType
+ = Struct8BytesHomogeneousFloat Function(Struct8BytesHomogeneousFloat);
+
+// Global variables to be able to test inputs after callback returned.
+Struct8BytesHomogeneousFloat
+ returnStructArgumentStruct8BytesHomogeneousFloat_a0 =
+ Struct8BytesHomogeneousFloat();
+
+// Result variable also global, so we can delete it after the callback.
+Struct8BytesHomogeneousFloat
+ returnStructArgumentStruct8BytesHomogeneousFloatResult =
+ Struct8BytesHomogeneousFloat();
+
+Struct8BytesHomogeneousFloat
+ returnStructArgumentStruct8BytesHomogeneousFloatCalculateResult() {
+ Struct8BytesHomogeneousFloat result =
+ returnStructArgumentStruct8BytesHomogeneousFloat_a0;
+
+ returnStructArgumentStruct8BytesHomogeneousFloatResult = result;
+
+ return result;
+}
+
+/// Test that a struct passed in as argument can be returned.
+/// Especially for ffi callbacks.
+/// Struct is passed in float registers in most ABIs.
+Struct8BytesHomogeneousFloat returnStructArgumentStruct8BytesHomogeneousFloat(
+ Struct8BytesHomogeneousFloat a0) {
+ print("returnStructArgumentStruct8BytesHomogeneousFloat(${a0})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "ReturnStructArgumentStruct8BytesHomogeneousFloat throwing on purpuse!");
+ }
+
+ returnStructArgumentStruct8BytesHomogeneousFloat_a0 = a0;
+
+ final result =
+ returnStructArgumentStruct8BytesHomogeneousFloatCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStructArgumentStruct8BytesHomogeneousFloatAfterCallback() {
+ final result =
+ returnStructArgumentStruct8BytesHomogeneousFloatCalculateResult();
+
+ print("after callback result = $result");
+}
+
+typedef ReturnStructArgumentStruct20BytesHomogeneousInt32Type
+ = Struct20BytesHomogeneousInt32 Function(Struct20BytesHomogeneousInt32);
+
+// Global variables to be able to test inputs after callback returned.
+Struct20BytesHomogeneousInt32
+ returnStructArgumentStruct20BytesHomogeneousInt32_a0 =
+ Struct20BytesHomogeneousInt32();
+
+// Result variable also global, so we can delete it after the callback.
+Struct20BytesHomogeneousInt32
+ returnStructArgumentStruct20BytesHomogeneousInt32Result =
+ Struct20BytesHomogeneousInt32();
+
+Struct20BytesHomogeneousInt32
+ returnStructArgumentStruct20BytesHomogeneousInt32CalculateResult() {
+ Struct20BytesHomogeneousInt32 result =
+ returnStructArgumentStruct20BytesHomogeneousInt32_a0;
+
+ returnStructArgumentStruct20BytesHomogeneousInt32Result = result;
+
+ return result;
+}
+
+/// On arm64, both argument and return value are passed in by pointer.
+Struct20BytesHomogeneousInt32 returnStructArgumentStruct20BytesHomogeneousInt32(
+ Struct20BytesHomogeneousInt32 a0) {
+ print("returnStructArgumentStruct20BytesHomogeneousInt32(${a0})");
+
+ // In legacy mode, possibly return null.
+ if (a0.a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0.a0 == 42 || a0.a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "ReturnStructArgumentStruct20BytesHomogeneousInt32 throwing on purpuse!");
+ }
+
+ returnStructArgumentStruct20BytesHomogeneousInt32_a0 = a0;
+
+ final result =
+ returnStructArgumentStruct20BytesHomogeneousInt32CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStructArgumentStruct20BytesHomogeneousInt32AfterCallback() {
+ final result =
+ returnStructArgumentStruct20BytesHomogeneousInt32CalculateResult();
+
+ print("after callback result = $result");
+}
+
+typedef ReturnStructArgumentInt32x8Struct20BytesHomogeneouType
+ = Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32, Int32,
+ Int32, Int32, Int32, Struct20BytesHomogeneousInt32);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStructArgumentInt32x8Struct20BytesHomogeneou_a0 = 0;
+int returnStructArgumentInt32x8Struct20BytesHomogeneou_a1 = 0;
+int returnStructArgumentInt32x8Struct20BytesHomogeneou_a2 = 0;
+int returnStructArgumentInt32x8Struct20BytesHomogeneou_a3 = 0;
+int returnStructArgumentInt32x8Struct20BytesHomogeneou_a4 = 0;
+int returnStructArgumentInt32x8Struct20BytesHomogeneou_a5 = 0;
+int returnStructArgumentInt32x8Struct20BytesHomogeneou_a6 = 0;
+int returnStructArgumentInt32x8Struct20BytesHomogeneou_a7 = 0;
+Struct20BytesHomogeneousInt32
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a8 =
+ Struct20BytesHomogeneousInt32();
+
+// Result variable also global, so we can delete it after the callback.
+Struct20BytesHomogeneousInt32
+ returnStructArgumentInt32x8Struct20BytesHomogeneouResult =
+ Struct20BytesHomogeneousInt32();
+
+Struct20BytesHomogeneousInt32
+ returnStructArgumentInt32x8Struct20BytesHomogeneouCalculateResult() {
+ Struct20BytesHomogeneousInt32 result =
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a8;
+
+ returnStructArgumentInt32x8Struct20BytesHomogeneouResult = result;
+
+ return result;
+}
+
+/// On arm64, both argument and return value are passed in by pointer.
+/// Ints exhaust registers, so that pointer is passed on stack.
+Struct20BytesHomogeneousInt32
+ returnStructArgumentInt32x8Struct20BytesHomogeneou(
+ int a0,
+ int a1,
+ int a2,
+ int a3,
+ int a4,
+ int a5,
+ int a6,
+ int a7,
+ Struct20BytesHomogeneousInt32 a8) {
+ print(
+ "returnStructArgumentInt32x8Struct20BytesHomogeneou(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "ReturnStructArgumentInt32x8Struct20BytesHomogeneou throwing on purpuse!");
+ }
+
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a0 = a0;
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a1 = a1;
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a2 = a2;
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a3 = a3;
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a4 = a4;
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a5 = a5;
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a6 = a6;
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a7 = a7;
+ returnStructArgumentInt32x8Struct20BytesHomogeneou_a8 = a8;
+
+ final result =
+ returnStructArgumentInt32x8Struct20BytesHomogeneouCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStructArgumentInt32x8Struct20BytesHomogeneouAfterCallback() {
+ final result =
+ returnStructArgumentInt32x8Struct20BytesHomogeneouCalculateResult();
+
+ print("after callback result = $result");
+}
+
+typedef ReturnStructAlignmentInt16Type = StructAlignmentInt16 Function(
+ Int8, Int16, Int8);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStructAlignmentInt16_a0 = 0;
+int returnStructAlignmentInt16_a1 = 0;
+int returnStructAlignmentInt16_a2 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+StructAlignmentInt16 returnStructAlignmentInt16Result = StructAlignmentInt16();
+
+StructAlignmentInt16 returnStructAlignmentInt16CalculateResult() {
+ StructAlignmentInt16 result = allocate<StructAlignmentInt16>().ref;
+
+ result.a0 = returnStructAlignmentInt16_a0;
+ result.a1 = returnStructAlignmentInt16_a1;
+ result.a2 = returnStructAlignmentInt16_a2;
+
+ returnStructAlignmentInt16Result = result;
+
+ return result;
+}
+
+/// Test alignment and padding of 16 byte int within struct.
+StructAlignmentInt16 returnStructAlignmentInt16(int a0, int a1, int a2) {
+ print("returnStructAlignmentInt16(${a0}, ${a1}, ${a2})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStructAlignmentInt16 throwing on purpuse!");
+ }
+
+ returnStructAlignmentInt16_a0 = a0;
+ returnStructAlignmentInt16_a1 = a1;
+ returnStructAlignmentInt16_a2 = a2;
+
+ final result = returnStructAlignmentInt16CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStructAlignmentInt16AfterCallback() {
+ free(returnStructAlignmentInt16Result.addressOf);
+
+ final result = returnStructAlignmentInt16CalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStructAlignmentInt16Result.addressOf);
+}
+
+typedef ReturnStructAlignmentInt32Type = StructAlignmentInt32 Function(
+ Int8, Int32, Int8);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStructAlignmentInt32_a0 = 0;
+int returnStructAlignmentInt32_a1 = 0;
+int returnStructAlignmentInt32_a2 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+StructAlignmentInt32 returnStructAlignmentInt32Result = StructAlignmentInt32();
+
+StructAlignmentInt32 returnStructAlignmentInt32CalculateResult() {
+ StructAlignmentInt32 result = allocate<StructAlignmentInt32>().ref;
+
+ result.a0 = returnStructAlignmentInt32_a0;
+ result.a1 = returnStructAlignmentInt32_a1;
+ result.a2 = returnStructAlignmentInt32_a2;
+
+ returnStructAlignmentInt32Result = result;
+
+ return result;
+}
+
+/// Test alignment and padding of 32 byte int within struct.
+StructAlignmentInt32 returnStructAlignmentInt32(int a0, int a1, int a2) {
+ print("returnStructAlignmentInt32(${a0}, ${a1}, ${a2})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStructAlignmentInt32 throwing on purpuse!");
+ }
+
+ returnStructAlignmentInt32_a0 = a0;
+ returnStructAlignmentInt32_a1 = a1;
+ returnStructAlignmentInt32_a2 = a2;
+
+ final result = returnStructAlignmentInt32CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStructAlignmentInt32AfterCallback() {
+ free(returnStructAlignmentInt32Result.addressOf);
+
+ final result = returnStructAlignmentInt32CalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStructAlignmentInt32Result.addressOf);
+}
+
+typedef ReturnStructAlignmentInt64Type = StructAlignmentInt64 Function(
+ Int8, Int64, Int8);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStructAlignmentInt64_a0 = 0;
+int returnStructAlignmentInt64_a1 = 0;
+int returnStructAlignmentInt64_a2 = 0;
+
+// Result variable also global, so we can delete it after the callback.
+StructAlignmentInt64 returnStructAlignmentInt64Result = StructAlignmentInt64();
+
+StructAlignmentInt64 returnStructAlignmentInt64CalculateResult() {
+ StructAlignmentInt64 result = allocate<StructAlignmentInt64>().ref;
+
+ result.a0 = returnStructAlignmentInt64_a0;
+ result.a1 = returnStructAlignmentInt64_a1;
+ result.a2 = returnStructAlignmentInt64_a2;
+
+ returnStructAlignmentInt64Result = result;
+
+ return result;
+}
+
+/// Test alignment and padding of 64 byte int within struct.
+StructAlignmentInt64 returnStructAlignmentInt64(int a0, int a1, int a2) {
+ print("returnStructAlignmentInt64(${a0}, ${a1}, ${a2})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("ReturnStructAlignmentInt64 throwing on purpuse!");
+ }
+
+ returnStructAlignmentInt64_a0 = a0;
+ returnStructAlignmentInt64_a1 = a1;
+ returnStructAlignmentInt64_a2 = a2;
+
+ final result = returnStructAlignmentInt64CalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void returnStructAlignmentInt64AfterCallback() {
+ free(returnStructAlignmentInt64Result.addressOf);
+
+ final result = returnStructAlignmentInt64CalculateResult();
+
+ print("after callback result = $result");
+
+ free(returnStructAlignmentInt64Result.addressOf);
+}
diff --git a/tests/ffi_2/function_callbacks_structs_by_value_test.dart b/tests/ffi_2/function_callbacks_structs_by_value_test.dart
new file mode 100644
index 0000000..98ab518
--- /dev/null
+++ b/tests/ffi_2/function_callbacks_structs_by_value_test.dart
@@ -0,0 +1,71 @@
+// Copyright (c) 2020, 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.
+//
+// SharedObjects=ffi_test_functions
+//
+// VMOptions=--deterministic --optimization-counter-threshold=5 --use-slow-path --stacktrace-every=100
+
+import 'dart:ffi';
+
+import "package:expect/expect.dart";
+import "package:ffi/ffi.dart";
+
+// Reuse the struct classes.
+import 'function_structs_by_value_generated_test.dart';
+
+void main() {
+ for (int i = 0; i < 10; i++) {
+ recursiveTest(10);
+ recursiveTest(11);
+ }
+}
+
+void recursiveTest(int recursionCounter) {
+ final struct = allocate<Struct20BytesHomogeneousInt32>().ref;
+ struct.a0 = 1;
+ struct.a1 = 2;
+ struct.a2 = 3;
+ struct.a3 = 4;
+ struct.a4 = 5;
+ final result = dartPassStructRecursive(recursionCounter, struct);
+ Expect.equals(struct.a0 + recursionCounter * 2, result.a0);
+ Expect.equals(struct.a1, result.a1);
+ Expect.equals(struct.a2, result.a2);
+ Expect.equals(struct.a3, result.a3);
+ Expect.equals(struct.a4, result.a4);
+ free(struct.addressOf);
+}
+
+Struct20BytesHomogeneousInt32 dartPassStructRecursive(
+ int recursionCounter, Struct20BytesHomogeneousInt32 struct) {
+ print("callbackPassStructRecurisive($recursionCounter, $struct)");
+ struct.a0++;
+ final structA0Saved = struct.a0;
+ if (recursionCounter <= 0) {
+ print("returning");
+ return struct;
+ }
+
+ final result =
+ cPassStructRecursive(recursionCounter - 1, struct, functionPointer);
+ result.a0++;
+
+ // Check struct.a0 is not modified by Dart->C call.
+ Expect.equals(structA0Saved, struct.a0);
+
+ // Check struct.a0 is not modified by C->Dart callback, if so struct.a4 == 0.
+ Expect.notEquals(0, struct.a4);
+
+ return result;
+}
+
+final functionPointer = Pointer.fromFunction<
+ Struct20BytesHomogeneousInt32 Function(
+ Int64, Struct20BytesHomogeneousInt32)>(dartPassStructRecursive);
+
+final cPassStructRecursive = ffiTestFunctions.lookupFunction<
+ Struct20BytesHomogeneousInt32 Function(Int64 recursionCounter,
+ Struct20BytesHomogeneousInt32 struct, Pointer callbackAddress),
+ Struct20BytesHomogeneousInt32 Function(int recursionCounter,
+ Struct20BytesHomogeneousInt32, Pointer)>("PassStructRecursive");
diff --git a/tests/ffi_2/function_structs_by_value_generated_test.dart b/tests/ffi_2/function_structs_by_value_generated_test.dart
new file mode 100644
index 0000000..d2c34dd
--- /dev/null
+++ b/tests/ffi_2/function_structs_by_value_generated_test.dart
@@ -0,0 +1,4720 @@
+// Copyright (c) 2020, 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.
+//
+// This file has been automatically generated. Please do not edit it manually.
+//
+// SharedObjects=ffi_test_functions
+// VMOptions=
+// VMOptions=--deterministic --optimization-counter-threshold=5
+// VMOptions=--use-slow-path
+// VMOptions=--use-slow-path --stacktrace-every=100
+
+import 'dart:ffi';
+
+import "package:expect/expect.dart";
+import "package:ffi/ffi.dart";
+
+import 'dylib_utils.dart';
+
+final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
+void main() {
+ for (int i = 0; i < 10; ++i) {
+ testPassStruct1ByteIntx10();
+ testPassStruct3BytesIntx10();
+ testPassStruct4BytesHomogeneousInt16x10();
+ testPassStruct7BytesIntx10();
+ testPassStruct8BytesIntx10();
+ testPassStruct8BytesHomogeneousFloatx10();
+ testPassStruct8BytesMixedx10();
+ testPassStruct9BytesIntx10();
+ testPassStruct9BytesHomogeneousUint82x10();
+ testPassStruct12BytesHomogeneousFloatx6();
+ testPassStruct16BytesHomogeneousFloatx5();
+ testPassStruct16BytesMixedx10();
+ testPassStruct16BytesMixed2x10();
+ testPassStruct17BytesIntx10();
+ testPassStruct19BytesHomogeneousUint8x10();
+ testPassStruct20BytesHomogeneousInt32x10();
+ testPassStruct20BytesHomogeneousFloat();
+ testPassStruct32BytesHomogeneousDoublex5();
+ testPassStruct40BytesHomogeneousDouble();
+ testPassStruct1024BytesHomogeneousUint64();
+ testPassFloatStruct16BytesHomogeneousFloatFloatStruct1();
+ testPassFloatStruct32BytesHomogeneousDoubleFloatStruct();
+ testPassInt8Struct16BytesMixedInt8Struct16BytesMixedIn();
+ testPassDoublex6Struct16BytesMixedx4Int32();
+ testPassInt32x4Struct16BytesMixedx4Double();
+ testPassStruct40BytesHomogeneousDoubleStruct4BytesHomo();
+ testPassStructAlignmentInt16();
+ testPassStructAlignmentInt32();
+ testPassStructAlignmentInt64();
+ testReturnStruct1ByteInt();
+ testReturnStruct3BytesInt();
+ testReturnStruct4BytesHomogeneousInt16();
+ testReturnStruct7BytesInt();
+ testReturnStruct8BytesInt();
+ testReturnStruct8BytesHomogeneousFloat();
+ testReturnStruct8BytesMixed();
+ testReturnStruct9BytesInt();
+ testReturnStruct9BytesHomogeneousUint82();
+ testReturnStruct12BytesHomogeneousFloat();
+ testReturnStruct16BytesHomogeneousFloat();
+ testReturnStruct16BytesMixed();
+ testReturnStruct16BytesMixed2();
+ testReturnStruct17BytesInt();
+ testReturnStruct19BytesHomogeneousUint8();
+ testReturnStruct20BytesHomogeneousInt32();
+ testReturnStruct20BytesHomogeneousFloat();
+ testReturnStruct32BytesHomogeneousDouble();
+ testReturnStruct40BytesHomogeneousDouble();
+ testReturnStruct1024BytesHomogeneousUint64();
+ testReturnStructArgumentStruct1ByteInt();
+ testReturnStructArgumentInt32x8Struct1ByteInt();
+ testReturnStructArgumentStruct8BytesHomogeneousFloat();
+ testReturnStructArgumentStruct20BytesHomogeneousInt32();
+ testReturnStructArgumentInt32x8Struct20BytesHomogeneou();
+ testReturnStructAlignmentInt16();
+ testReturnStructAlignmentInt32();
+ testReturnStructAlignmentInt64();
+ }
+}
+
+class Struct0Bytes extends Struct {
+ String toString() => "()";
+}
+
+class Struct1ByteInt extends Struct {
+ @Int8()
+ int a0;
+
+ String toString() => "(${a0})";
+}
+
+class Struct3BytesInt extends Struct {
+ @Int16()
+ int a0;
+
+ @Int8()
+ int a1;
+
+ String toString() => "(${a0}, ${a1})";
+}
+
+class Struct4BytesHomogeneousInt16 extends Struct {
+ @Int16()
+ int a0;
+
+ @Int16()
+ int a1;
+
+ String toString() => "(${a0}, ${a1})";
+}
+
+class Struct7BytesInt extends Struct {
+ @Int32()
+ int a0;
+
+ @Int16()
+ int a1;
+
+ @Int8()
+ int a2;
+
+ String toString() => "(${a0}, ${a1}, ${a2})";
+}
+
+class Struct8BytesInt extends Struct {
+ @Int16()
+ int a0;
+
+ @Int16()
+ int a1;
+
+ @Int32()
+ int a2;
+
+ String toString() => "(${a0}, ${a1}, ${a2})";
+}
+
+class Struct8BytesHomogeneousFloat extends Struct {
+ @Float()
+ double a0;
+
+ @Float()
+ double a1;
+
+ String toString() => "(${a0}, ${a1})";
+}
+
+class Struct8BytesMixed extends Struct {
+ @Float()
+ double a0;
+
+ @Int16()
+ int a1;
+
+ @Int16()
+ int a2;
+
+ String toString() => "(${a0}, ${a1}, ${a2})";
+}
+
+class Struct9BytesInt extends Struct {
+ @Int64()
+ int a0;
+
+ @Int8()
+ int a1;
+
+ String toString() => "(${a0}, ${a1})";
+}
+
+class Struct9BytesHomogeneousUint82 extends Struct {
+ @Uint8()
+ int a0;
+
+ @Uint8()
+ int a1;
+
+ @Uint8()
+ int a2;
+
+ @Uint8()
+ int a3;
+
+ @Uint8()
+ int a4;
+
+ @Uint8()
+ int a5;
+
+ @Uint8()
+ int a6;
+
+ @Uint8()
+ int a7;
+
+ @Uint8()
+ int a8;
+
+ String toString() =>
+ "(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8})";
+}
+
+class Struct12BytesHomogeneousFloat extends Struct {
+ @Float()
+ double a0;
+
+ @Float()
+ double a1;
+
+ @Float()
+ double a2;
+
+ String toString() => "(${a0}, ${a1}, ${a2})";
+}
+
+class Struct16BytesHomogeneousFloat extends Struct {
+ @Float()
+ double a0;
+
+ @Float()
+ double a1;
+
+ @Float()
+ double a2;
+
+ @Float()
+ double a3;
+
+ String toString() => "(${a0}, ${a1}, ${a2}, ${a3})";
+}
+
+class Struct16BytesMixed extends Struct {
+ @Double()
+ double a0;
+
+ @Int64()
+ int a1;
+
+ String toString() => "(${a0}, ${a1})";
+}
+
+class Struct16BytesMixed2 extends Struct {
+ @Float()
+ double a0;
+
+ @Float()
+ double a1;
+
+ @Float()
+ double a2;
+
+ @Int32()
+ int a3;
+
+ String toString() => "(${a0}, ${a1}, ${a2}, ${a3})";
+}
+
+class Struct17BytesInt extends Struct {
+ @Int64()
+ int a0;
+
+ @Int64()
+ int a1;
+
+ @Int8()
+ int a2;
+
+ String toString() => "(${a0}, ${a1}, ${a2})";
+}
+
+class Struct19BytesHomogeneousUint8 extends Struct {
+ @Uint8()
+ int a0;
+
+ @Uint8()
+ int a1;
+
+ @Uint8()
+ int a2;
+
+ @Uint8()
+ int a3;
+
+ @Uint8()
+ int a4;
+
+ @Uint8()
+ int a5;
+
+ @Uint8()
+ int a6;
+
+ @Uint8()
+ int a7;
+
+ @Uint8()
+ int a8;
+
+ @Uint8()
+ int a9;
+
+ @Uint8()
+ int a10;
+
+ @Uint8()
+ int a11;
+
+ @Uint8()
+ int a12;
+
+ @Uint8()
+ int a13;
+
+ @Uint8()
+ int a14;
+
+ @Uint8()
+ int a15;
+
+ @Uint8()
+ int a16;
+
+ @Uint8()
+ int a17;
+
+ @Uint8()
+ int a18;
+
+ String toString() =>
+ "(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9}, ${a10}, ${a11}, ${a12}, ${a13}, ${a14}, ${a15}, ${a16}, ${a17}, ${a18})";
+}
+
+class Struct20BytesHomogeneousInt32 extends Struct {
+ @Int32()
+ int a0;
+
+ @Int32()
+ int a1;
+
+ @Int32()
+ int a2;
+
+ @Int32()
+ int a3;
+
+ @Int32()
+ int a4;
+
+ String toString() => "(${a0}, ${a1}, ${a2}, ${a3}, ${a4})";
+}
+
+class Struct20BytesHomogeneousFloat extends Struct {
+ @Float()
+ double a0;
+
+ @Float()
+ double a1;
+
+ @Float()
+ double a2;
+
+ @Float()
+ double a3;
+
+ @Float()
+ double a4;
+
+ String toString() => "(${a0}, ${a1}, ${a2}, ${a3}, ${a4})";
+}
+
+class Struct32BytesHomogeneousDouble extends Struct {
+ @Double()
+ double a0;
+
+ @Double()
+ double a1;
+
+ @Double()
+ double a2;
+
+ @Double()
+ double a3;
+
+ String toString() => "(${a0}, ${a1}, ${a2}, ${a3})";
+}
+
+class Struct40BytesHomogeneousDouble extends Struct {
+ @Double()
+ double a0;
+
+ @Double()
+ double a1;
+
+ @Double()
+ double a2;
+
+ @Double()
+ double a3;
+
+ @Double()
+ double a4;
+
+ String toString() => "(${a0}, ${a1}, ${a2}, ${a3}, ${a4})";
+}
+
+class Struct1024BytesHomogeneousUint64 extends Struct {
+ @Uint64()
+ int a0;
+
+ @Uint64()
+ int a1;
+
+ @Uint64()
+ int a2;
+
+ @Uint64()
+ int a3;
+
+ @Uint64()
+ int a4;
+
+ @Uint64()
+ int a5;
+
+ @Uint64()
+ int a6;
+
+ @Uint64()
+ int a7;
+
+ @Uint64()
+ int a8;
+
+ @Uint64()
+ int a9;
+
+ @Uint64()
+ int a10;
+
+ @Uint64()
+ int a11;
+
+ @Uint64()
+ int a12;
+
+ @Uint64()
+ int a13;
+
+ @Uint64()
+ int a14;
+
+ @Uint64()
+ int a15;
+
+ @Uint64()
+ int a16;
+
+ @Uint64()
+ int a17;
+
+ @Uint64()
+ int a18;
+
+ @Uint64()
+ int a19;
+
+ @Uint64()
+ int a20;
+
+ @Uint64()
+ int a21;
+
+ @Uint64()
+ int a22;
+
+ @Uint64()
+ int a23;
+
+ @Uint64()
+ int a24;
+
+ @Uint64()
+ int a25;
+
+ @Uint64()
+ int a26;
+
+ @Uint64()
+ int a27;
+
+ @Uint64()
+ int a28;
+
+ @Uint64()
+ int a29;
+
+ @Uint64()
+ int a30;
+
+ @Uint64()
+ int a31;
+
+ @Uint64()
+ int a32;
+
+ @Uint64()
+ int a33;
+
+ @Uint64()
+ int a34;
+
+ @Uint64()
+ int a35;
+
+ @Uint64()
+ int a36;
+
+ @Uint64()
+ int a37;
+
+ @Uint64()
+ int a38;
+
+ @Uint64()
+ int a39;
+
+ @Uint64()
+ int a40;
+
+ @Uint64()
+ int a41;
+
+ @Uint64()
+ int a42;
+
+ @Uint64()
+ int a43;
+
+ @Uint64()
+ int a44;
+
+ @Uint64()
+ int a45;
+
+ @Uint64()
+ int a46;
+
+ @Uint64()
+ int a47;
+
+ @Uint64()
+ int a48;
+
+ @Uint64()
+ int a49;
+
+ @Uint64()
+ int a50;
+
+ @Uint64()
+ int a51;
+
+ @Uint64()
+ int a52;
+
+ @Uint64()
+ int a53;
+
+ @Uint64()
+ int a54;
+
+ @Uint64()
+ int a55;
+
+ @Uint64()
+ int a56;
+
+ @Uint64()
+ int a57;
+
+ @Uint64()
+ int a58;
+
+ @Uint64()
+ int a59;
+
+ @Uint64()
+ int a60;
+
+ @Uint64()
+ int a61;
+
+ @Uint64()
+ int a62;
+
+ @Uint64()
+ int a63;
+
+ @Uint64()
+ int a64;
+
+ @Uint64()
+ int a65;
+
+ @Uint64()
+ int a66;
+
+ @Uint64()
+ int a67;
+
+ @Uint64()
+ int a68;
+
+ @Uint64()
+ int a69;
+
+ @Uint64()
+ int a70;
+
+ @Uint64()
+ int a71;
+
+ @Uint64()
+ int a72;
+
+ @Uint64()
+ int a73;
+
+ @Uint64()
+ int a74;
+
+ @Uint64()
+ int a75;
+
+ @Uint64()
+ int a76;
+
+ @Uint64()
+ int a77;
+
+ @Uint64()
+ int a78;
+
+ @Uint64()
+ int a79;
+
+ @Uint64()
+ int a80;
+
+ @Uint64()
+ int a81;
+
+ @Uint64()
+ int a82;
+
+ @Uint64()
+ int a83;
+
+ @Uint64()
+ int a84;
+
+ @Uint64()
+ int a85;
+
+ @Uint64()
+ int a86;
+
+ @Uint64()
+ int a87;
+
+ @Uint64()
+ int a88;
+
+ @Uint64()
+ int a89;
+
+ @Uint64()
+ int a90;
+
+ @Uint64()
+ int a91;
+
+ @Uint64()
+ int a92;
+
+ @Uint64()
+ int a93;
+
+ @Uint64()
+ int a94;
+
+ @Uint64()
+ int a95;
+
+ @Uint64()
+ int a96;
+
+ @Uint64()
+ int a97;
+
+ @Uint64()
+ int a98;
+
+ @Uint64()
+ int a99;
+
+ @Uint64()
+ int a100;
+
+ @Uint64()
+ int a101;
+
+ @Uint64()
+ int a102;
+
+ @Uint64()
+ int a103;
+
+ @Uint64()
+ int a104;
+
+ @Uint64()
+ int a105;
+
+ @Uint64()
+ int a106;
+
+ @Uint64()
+ int a107;
+
+ @Uint64()
+ int a108;
+
+ @Uint64()
+ int a109;
+
+ @Uint64()
+ int a110;
+
+ @Uint64()
+ int a111;
+
+ @Uint64()
+ int a112;
+
+ @Uint64()
+ int a113;
+
+ @Uint64()
+ int a114;
+
+ @Uint64()
+ int a115;
+
+ @Uint64()
+ int a116;
+
+ @Uint64()
+ int a117;
+
+ @Uint64()
+ int a118;
+
+ @Uint64()
+ int a119;
+
+ @Uint64()
+ int a120;
+
+ @Uint64()
+ int a121;
+
+ @Uint64()
+ int a122;
+
+ @Uint64()
+ int a123;
+
+ @Uint64()
+ int a124;
+
+ @Uint64()
+ int a125;
+
+ @Uint64()
+ int a126;
+
+ @Uint64()
+ int a127;
+
+ String toString() =>
+ "(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9}, ${a10}, ${a11}, ${a12}, ${a13}, ${a14}, ${a15}, ${a16}, ${a17}, ${a18}, ${a19}, ${a20}, ${a21}, ${a22}, ${a23}, ${a24}, ${a25}, ${a26}, ${a27}, ${a28}, ${a29}, ${a30}, ${a31}, ${a32}, ${a33}, ${a34}, ${a35}, ${a36}, ${a37}, ${a38}, ${a39}, ${a40}, ${a41}, ${a42}, ${a43}, ${a44}, ${a45}, ${a46}, ${a47}, ${a48}, ${a49}, ${a50}, ${a51}, ${a52}, ${a53}, ${a54}, ${a55}, ${a56}, ${a57}, ${a58}, ${a59}, ${a60}, ${a61}, ${a62}, ${a63}, ${a64}, ${a65}, ${a66}, ${a67}, ${a68}, ${a69}, ${a70}, ${a71}, ${a72}, ${a73}, ${a74}, ${a75}, ${a76}, ${a77}, ${a78}, ${a79}, ${a80}, ${a81}, ${a82}, ${a83}, ${a84}, ${a85}, ${a86}, ${a87}, ${a88}, ${a89}, ${a90}, ${a91}, ${a92}, ${a93}, ${a94}, ${a95}, ${a96}, ${a97}, ${a98}, ${a99}, ${a100}, ${a101}, ${a102}, ${a103}, ${a104}, ${a105}, ${a106}, ${a107}, ${a108}, ${a109}, ${a110}, ${a111}, ${a112}, ${a113}, ${a114}, ${a115}, ${a116}, ${a117}, ${a118}, ${a119}, ${a120}, ${a121}, ${a122}, ${a123}, ${a124}, ${a125}, ${a126}, ${a127})";
+}
+
+class StructAlignmentInt16 extends Struct {
+ @Int8()
+ int a0;
+
+ @Int16()
+ int a1;
+
+ @Int8()
+ int a2;
+
+ String toString() => "(${a0}, ${a1}, ${a2})";
+}
+
+class StructAlignmentInt32 extends Struct {
+ @Int8()
+ int a0;
+
+ @Int32()
+ int a1;
+
+ @Int8()
+ int a2;
+
+ String toString() => "(${a0}, ${a1}, ${a2})";
+}
+
+class StructAlignmentInt64 extends Struct {
+ @Int8()
+ int a0;
+
+ @Int64()
+ int a1;
+
+ @Int8()
+ int a2;
+
+ String toString() => "(${a0}, ${a1}, ${a2})";
+}
+
+final passStruct1ByteIntx10 = ffiTestFunctions.lookupFunction<
+ Int64 Function(
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt),
+ int Function(
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt,
+ Struct1ByteInt)>("PassStruct1ByteIntx10");
+
+/// Smallest struct with data.
+/// 10 struct arguments will exhaust available registers.
+void testPassStruct1ByteIntx10() {
+ Struct1ByteInt a0 = allocate<Struct1ByteInt>().ref;
+ Struct1ByteInt a1 = allocate<Struct1ByteInt>().ref;
+ Struct1ByteInt a2 = allocate<Struct1ByteInt>().ref;
+ Struct1ByteInt a3 = allocate<Struct1ByteInt>().ref;
+ Struct1ByteInt a4 = allocate<Struct1ByteInt>().ref;
+ Struct1ByteInt a5 = allocate<Struct1ByteInt>().ref;
+ Struct1ByteInt a6 = allocate<Struct1ByteInt>().ref;
+ Struct1ByteInt a7 = allocate<Struct1ByteInt>().ref;
+ Struct1ByteInt a8 = allocate<Struct1ByteInt>().ref;
+ Struct1ByteInt a9 = allocate<Struct1ByteInt>().ref;
+
+ a0.a0 = -1;
+ a1.a0 = 2;
+ a2.a0 = -3;
+ a3.a0 = 4;
+ a4.a0 = -5;
+ a5.a0 = 6;
+ a6.a0 = -7;
+ a7.a0 = 8;
+ a8.a0 = -9;
+ a9.a0 = 10;
+
+ final result = passStruct1ByteIntx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.equals(5, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct3BytesIntx10 = ffiTestFunctions.lookupFunction<
+ Int64 Function(
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt),
+ int Function(
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt,
+ Struct3BytesInt)>("PassStruct3BytesIntx10");
+
+/// Not a multiple of word size, not a power of two.
+/// 10 struct arguments will exhaust available registers.
+void testPassStruct3BytesIntx10() {
+ Struct3BytesInt a0 = allocate<Struct3BytesInt>().ref;
+ Struct3BytesInt a1 = allocate<Struct3BytesInt>().ref;
+ Struct3BytesInt a2 = allocate<Struct3BytesInt>().ref;
+ Struct3BytesInt a3 = allocate<Struct3BytesInt>().ref;
+ Struct3BytesInt a4 = allocate<Struct3BytesInt>().ref;
+ Struct3BytesInt a5 = allocate<Struct3BytesInt>().ref;
+ Struct3BytesInt a6 = allocate<Struct3BytesInt>().ref;
+ Struct3BytesInt a7 = allocate<Struct3BytesInt>().ref;
+ Struct3BytesInt a8 = allocate<Struct3BytesInt>().ref;
+ Struct3BytesInt a9 = allocate<Struct3BytesInt>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a1.a0 = -3;
+ a1.a1 = 4;
+ a2.a0 = -5;
+ a2.a1 = 6;
+ a3.a0 = -7;
+ a3.a1 = 8;
+ a4.a0 = -9;
+ a4.a1 = 10;
+ a5.a0 = -11;
+ a5.a1 = 12;
+ a6.a0 = -13;
+ a6.a1 = 14;
+ a7.a0 = -15;
+ a7.a1 = 16;
+ a8.a0 = -17;
+ a8.a1 = 18;
+ a9.a0 = -19;
+ a9.a1 = 20;
+
+ final result = passStruct3BytesIntx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.equals(10, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct4BytesHomogeneousInt16x10 = ffiTestFunctions.lookupFunction<
+ Int64 Function(
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16),
+ int Function(
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16,
+ Struct4BytesHomogeneousInt16)>("PassStruct4BytesHomogeneousInt16x10");
+
+/// Exactly word size on 32-bit architectures.
+/// 10 struct arguments will exhaust available registers.
+void testPassStruct4BytesHomogeneousInt16x10() {
+ Struct4BytesHomogeneousInt16 a0 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+ Struct4BytesHomogeneousInt16 a1 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+ Struct4BytesHomogeneousInt16 a2 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+ Struct4BytesHomogeneousInt16 a3 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+ Struct4BytesHomogeneousInt16 a4 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+ Struct4BytesHomogeneousInt16 a5 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+ Struct4BytesHomogeneousInt16 a6 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+ Struct4BytesHomogeneousInt16 a7 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+ Struct4BytesHomogeneousInt16 a8 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+ Struct4BytesHomogeneousInt16 a9 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a1.a0 = -3;
+ a1.a1 = 4;
+ a2.a0 = -5;
+ a2.a1 = 6;
+ a3.a0 = -7;
+ a3.a1 = 8;
+ a4.a0 = -9;
+ a4.a1 = 10;
+ a5.a0 = -11;
+ a5.a1 = 12;
+ a6.a0 = -13;
+ a6.a1 = 14;
+ a7.a0 = -15;
+ a7.a1 = 16;
+ a8.a0 = -17;
+ a8.a1 = 18;
+ a9.a0 = -19;
+ a9.a1 = 20;
+
+ final result = passStruct4BytesHomogeneousInt16x10(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.equals(10, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct7BytesIntx10 = ffiTestFunctions.lookupFunction<
+ Int64 Function(
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt),
+ int Function(
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt,
+ Struct7BytesInt)>("PassStruct7BytesIntx10");
+
+/// Sub word size on 64 bit architectures.
+/// 10 struct arguments will exhaust available registers.
+void testPassStruct7BytesIntx10() {
+ Struct7BytesInt a0 = allocate<Struct7BytesInt>().ref;
+ Struct7BytesInt a1 = allocate<Struct7BytesInt>().ref;
+ Struct7BytesInt a2 = allocate<Struct7BytesInt>().ref;
+ Struct7BytesInt a3 = allocate<Struct7BytesInt>().ref;
+ Struct7BytesInt a4 = allocate<Struct7BytesInt>().ref;
+ Struct7BytesInt a5 = allocate<Struct7BytesInt>().ref;
+ Struct7BytesInt a6 = allocate<Struct7BytesInt>().ref;
+ Struct7BytesInt a7 = allocate<Struct7BytesInt>().ref;
+ Struct7BytesInt a8 = allocate<Struct7BytesInt>().ref;
+ Struct7BytesInt a9 = allocate<Struct7BytesInt>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+ a1.a0 = 4;
+ a1.a1 = -5;
+ a1.a2 = 6;
+ a2.a0 = -7;
+ a2.a1 = 8;
+ a2.a2 = -9;
+ a3.a0 = 10;
+ a3.a1 = -11;
+ a3.a2 = 12;
+ a4.a0 = -13;
+ a4.a1 = 14;
+ a4.a2 = -15;
+ a5.a0 = 16;
+ a5.a1 = -17;
+ a5.a2 = 18;
+ a6.a0 = -19;
+ a6.a1 = 20;
+ a6.a2 = -21;
+ a7.a0 = 22;
+ a7.a1 = -23;
+ a7.a2 = 24;
+ a8.a0 = -25;
+ a8.a1 = 26;
+ a8.a2 = -27;
+ a9.a0 = 28;
+ a9.a1 = -29;
+ a9.a2 = 30;
+
+ final result = passStruct7BytesIntx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.equals(15, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct8BytesIntx10 = ffiTestFunctions.lookupFunction<
+ Int64 Function(
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt),
+ int Function(
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt,
+ Struct8BytesInt)>("PassStruct8BytesIntx10");
+
+/// Exactly word size struct on 64bit architectures.
+/// 10 struct arguments will exhaust available registers.
+void testPassStruct8BytesIntx10() {
+ Struct8BytesInt a0 = allocate<Struct8BytesInt>().ref;
+ Struct8BytesInt a1 = allocate<Struct8BytesInt>().ref;
+ Struct8BytesInt a2 = allocate<Struct8BytesInt>().ref;
+ Struct8BytesInt a3 = allocate<Struct8BytesInt>().ref;
+ Struct8BytesInt a4 = allocate<Struct8BytesInt>().ref;
+ Struct8BytesInt a5 = allocate<Struct8BytesInt>().ref;
+ Struct8BytesInt a6 = allocate<Struct8BytesInt>().ref;
+ Struct8BytesInt a7 = allocate<Struct8BytesInt>().ref;
+ Struct8BytesInt a8 = allocate<Struct8BytesInt>().ref;
+ Struct8BytesInt a9 = allocate<Struct8BytesInt>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+ a1.a0 = 4;
+ a1.a1 = -5;
+ a1.a2 = 6;
+ a2.a0 = -7;
+ a2.a1 = 8;
+ a2.a2 = -9;
+ a3.a0 = 10;
+ a3.a1 = -11;
+ a3.a2 = 12;
+ a4.a0 = -13;
+ a4.a1 = 14;
+ a4.a2 = -15;
+ a5.a0 = 16;
+ a5.a1 = -17;
+ a5.a2 = 18;
+ a6.a0 = -19;
+ a6.a1 = 20;
+ a6.a2 = -21;
+ a7.a0 = 22;
+ a7.a1 = -23;
+ a7.a2 = 24;
+ a8.a0 = -25;
+ a8.a1 = 26;
+ a8.a2 = -27;
+ a9.a0 = 28;
+ a9.a1 = -29;
+ a9.a2 = 30;
+
+ final result = passStruct8BytesIntx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.equals(15, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct8BytesHomogeneousFloatx10 = ffiTestFunctions.lookupFunction<
+ Float Function(
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat),
+ double Function(
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat,
+ Struct8BytesHomogeneousFloat)>("PassStruct8BytesHomogeneousFloatx10");
+
+/// Arguments passed in FP registers as long as they fit.
+/// 10 struct arguments will exhaust available registers.
+void testPassStruct8BytesHomogeneousFloatx10() {
+ Struct8BytesHomogeneousFloat a0 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+ Struct8BytesHomogeneousFloat a1 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+ Struct8BytesHomogeneousFloat a2 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+ Struct8BytesHomogeneousFloat a3 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+ Struct8BytesHomogeneousFloat a4 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+ Struct8BytesHomogeneousFloat a5 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+ Struct8BytesHomogeneousFloat a6 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+ Struct8BytesHomogeneousFloat a7 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+ Struct8BytesHomogeneousFloat a8 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+ Struct8BytesHomogeneousFloat a9 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a1.a0 = -3.0;
+ a1.a1 = 4.0;
+ a2.a0 = -5.0;
+ a2.a1 = 6.0;
+ a3.a0 = -7.0;
+ a3.a1 = 8.0;
+ a4.a0 = -9.0;
+ a4.a1 = 10.0;
+ a5.a0 = -11.0;
+ a5.a1 = 12.0;
+ a6.a0 = -13.0;
+ a6.a1 = 14.0;
+ a7.a0 = -15.0;
+ a7.a1 = 16.0;
+ a8.a0 = -17.0;
+ a8.a1 = 18.0;
+ a9.a0 = -19.0;
+ a9.a1 = 20.0;
+
+ final result = passStruct8BytesHomogeneousFloatx10(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.approxEquals(10.0, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct8BytesMixedx10 = ffiTestFunctions.lookupFunction<
+ Float Function(
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed),
+ double Function(
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed,
+ Struct8BytesMixed)>("PassStruct8BytesMixedx10");
+
+/// On x64, arguments go in int registers because it is not only float.
+/// 10 struct arguments will exhaust available registers.
+void testPassStruct8BytesMixedx10() {
+ Struct8BytesMixed a0 = allocate<Struct8BytesMixed>().ref;
+ Struct8BytesMixed a1 = allocate<Struct8BytesMixed>().ref;
+ Struct8BytesMixed a2 = allocate<Struct8BytesMixed>().ref;
+ Struct8BytesMixed a3 = allocate<Struct8BytesMixed>().ref;
+ Struct8BytesMixed a4 = allocate<Struct8BytesMixed>().ref;
+ Struct8BytesMixed a5 = allocate<Struct8BytesMixed>().ref;
+ Struct8BytesMixed a6 = allocate<Struct8BytesMixed>().ref;
+ Struct8BytesMixed a7 = allocate<Struct8BytesMixed>().ref;
+ Struct8BytesMixed a8 = allocate<Struct8BytesMixed>().ref;
+ Struct8BytesMixed a9 = allocate<Struct8BytesMixed>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2;
+ a0.a2 = -3;
+ a1.a0 = 4.0;
+ a1.a1 = -5;
+ a1.a2 = 6;
+ a2.a0 = -7.0;
+ a2.a1 = 8;
+ a2.a2 = -9;
+ a3.a0 = 10.0;
+ a3.a1 = -11;
+ a3.a2 = 12;
+ a4.a0 = -13.0;
+ a4.a1 = 14;
+ a4.a2 = -15;
+ a5.a0 = 16.0;
+ a5.a1 = -17;
+ a5.a2 = 18;
+ a6.a0 = -19.0;
+ a6.a1 = 20;
+ a6.a2 = -21;
+ a7.a0 = 22.0;
+ a7.a1 = -23;
+ a7.a2 = 24;
+ a8.a0 = -25.0;
+ a8.a1 = 26;
+ a8.a2 = -27;
+ a9.a0 = 28.0;
+ a9.a1 = -29;
+ a9.a2 = 30;
+
+ final result =
+ passStruct8BytesMixedx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.approxEquals(15.0, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct9BytesIntx10 = ffiTestFunctions.lookupFunction<
+ Int64 Function(
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt),
+ int Function(
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt,
+ Struct9BytesInt)>("PassStruct9BytesIntx10");
+
+/// Argument is a single byte over a multiple of word size.
+/// 10 struct arguments will exhaust available registers.
+/// Tests upper bytes in the integer registers that are partly filled.
+/// Tests stack alignment of non word size stack arguments.
+void testPassStruct9BytesIntx10() {
+ Struct9BytesInt a0 = allocate<Struct9BytesInt>().ref;
+ Struct9BytesInt a1 = allocate<Struct9BytesInt>().ref;
+ Struct9BytesInt a2 = allocate<Struct9BytesInt>().ref;
+ Struct9BytesInt a3 = allocate<Struct9BytesInt>().ref;
+ Struct9BytesInt a4 = allocate<Struct9BytesInt>().ref;
+ Struct9BytesInt a5 = allocate<Struct9BytesInt>().ref;
+ Struct9BytesInt a6 = allocate<Struct9BytesInt>().ref;
+ Struct9BytesInt a7 = allocate<Struct9BytesInt>().ref;
+ Struct9BytesInt a8 = allocate<Struct9BytesInt>().ref;
+ Struct9BytesInt a9 = allocate<Struct9BytesInt>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a1.a0 = -3;
+ a1.a1 = 4;
+ a2.a0 = -5;
+ a2.a1 = 6;
+ a3.a0 = -7;
+ a3.a1 = 8;
+ a4.a0 = -9;
+ a4.a1 = 10;
+ a5.a0 = -11;
+ a5.a1 = 12;
+ a6.a0 = -13;
+ a6.a1 = 14;
+ a7.a0 = -15;
+ a7.a1 = 16;
+ a8.a0 = -17;
+ a8.a1 = 18;
+ a9.a0 = -19;
+ a9.a1 = 20;
+
+ final result = passStruct9BytesIntx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.equals(10, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct9BytesHomogeneousUint82x10 = ffiTestFunctions.lookupFunction<
+ Int64 Function(
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82),
+ int Function(
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82,
+ Struct9BytesHomogeneousUint82)>("PassStruct9BytesHomogeneousUint82x10");
+
+/// Argument is a single byte over a multiple of word size.
+/// 10 struct arguments will exhaust available registers.
+/// Struct only has 1-byte aligned fields to test struct alignment itself.
+///
+void testPassStruct9BytesHomogeneousUint82x10() {
+ Struct9BytesHomogeneousUint82 a0 =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+ Struct9BytesHomogeneousUint82 a1 =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+ Struct9BytesHomogeneousUint82 a2 =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+ Struct9BytesHomogeneousUint82 a3 =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+ Struct9BytesHomogeneousUint82 a4 =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+ Struct9BytesHomogeneousUint82 a5 =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+ Struct9BytesHomogeneousUint82 a6 =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+ Struct9BytesHomogeneousUint82 a7 =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+ Struct9BytesHomogeneousUint82 a8 =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+ Struct9BytesHomogeneousUint82 a9 =
+ allocate<Struct9BytesHomogeneousUint82>().ref;
+
+ a0.a0 = 1;
+ a0.a1 = 2;
+ a0.a2 = 3;
+ a0.a3 = 4;
+ a0.a4 = 5;
+ a0.a5 = 6;
+ a0.a6 = 7;
+ a0.a7 = 8;
+ a0.a8 = 9;
+ a1.a0 = 10;
+ a1.a1 = 11;
+ a1.a2 = 12;
+ a1.a3 = 13;
+ a1.a4 = 14;
+ a1.a5 = 15;
+ a1.a6 = 16;
+ a1.a7 = 17;
+ a1.a8 = 18;
+ a2.a0 = 19;
+ a2.a1 = 20;
+ a2.a2 = 21;
+ a2.a3 = 22;
+ a2.a4 = 23;
+ a2.a5 = 24;
+ a2.a6 = 25;
+ a2.a7 = 26;
+ a2.a8 = 27;
+ a3.a0 = 28;
+ a3.a1 = 29;
+ a3.a2 = 30;
+ a3.a3 = 31;
+ a3.a4 = 32;
+ a3.a5 = 33;
+ a3.a6 = 34;
+ a3.a7 = 35;
+ a3.a8 = 36;
+ a4.a0 = 37;
+ a4.a1 = 38;
+ a4.a2 = 39;
+ a4.a3 = 40;
+ a4.a4 = 41;
+ a4.a5 = 42;
+ a4.a6 = 43;
+ a4.a7 = 44;
+ a4.a8 = 45;
+ a5.a0 = 46;
+ a5.a1 = 47;
+ a5.a2 = 48;
+ a5.a3 = 49;
+ a5.a4 = 50;
+ a5.a5 = 51;
+ a5.a6 = 52;
+ a5.a7 = 53;
+ a5.a8 = 54;
+ a6.a0 = 55;
+ a6.a1 = 56;
+ a6.a2 = 57;
+ a6.a3 = 58;
+ a6.a4 = 59;
+ a6.a5 = 60;
+ a6.a6 = 61;
+ a6.a7 = 62;
+ a6.a8 = 63;
+ a7.a0 = 64;
+ a7.a1 = 65;
+ a7.a2 = 66;
+ a7.a3 = 67;
+ a7.a4 = 68;
+ a7.a5 = 69;
+ a7.a6 = 70;
+ a7.a7 = 71;
+ a7.a8 = 72;
+ a8.a0 = 73;
+ a8.a1 = 74;
+ a8.a2 = 75;
+ a8.a3 = 76;
+ a8.a4 = 77;
+ a8.a5 = 78;
+ a8.a6 = 79;
+ a8.a7 = 80;
+ a8.a8 = 81;
+ a9.a0 = 82;
+ a9.a1 = 83;
+ a9.a2 = 84;
+ a9.a3 = 85;
+ a9.a4 = 86;
+ a9.a5 = 87;
+ a9.a6 = 88;
+ a9.a7 = 89;
+ a9.a8 = 90;
+
+ final result = passStruct9BytesHomogeneousUint82x10(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.equals(4095, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct12BytesHomogeneousFloatx6 = ffiTestFunctions.lookupFunction<
+ Float Function(
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat),
+ double Function(
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat,
+ Struct12BytesHomogeneousFloat)>("PassStruct12BytesHomogeneousFloatx6");
+
+/// Arguments in FPU registers on arm hardfp and arm64.
+/// Struct arguments will exhaust available registers, and leave some empty.
+/// The last argument is to test whether arguments are backfilled.
+void testPassStruct12BytesHomogeneousFloatx6() {
+ Struct12BytesHomogeneousFloat a0 =
+ allocate<Struct12BytesHomogeneousFloat>().ref;
+ Struct12BytesHomogeneousFloat a1 =
+ allocate<Struct12BytesHomogeneousFloat>().ref;
+ Struct12BytesHomogeneousFloat a2 =
+ allocate<Struct12BytesHomogeneousFloat>().ref;
+ Struct12BytesHomogeneousFloat a3 =
+ allocate<Struct12BytesHomogeneousFloat>().ref;
+ Struct12BytesHomogeneousFloat a4 =
+ allocate<Struct12BytesHomogeneousFloat>().ref;
+ Struct12BytesHomogeneousFloat a5 =
+ allocate<Struct12BytesHomogeneousFloat>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a0.a2 = -3.0;
+ a1.a0 = 4.0;
+ a1.a1 = -5.0;
+ a1.a2 = 6.0;
+ a2.a0 = -7.0;
+ a2.a1 = 8.0;
+ a2.a2 = -9.0;
+ a3.a0 = 10.0;
+ a3.a1 = -11.0;
+ a3.a2 = 12.0;
+ a4.a0 = -13.0;
+ a4.a1 = 14.0;
+ a4.a2 = -15.0;
+ a5.a0 = 16.0;
+ a5.a1 = -17.0;
+ a5.a2 = 18.0;
+
+ final result = passStruct12BytesHomogeneousFloatx6(a0, a1, a2, a3, a4, a5);
+
+ print("result = $result");
+
+ Expect.approxEquals(9.0, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+}
+
+final passStruct16BytesHomogeneousFloatx5 = ffiTestFunctions.lookupFunction<
+ Float Function(
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat),
+ double Function(
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat,
+ Struct16BytesHomogeneousFloat)>("PassStruct16BytesHomogeneousFloatx5");
+
+/// On Linux x64 argument is transferred on stack because it is over 16 bytes.
+/// Arguments in FPU registers on arm hardfp and arm64.
+/// 5 struct arguments will exhaust available registers.
+void testPassStruct16BytesHomogeneousFloatx5() {
+ Struct16BytesHomogeneousFloat a0 =
+ allocate<Struct16BytesHomogeneousFloat>().ref;
+ Struct16BytesHomogeneousFloat a1 =
+ allocate<Struct16BytesHomogeneousFloat>().ref;
+ Struct16BytesHomogeneousFloat a2 =
+ allocate<Struct16BytesHomogeneousFloat>().ref;
+ Struct16BytesHomogeneousFloat a3 =
+ allocate<Struct16BytesHomogeneousFloat>().ref;
+ Struct16BytesHomogeneousFloat a4 =
+ allocate<Struct16BytesHomogeneousFloat>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a0.a2 = -3.0;
+ a0.a3 = 4.0;
+ a1.a0 = -5.0;
+ a1.a1 = 6.0;
+ a1.a2 = -7.0;
+ a1.a3 = 8.0;
+ a2.a0 = -9.0;
+ a2.a1 = 10.0;
+ a2.a2 = -11.0;
+ a2.a3 = 12.0;
+ a3.a0 = -13.0;
+ a3.a1 = 14.0;
+ a3.a2 = -15.0;
+ a3.a3 = 16.0;
+ a4.a0 = -17.0;
+ a4.a1 = 18.0;
+ a4.a2 = -19.0;
+ a4.a3 = 20.0;
+
+ final result = passStruct16BytesHomogeneousFloatx5(a0, a1, a2, a3, a4);
+
+ print("result = $result");
+
+ Expect.approxEquals(10.0, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+}
+
+final passStruct16BytesMixedx10 = ffiTestFunctions.lookupFunction<
+ Double Function(
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed),
+ double Function(
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed)>("PassStruct16BytesMixedx10");
+
+/// On x64, arguments are split over FP and int registers.
+/// On x64, it will exhaust the integer registers with the 6th argument.
+/// The rest goes on the stack.
+/// On arm, arguments are 8 byte aligned.
+void testPassStruct16BytesMixedx10() {
+ Struct16BytesMixed a0 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a1 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a2 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a3 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a4 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a5 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a6 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a7 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a8 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a9 = allocate<Struct16BytesMixed>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2;
+ a1.a0 = -3.0;
+ a1.a1 = 4;
+ a2.a0 = -5.0;
+ a2.a1 = 6;
+ a3.a0 = -7.0;
+ a3.a1 = 8;
+ a4.a0 = -9.0;
+ a4.a1 = 10;
+ a5.a0 = -11.0;
+ a5.a1 = 12;
+ a6.a0 = -13.0;
+ a6.a1 = 14;
+ a7.a0 = -15.0;
+ a7.a1 = 16;
+ a8.a0 = -17.0;
+ a8.a1 = 18;
+ a9.a0 = -19.0;
+ a9.a1 = 20;
+
+ final result =
+ passStruct16BytesMixedx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.approxEquals(10.0, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct16BytesMixed2x10 = ffiTestFunctions.lookupFunction<
+ Float Function(
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2),
+ double Function(
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2,
+ Struct16BytesMixed2)>("PassStruct16BytesMixed2x10");
+
+/// On x64, arguments are split over FP and int registers.
+/// On x64, it will exhaust the integer registers with the 6th argument.
+/// The rest goes on the stack.
+/// On arm, arguments are 4 byte aligned.
+void testPassStruct16BytesMixed2x10() {
+ Struct16BytesMixed2 a0 = allocate<Struct16BytesMixed2>().ref;
+ Struct16BytesMixed2 a1 = allocate<Struct16BytesMixed2>().ref;
+ Struct16BytesMixed2 a2 = allocate<Struct16BytesMixed2>().ref;
+ Struct16BytesMixed2 a3 = allocate<Struct16BytesMixed2>().ref;
+ Struct16BytesMixed2 a4 = allocate<Struct16BytesMixed2>().ref;
+ Struct16BytesMixed2 a5 = allocate<Struct16BytesMixed2>().ref;
+ Struct16BytesMixed2 a6 = allocate<Struct16BytesMixed2>().ref;
+ Struct16BytesMixed2 a7 = allocate<Struct16BytesMixed2>().ref;
+ Struct16BytesMixed2 a8 = allocate<Struct16BytesMixed2>().ref;
+ Struct16BytesMixed2 a9 = allocate<Struct16BytesMixed2>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a0.a2 = -3.0;
+ a0.a3 = 4;
+ a1.a0 = -5.0;
+ a1.a1 = 6.0;
+ a1.a2 = -7.0;
+ a1.a3 = 8;
+ a2.a0 = -9.0;
+ a2.a1 = 10.0;
+ a2.a2 = -11.0;
+ a2.a3 = 12;
+ a3.a0 = -13.0;
+ a3.a1 = 14.0;
+ a3.a2 = -15.0;
+ a3.a3 = 16;
+ a4.a0 = -17.0;
+ a4.a1 = 18.0;
+ a4.a2 = -19.0;
+ a4.a3 = 20;
+ a5.a0 = -21.0;
+ a5.a1 = 22.0;
+ a5.a2 = -23.0;
+ a5.a3 = 24;
+ a6.a0 = -25.0;
+ a6.a1 = 26.0;
+ a6.a2 = -27.0;
+ a6.a3 = 28;
+ a7.a0 = -29.0;
+ a7.a1 = 30.0;
+ a7.a2 = -31.0;
+ a7.a3 = 32;
+ a8.a0 = -33.0;
+ a8.a1 = 34.0;
+ a8.a2 = -35.0;
+ a8.a3 = 36;
+ a9.a0 = -37.0;
+ a9.a1 = 38.0;
+ a9.a2 = -39.0;
+ a9.a3 = 40;
+
+ final result =
+ passStruct16BytesMixed2x10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.approxEquals(20.0, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct17BytesIntx10 = ffiTestFunctions.lookupFunction<
+ Int64 Function(
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt),
+ int Function(
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt,
+ Struct17BytesInt)>("PassStruct17BytesIntx10");
+
+/// Arguments are passed as pointer to copy on arm64.
+/// Tests that the memory allocated for copies are rounded up to word size.
+void testPassStruct17BytesIntx10() {
+ Struct17BytesInt a0 = allocate<Struct17BytesInt>().ref;
+ Struct17BytesInt a1 = allocate<Struct17BytesInt>().ref;
+ Struct17BytesInt a2 = allocate<Struct17BytesInt>().ref;
+ Struct17BytesInt a3 = allocate<Struct17BytesInt>().ref;
+ Struct17BytesInt a4 = allocate<Struct17BytesInt>().ref;
+ Struct17BytesInt a5 = allocate<Struct17BytesInt>().ref;
+ Struct17BytesInt a6 = allocate<Struct17BytesInt>().ref;
+ Struct17BytesInt a7 = allocate<Struct17BytesInt>().ref;
+ Struct17BytesInt a8 = allocate<Struct17BytesInt>().ref;
+ Struct17BytesInt a9 = allocate<Struct17BytesInt>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+ a1.a0 = 4;
+ a1.a1 = -5;
+ a1.a2 = 6;
+ a2.a0 = -7;
+ a2.a1 = 8;
+ a2.a2 = -9;
+ a3.a0 = 10;
+ a3.a1 = -11;
+ a3.a2 = 12;
+ a4.a0 = -13;
+ a4.a1 = 14;
+ a4.a2 = -15;
+ a5.a0 = 16;
+ a5.a1 = -17;
+ a5.a2 = 18;
+ a6.a0 = -19;
+ a6.a1 = 20;
+ a6.a2 = -21;
+ a7.a0 = 22;
+ a7.a1 = -23;
+ a7.a2 = 24;
+ a8.a0 = -25;
+ a8.a1 = 26;
+ a8.a2 = -27;
+ a9.a0 = 28;
+ a9.a1 = -29;
+ a9.a2 = 30;
+
+ final result =
+ passStruct17BytesIntx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.equals(15, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct19BytesHomogeneousUint8x10 = ffiTestFunctions.lookupFunction<
+ Int64 Function(
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8),
+ int Function(
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8,
+ Struct19BytesHomogeneousUint8)>("PassStruct19BytesHomogeneousUint8x10");
+
+/// The minimum alignment of this struct is only 1 byte based on its fields.
+/// Test that the memory backing these structs is extended to the right size.
+///
+void testPassStruct19BytesHomogeneousUint8x10() {
+ Struct19BytesHomogeneousUint8 a0 =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+ Struct19BytesHomogeneousUint8 a1 =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+ Struct19BytesHomogeneousUint8 a2 =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+ Struct19BytesHomogeneousUint8 a3 =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+ Struct19BytesHomogeneousUint8 a4 =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+ Struct19BytesHomogeneousUint8 a5 =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+ Struct19BytesHomogeneousUint8 a6 =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+ Struct19BytesHomogeneousUint8 a7 =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+ Struct19BytesHomogeneousUint8 a8 =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+ Struct19BytesHomogeneousUint8 a9 =
+ allocate<Struct19BytesHomogeneousUint8>().ref;
+
+ a0.a0 = 1;
+ a0.a1 = 2;
+ a0.a2 = 3;
+ a0.a3 = 4;
+ a0.a4 = 5;
+ a0.a5 = 6;
+ a0.a6 = 7;
+ a0.a7 = 8;
+ a0.a8 = 9;
+ a0.a9 = 10;
+ a0.a10 = 11;
+ a0.a11 = 12;
+ a0.a12 = 13;
+ a0.a13 = 14;
+ a0.a14 = 15;
+ a0.a15 = 16;
+ a0.a16 = 17;
+ a0.a17 = 18;
+ a0.a18 = 19;
+ a1.a0 = 20;
+ a1.a1 = 21;
+ a1.a2 = 22;
+ a1.a3 = 23;
+ a1.a4 = 24;
+ a1.a5 = 25;
+ a1.a6 = 26;
+ a1.a7 = 27;
+ a1.a8 = 28;
+ a1.a9 = 29;
+ a1.a10 = 30;
+ a1.a11 = 31;
+ a1.a12 = 32;
+ a1.a13 = 33;
+ a1.a14 = 34;
+ a1.a15 = 35;
+ a1.a16 = 36;
+ a1.a17 = 37;
+ a1.a18 = 38;
+ a2.a0 = 39;
+ a2.a1 = 40;
+ a2.a2 = 41;
+ a2.a3 = 42;
+ a2.a4 = 43;
+ a2.a5 = 44;
+ a2.a6 = 45;
+ a2.a7 = 46;
+ a2.a8 = 47;
+ a2.a9 = 48;
+ a2.a10 = 49;
+ a2.a11 = 50;
+ a2.a12 = 51;
+ a2.a13 = 52;
+ a2.a14 = 53;
+ a2.a15 = 54;
+ a2.a16 = 55;
+ a2.a17 = 56;
+ a2.a18 = 57;
+ a3.a0 = 58;
+ a3.a1 = 59;
+ a3.a2 = 60;
+ a3.a3 = 61;
+ a3.a4 = 62;
+ a3.a5 = 63;
+ a3.a6 = 64;
+ a3.a7 = 65;
+ a3.a8 = 66;
+ a3.a9 = 67;
+ a3.a10 = 68;
+ a3.a11 = 69;
+ a3.a12 = 70;
+ a3.a13 = 71;
+ a3.a14 = 72;
+ a3.a15 = 73;
+ a3.a16 = 74;
+ a3.a17 = 75;
+ a3.a18 = 76;
+ a4.a0 = 77;
+ a4.a1 = 78;
+ a4.a2 = 79;
+ a4.a3 = 80;
+ a4.a4 = 81;
+ a4.a5 = 82;
+ a4.a6 = 83;
+ a4.a7 = 84;
+ a4.a8 = 85;
+ a4.a9 = 86;
+ a4.a10 = 87;
+ a4.a11 = 88;
+ a4.a12 = 89;
+ a4.a13 = 90;
+ a4.a14 = 91;
+ a4.a15 = 92;
+ a4.a16 = 93;
+ a4.a17 = 94;
+ a4.a18 = 95;
+ a5.a0 = 96;
+ a5.a1 = 97;
+ a5.a2 = 98;
+ a5.a3 = 99;
+ a5.a4 = 100;
+ a5.a5 = 101;
+ a5.a6 = 102;
+ a5.a7 = 103;
+ a5.a8 = 104;
+ a5.a9 = 105;
+ a5.a10 = 106;
+ a5.a11 = 107;
+ a5.a12 = 108;
+ a5.a13 = 109;
+ a5.a14 = 110;
+ a5.a15 = 111;
+ a5.a16 = 112;
+ a5.a17 = 113;
+ a5.a18 = 114;
+ a6.a0 = 115;
+ a6.a1 = 116;
+ a6.a2 = 117;
+ a6.a3 = 118;
+ a6.a4 = 119;
+ a6.a5 = 120;
+ a6.a6 = 121;
+ a6.a7 = 122;
+ a6.a8 = 123;
+ a6.a9 = 124;
+ a6.a10 = 125;
+ a6.a11 = 126;
+ a6.a12 = 127;
+ a6.a13 = 128;
+ a6.a14 = 129;
+ a6.a15 = 130;
+ a6.a16 = 131;
+ a6.a17 = 132;
+ a6.a18 = 133;
+ a7.a0 = 134;
+ a7.a1 = 135;
+ a7.a2 = 136;
+ a7.a3 = 137;
+ a7.a4 = 138;
+ a7.a5 = 139;
+ a7.a6 = 140;
+ a7.a7 = 141;
+ a7.a8 = 142;
+ a7.a9 = 143;
+ a7.a10 = 144;
+ a7.a11 = 145;
+ a7.a12 = 146;
+ a7.a13 = 147;
+ a7.a14 = 148;
+ a7.a15 = 149;
+ a7.a16 = 150;
+ a7.a17 = 151;
+ a7.a18 = 152;
+ a8.a0 = 153;
+ a8.a1 = 154;
+ a8.a2 = 155;
+ a8.a3 = 156;
+ a8.a4 = 157;
+ a8.a5 = 158;
+ a8.a6 = 159;
+ a8.a7 = 160;
+ a8.a8 = 161;
+ a8.a9 = 162;
+ a8.a10 = 163;
+ a8.a11 = 164;
+ a8.a12 = 165;
+ a8.a13 = 166;
+ a8.a14 = 167;
+ a8.a15 = 168;
+ a8.a16 = 169;
+ a8.a17 = 170;
+ a8.a18 = 171;
+ a9.a0 = 172;
+ a9.a1 = 173;
+ a9.a2 = 174;
+ a9.a3 = 175;
+ a9.a4 = 176;
+ a9.a5 = 177;
+ a9.a6 = 178;
+ a9.a7 = 179;
+ a9.a8 = 180;
+ a9.a9 = 181;
+ a9.a10 = 182;
+ a9.a11 = 183;
+ a9.a12 = 184;
+ a9.a13 = 185;
+ a9.a14 = 186;
+ a9.a15 = 187;
+ a9.a16 = 188;
+ a9.a17 = 189;
+ a9.a18 = 190;
+
+ final result = passStruct19BytesHomogeneousUint8x10(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.equals(18145, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct20BytesHomogeneousInt32x10 = ffiTestFunctions.lookupFunction<
+ Int32 Function(
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32),
+ int Function(
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32,
+ Struct20BytesHomogeneousInt32)>("PassStruct20BytesHomogeneousInt32x10");
+
+/// Argument too big to go into integer registers on arm64.
+/// The arguments are passed as pointers to copies.
+/// The amount of arguments exhausts the number of integer registers, such that
+/// pointers to copies are also passed on the stack.
+void testPassStruct20BytesHomogeneousInt32x10() {
+ Struct20BytesHomogeneousInt32 a0 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+ Struct20BytesHomogeneousInt32 a1 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+ Struct20BytesHomogeneousInt32 a2 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+ Struct20BytesHomogeneousInt32 a3 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+ Struct20BytesHomogeneousInt32 a4 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+ Struct20BytesHomogeneousInt32 a5 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+ Struct20BytesHomogeneousInt32 a6 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+ Struct20BytesHomogeneousInt32 a7 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+ Struct20BytesHomogeneousInt32 a8 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+ Struct20BytesHomogeneousInt32 a9 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+ a0.a3 = 4;
+ a0.a4 = -5;
+ a1.a0 = 6;
+ a1.a1 = -7;
+ a1.a2 = 8;
+ a1.a3 = -9;
+ a1.a4 = 10;
+ a2.a0 = -11;
+ a2.a1 = 12;
+ a2.a2 = -13;
+ a2.a3 = 14;
+ a2.a4 = -15;
+ a3.a0 = 16;
+ a3.a1 = -17;
+ a3.a2 = 18;
+ a3.a3 = -19;
+ a3.a4 = 20;
+ a4.a0 = -21;
+ a4.a1 = 22;
+ a4.a2 = -23;
+ a4.a3 = 24;
+ a4.a4 = -25;
+ a5.a0 = 26;
+ a5.a1 = -27;
+ a5.a2 = 28;
+ a5.a3 = -29;
+ a5.a4 = 30;
+ a6.a0 = -31;
+ a6.a1 = 32;
+ a6.a2 = -33;
+ a6.a3 = 34;
+ a6.a4 = -35;
+ a7.a0 = 36;
+ a7.a1 = -37;
+ a7.a2 = 38;
+ a7.a3 = -39;
+ a7.a4 = 40;
+ a8.a0 = -41;
+ a8.a1 = 42;
+ a8.a2 = -43;
+ a8.a3 = 44;
+ a8.a4 = -45;
+ a9.a0 = 46;
+ a9.a1 = -47;
+ a9.a2 = 48;
+ a9.a3 = -49;
+ a9.a4 = 50;
+
+ final result = passStruct20BytesHomogeneousInt32x10(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+ print("result = $result");
+
+ Expect.equals(25, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passStruct20BytesHomogeneousFloat = ffiTestFunctions.lookupFunction<
+ Float Function(Struct20BytesHomogeneousFloat),
+ double Function(
+ Struct20BytesHomogeneousFloat)>("PassStruct20BytesHomogeneousFloat");
+
+/// Argument too big to go into FPU registers in hardfp and arm64.
+void testPassStruct20BytesHomogeneousFloat() {
+ Struct20BytesHomogeneousFloat a0 =
+ allocate<Struct20BytesHomogeneousFloat>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a0.a2 = -3.0;
+ a0.a3 = 4.0;
+ a0.a4 = -5.0;
+
+ final result = passStruct20BytesHomogeneousFloat(a0);
+
+ print("result = $result");
+
+ Expect.approxEquals(-3.0, result);
+
+ free(a0.addressOf);
+}
+
+final passStruct32BytesHomogeneousDoublex5 = ffiTestFunctions.lookupFunction<
+ Double Function(
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble),
+ double Function(
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble,
+ Struct32BytesHomogeneousDouble)>(
+ "PassStruct32BytesHomogeneousDoublex5");
+
+/// Arguments in FPU registers on arm64.
+/// 5 struct arguments will exhaust available registers.
+void testPassStruct32BytesHomogeneousDoublex5() {
+ Struct32BytesHomogeneousDouble a0 =
+ allocate<Struct32BytesHomogeneousDouble>().ref;
+ Struct32BytesHomogeneousDouble a1 =
+ allocate<Struct32BytesHomogeneousDouble>().ref;
+ Struct32BytesHomogeneousDouble a2 =
+ allocate<Struct32BytesHomogeneousDouble>().ref;
+ Struct32BytesHomogeneousDouble a3 =
+ allocate<Struct32BytesHomogeneousDouble>().ref;
+ Struct32BytesHomogeneousDouble a4 =
+ allocate<Struct32BytesHomogeneousDouble>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a0.a2 = -3.0;
+ a0.a3 = 4.0;
+ a1.a0 = -5.0;
+ a1.a1 = 6.0;
+ a1.a2 = -7.0;
+ a1.a3 = 8.0;
+ a2.a0 = -9.0;
+ a2.a1 = 10.0;
+ a2.a2 = -11.0;
+ a2.a3 = 12.0;
+ a3.a0 = -13.0;
+ a3.a1 = 14.0;
+ a3.a2 = -15.0;
+ a3.a3 = 16.0;
+ a4.a0 = -17.0;
+ a4.a1 = 18.0;
+ a4.a2 = -19.0;
+ a4.a3 = 20.0;
+
+ final result = passStruct32BytesHomogeneousDoublex5(a0, a1, a2, a3, a4);
+
+ print("result = $result");
+
+ Expect.approxEquals(10.0, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+ free(a3.addressOf);
+ free(a4.addressOf);
+}
+
+final passStruct40BytesHomogeneousDouble = ffiTestFunctions.lookupFunction<
+ Double Function(Struct40BytesHomogeneousDouble),
+ double Function(
+ Struct40BytesHomogeneousDouble)>("PassStruct40BytesHomogeneousDouble");
+
+/// Argument too big to go into FPU registers in arm64.
+void testPassStruct40BytesHomogeneousDouble() {
+ Struct40BytesHomogeneousDouble a0 =
+ allocate<Struct40BytesHomogeneousDouble>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a0.a2 = -3.0;
+ a0.a3 = 4.0;
+ a0.a4 = -5.0;
+
+ final result = passStruct40BytesHomogeneousDouble(a0);
+
+ print("result = $result");
+
+ Expect.approxEquals(-3.0, result);
+
+ free(a0.addressOf);
+}
+
+final passStruct1024BytesHomogeneousUint64 = ffiTestFunctions.lookupFunction<
+ Uint64 Function(Struct1024BytesHomogeneousUint64),
+ int Function(Struct1024BytesHomogeneousUint64)>(
+ "PassStruct1024BytesHomogeneousUint64");
+
+/// Test 1kb struct.
+void testPassStruct1024BytesHomogeneousUint64() {
+ Struct1024BytesHomogeneousUint64 a0 =
+ allocate<Struct1024BytesHomogeneousUint64>().ref;
+
+ a0.a0 = 1;
+ a0.a1 = 2;
+ a0.a2 = 3;
+ a0.a3 = 4;
+ a0.a4 = 5;
+ a0.a5 = 6;
+ a0.a6 = 7;
+ a0.a7 = 8;
+ a0.a8 = 9;
+ a0.a9 = 10;
+ a0.a10 = 11;
+ a0.a11 = 12;
+ a0.a12 = 13;
+ a0.a13 = 14;
+ a0.a14 = 15;
+ a0.a15 = 16;
+ a0.a16 = 17;
+ a0.a17 = 18;
+ a0.a18 = 19;
+ a0.a19 = 20;
+ a0.a20 = 21;
+ a0.a21 = 22;
+ a0.a22 = 23;
+ a0.a23 = 24;
+ a0.a24 = 25;
+ a0.a25 = 26;
+ a0.a26 = 27;
+ a0.a27 = 28;
+ a0.a28 = 29;
+ a0.a29 = 30;
+ a0.a30 = 31;
+ a0.a31 = 32;
+ a0.a32 = 33;
+ a0.a33 = 34;
+ a0.a34 = 35;
+ a0.a35 = 36;
+ a0.a36 = 37;
+ a0.a37 = 38;
+ a0.a38 = 39;
+ a0.a39 = 40;
+ a0.a40 = 41;
+ a0.a41 = 42;
+ a0.a42 = 43;
+ a0.a43 = 44;
+ a0.a44 = 45;
+ a0.a45 = 46;
+ a0.a46 = 47;
+ a0.a47 = 48;
+ a0.a48 = 49;
+ a0.a49 = 50;
+ a0.a50 = 51;
+ a0.a51 = 52;
+ a0.a52 = 53;
+ a0.a53 = 54;
+ a0.a54 = 55;
+ a0.a55 = 56;
+ a0.a56 = 57;
+ a0.a57 = 58;
+ a0.a58 = 59;
+ a0.a59 = 60;
+ a0.a60 = 61;
+ a0.a61 = 62;
+ a0.a62 = 63;
+ a0.a63 = 64;
+ a0.a64 = 65;
+ a0.a65 = 66;
+ a0.a66 = 67;
+ a0.a67 = 68;
+ a0.a68 = 69;
+ a0.a69 = 70;
+ a0.a70 = 71;
+ a0.a71 = 72;
+ a0.a72 = 73;
+ a0.a73 = 74;
+ a0.a74 = 75;
+ a0.a75 = 76;
+ a0.a76 = 77;
+ a0.a77 = 78;
+ a0.a78 = 79;
+ a0.a79 = 80;
+ a0.a80 = 81;
+ a0.a81 = 82;
+ a0.a82 = 83;
+ a0.a83 = 84;
+ a0.a84 = 85;
+ a0.a85 = 86;
+ a0.a86 = 87;
+ a0.a87 = 88;
+ a0.a88 = 89;
+ a0.a89 = 90;
+ a0.a90 = 91;
+ a0.a91 = 92;
+ a0.a92 = 93;
+ a0.a93 = 94;
+ a0.a94 = 95;
+ a0.a95 = 96;
+ a0.a96 = 97;
+ a0.a97 = 98;
+ a0.a98 = 99;
+ a0.a99 = 100;
+ a0.a100 = 101;
+ a0.a101 = 102;
+ a0.a102 = 103;
+ a0.a103 = 104;
+ a0.a104 = 105;
+ a0.a105 = 106;
+ a0.a106 = 107;
+ a0.a107 = 108;
+ a0.a108 = 109;
+ a0.a109 = 110;
+ a0.a110 = 111;
+ a0.a111 = 112;
+ a0.a112 = 113;
+ a0.a113 = 114;
+ a0.a114 = 115;
+ a0.a115 = 116;
+ a0.a116 = 117;
+ a0.a117 = 118;
+ a0.a118 = 119;
+ a0.a119 = 120;
+ a0.a120 = 121;
+ a0.a121 = 122;
+ a0.a122 = 123;
+ a0.a123 = 124;
+ a0.a124 = 125;
+ a0.a125 = 126;
+ a0.a126 = 127;
+ a0.a127 = 128;
+
+ final result = passStruct1024BytesHomogeneousUint64(a0);
+
+ print("result = $result");
+
+ Expect.equals(8256, result);
+
+ free(a0.addressOf);
+}
+
+final passFloatStruct16BytesHomogeneousFloatFloatStruct1 =
+ ffiTestFunctions.lookupFunction<
+ Float Function(
+ Float,
+ Struct16BytesHomogeneousFloat,
+ Float,
+ Struct16BytesHomogeneousFloat,
+ Float,
+ Struct16BytesHomogeneousFloat,
+ Float,
+ Struct16BytesHomogeneousFloat,
+ Float),
+ double Function(
+ double,
+ Struct16BytesHomogeneousFloat,
+ double,
+ Struct16BytesHomogeneousFloat,
+ double,
+ Struct16BytesHomogeneousFloat,
+ double,
+ Struct16BytesHomogeneousFloat,
+ double)>("PassFloatStruct16BytesHomogeneousFloatFloatStruct1");
+
+/// Tests the alignment of structs in FPU registers and backfilling.
+void testPassFloatStruct16BytesHomogeneousFloatFloatStruct1() {
+ double a0;
+ Struct16BytesHomogeneousFloat a1 =
+ allocate<Struct16BytesHomogeneousFloat>().ref;
+ double a2;
+ Struct16BytesHomogeneousFloat a3 =
+ allocate<Struct16BytesHomogeneousFloat>().ref;
+ double a4;
+ Struct16BytesHomogeneousFloat a5 =
+ allocate<Struct16BytesHomogeneousFloat>().ref;
+ double a6;
+ Struct16BytesHomogeneousFloat a7 =
+ allocate<Struct16BytesHomogeneousFloat>().ref;
+ double a8;
+
+ a0 = -1.0;
+ a1.a0 = 2.0;
+ a1.a1 = -3.0;
+ a1.a2 = 4.0;
+ a1.a3 = -5.0;
+ a2 = 6.0;
+ a3.a0 = -7.0;
+ a3.a1 = 8.0;
+ a3.a2 = -9.0;
+ a3.a3 = 10.0;
+ a4 = -11.0;
+ a5.a0 = 12.0;
+ a5.a1 = -13.0;
+ a5.a2 = 14.0;
+ a5.a3 = -15.0;
+ a6 = 16.0;
+ a7.a0 = -17.0;
+ a7.a1 = 18.0;
+ a7.a2 = -19.0;
+ a7.a3 = 20.0;
+ a8 = -21.0;
+
+ final result = passFloatStruct16BytesHomogeneousFloatFloatStruct1(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ print("result = $result");
+
+ Expect.approxEquals(-11.0, result);
+
+ free(a1.addressOf);
+ free(a3.addressOf);
+ free(a5.addressOf);
+ free(a7.addressOf);
+}
+
+final passFloatStruct32BytesHomogeneousDoubleFloatStruct =
+ ffiTestFunctions.lookupFunction<
+ Double Function(
+ Float,
+ Struct32BytesHomogeneousDouble,
+ Float,
+ Struct32BytesHomogeneousDouble,
+ Float,
+ Struct32BytesHomogeneousDouble,
+ Float,
+ Struct32BytesHomogeneousDouble,
+ Float),
+ double Function(
+ double,
+ Struct32BytesHomogeneousDouble,
+ double,
+ Struct32BytesHomogeneousDouble,
+ double,
+ Struct32BytesHomogeneousDouble,
+ double,
+ Struct32BytesHomogeneousDouble,
+ double)>("PassFloatStruct32BytesHomogeneousDoubleFloatStruct");
+
+/// Tests the alignment of structs in FPU registers and backfilling.
+void testPassFloatStruct32BytesHomogeneousDoubleFloatStruct() {
+ double a0;
+ Struct32BytesHomogeneousDouble a1 =
+ allocate<Struct32BytesHomogeneousDouble>().ref;
+ double a2;
+ Struct32BytesHomogeneousDouble a3 =
+ allocate<Struct32BytesHomogeneousDouble>().ref;
+ double a4;
+ Struct32BytesHomogeneousDouble a5 =
+ allocate<Struct32BytesHomogeneousDouble>().ref;
+ double a6;
+ Struct32BytesHomogeneousDouble a7 =
+ allocate<Struct32BytesHomogeneousDouble>().ref;
+ double a8;
+
+ a0 = -1.0;
+ a1.a0 = 2.0;
+ a1.a1 = -3.0;
+ a1.a2 = 4.0;
+ a1.a3 = -5.0;
+ a2 = 6.0;
+ a3.a0 = -7.0;
+ a3.a1 = 8.0;
+ a3.a2 = -9.0;
+ a3.a3 = 10.0;
+ a4 = -11.0;
+ a5.a0 = 12.0;
+ a5.a1 = -13.0;
+ a5.a2 = 14.0;
+ a5.a3 = -15.0;
+ a6 = 16.0;
+ a7.a0 = -17.0;
+ a7.a1 = 18.0;
+ a7.a2 = -19.0;
+ a7.a3 = 20.0;
+ a8 = -21.0;
+
+ final result = passFloatStruct32BytesHomogeneousDoubleFloatStruct(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ print("result = $result");
+
+ Expect.approxEquals(-11.0, result);
+
+ free(a1.addressOf);
+ free(a3.addressOf);
+ free(a5.addressOf);
+ free(a7.addressOf);
+}
+
+final passInt8Struct16BytesMixedInt8Struct16BytesMixedIn =
+ ffiTestFunctions.lookupFunction<
+ Double Function(Int8, Struct16BytesMixed, Int8, Struct16BytesMixed,
+ Int8, Struct16BytesMixed, Int8, Struct16BytesMixed, Int8),
+ double Function(
+ int,
+ Struct16BytesMixed,
+ int,
+ Struct16BytesMixed,
+ int,
+ Struct16BytesMixed,
+ int,
+ Struct16BytesMixed,
+ int)>("PassInt8Struct16BytesMixedInt8Struct16BytesMixedIn");
+
+/// Tests the alignment of structs in integers registers and on the stack.
+/// Arm32 aligns this struct at 8.
+/// Also, arm32 allocates the second struct partially in registers, partially
+/// on stack.
+/// Test backfilling of integer registers.
+void testPassInt8Struct16BytesMixedInt8Struct16BytesMixedIn() {
+ int a0;
+ Struct16BytesMixed a1 = allocate<Struct16BytesMixed>().ref;
+ int a2;
+ Struct16BytesMixed a3 = allocate<Struct16BytesMixed>().ref;
+ int a4;
+ Struct16BytesMixed a5 = allocate<Struct16BytesMixed>().ref;
+ int a6;
+ Struct16BytesMixed a7 = allocate<Struct16BytesMixed>().ref;
+ int a8;
+
+ a0 = -1;
+ a1.a0 = 2.0;
+ a1.a1 = -3;
+ a2 = 4;
+ a3.a0 = -5.0;
+ a3.a1 = 6;
+ a4 = -7;
+ a5.a0 = 8.0;
+ a5.a1 = -9;
+ a6 = 10;
+ a7.a0 = -11.0;
+ a7.a1 = 12;
+ a8 = -13;
+
+ final result = passInt8Struct16BytesMixedInt8Struct16BytesMixedIn(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ print("result = $result");
+
+ Expect.approxEquals(-7.0, result);
+
+ free(a1.addressOf);
+ free(a3.addressOf);
+ free(a5.addressOf);
+ free(a7.addressOf);
+}
+
+final passDoublex6Struct16BytesMixedx4Int32 = ffiTestFunctions.lookupFunction<
+ Double Function(
+ Double,
+ Double,
+ Double,
+ Double,
+ Double,
+ Double,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Int32),
+ double Function(
+ double,
+ double,
+ double,
+ double,
+ double,
+ double,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ int)>("PassDoublex6Struct16BytesMixedx4Int32");
+
+/// On Linux x64, it will exhaust xmm registers first, after 6 doubles and 2
+/// structs. The rest of the structs will go on the stack.
+/// The int will be backfilled into the int register.
+void testPassDoublex6Struct16BytesMixedx4Int32() {
+ double a0;
+ double a1;
+ double a2;
+ double a3;
+ double a4;
+ double a5;
+ Struct16BytesMixed a6 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a7 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a8 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a9 = allocate<Struct16BytesMixed>().ref;
+ int a10;
+
+ a0 = -1.0;
+ a1 = 2.0;
+ a2 = -3.0;
+ a3 = 4.0;
+ a4 = -5.0;
+ a5 = 6.0;
+ a6.a0 = -7.0;
+ a6.a1 = 8;
+ a7.a0 = -9.0;
+ a7.a1 = 10;
+ a8.a0 = -11.0;
+ a8.a1 = 12;
+ a9.a0 = -13.0;
+ a9.a1 = 14;
+ a10 = -15;
+
+ final result = passDoublex6Struct16BytesMixedx4Int32(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
+
+ print("result = $result");
+
+ Expect.approxEquals(-8.0, result);
+
+ free(a6.addressOf);
+ free(a7.addressOf);
+ free(a8.addressOf);
+ free(a9.addressOf);
+}
+
+final passInt32x4Struct16BytesMixedx4Double = ffiTestFunctions.lookupFunction<
+ Double Function(Int32, Int32, Int32, Int32, Struct16BytesMixed,
+ Struct16BytesMixed, Struct16BytesMixed, Struct16BytesMixed, Double),
+ double Function(
+ int,
+ int,
+ int,
+ int,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ Struct16BytesMixed,
+ double)>("PassInt32x4Struct16BytesMixedx4Double");
+
+/// On Linux x64, it will exhaust int registers first.
+/// The rest of the structs will go on the stack.
+/// The double will be backfilled into the xmm register.
+void testPassInt32x4Struct16BytesMixedx4Double() {
+ int a0;
+ int a1;
+ int a2;
+ int a3;
+ Struct16BytesMixed a4 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a5 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a6 = allocate<Struct16BytesMixed>().ref;
+ Struct16BytesMixed a7 = allocate<Struct16BytesMixed>().ref;
+ double a8;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+ a3 = 4;
+ a4.a0 = -5.0;
+ a4.a1 = 6;
+ a5.a0 = -7.0;
+ a5.a1 = 8;
+ a6.a0 = -9.0;
+ a6.a1 = 10;
+ a7.a0 = -11.0;
+ a7.a1 = 12;
+ a8 = -13.0;
+
+ final result =
+ passInt32x4Struct16BytesMixedx4Double(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ print("result = $result");
+
+ Expect.approxEquals(-7.0, result);
+
+ free(a4.addressOf);
+ free(a5.addressOf);
+ free(a6.addressOf);
+ free(a7.addressOf);
+}
+
+final passStruct40BytesHomogeneousDoubleStruct4BytesHomo =
+ ffiTestFunctions.lookupFunction<
+ Double Function(Struct40BytesHomogeneousDouble,
+ Struct4BytesHomogeneousInt16, Struct8BytesHomogeneousFloat),
+ double Function(Struct40BytesHomogeneousDouble,
+ Struct4BytesHomogeneousInt16, Struct8BytesHomogeneousFloat)>(
+ "PassStruct40BytesHomogeneousDoubleStruct4BytesHomo");
+
+/// On various architectures, first struct is allocated on stack.
+/// Check that the other two arguments are allocated on registers.
+void testPassStruct40BytesHomogeneousDoubleStruct4BytesHomo() {
+ Struct40BytesHomogeneousDouble a0 =
+ allocate<Struct40BytesHomogeneousDouble>().ref;
+ Struct4BytesHomogeneousInt16 a1 =
+ allocate<Struct4BytesHomogeneousInt16>().ref;
+ Struct8BytesHomogeneousFloat a2 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+ a0.a2 = -3.0;
+ a0.a3 = 4.0;
+ a0.a4 = -5.0;
+ a1.a0 = 6;
+ a1.a1 = -7;
+ a2.a0 = 8.0;
+ a2.a1 = -9.0;
+
+ final result = passStruct40BytesHomogeneousDoubleStruct4BytesHomo(a0, a1, a2);
+
+ print("result = $result");
+
+ Expect.approxEquals(-5.0, result);
+
+ free(a0.addressOf);
+ free(a1.addressOf);
+ free(a2.addressOf);
+}
+
+final passStructAlignmentInt16 = ffiTestFunctions.lookupFunction<
+ Int64 Function(StructAlignmentInt16),
+ int Function(StructAlignmentInt16)>("PassStructAlignmentInt16");
+
+/// Test alignment and padding of 16 byte int within struct.
+void testPassStructAlignmentInt16() {
+ StructAlignmentInt16 a0 = allocate<StructAlignmentInt16>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+
+ final result = passStructAlignmentInt16(a0);
+
+ print("result = $result");
+
+ Expect.equals(-2, result);
+
+ free(a0.addressOf);
+}
+
+final passStructAlignmentInt32 = ffiTestFunctions.lookupFunction<
+ Int64 Function(StructAlignmentInt32),
+ int Function(StructAlignmentInt32)>("PassStructAlignmentInt32");
+
+/// Test alignment and padding of 32 byte int within struct.
+void testPassStructAlignmentInt32() {
+ StructAlignmentInt32 a0 = allocate<StructAlignmentInt32>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+
+ final result = passStructAlignmentInt32(a0);
+
+ print("result = $result");
+
+ Expect.equals(-2, result);
+
+ free(a0.addressOf);
+}
+
+final passStructAlignmentInt64 = ffiTestFunctions.lookupFunction<
+ Int64 Function(StructAlignmentInt64),
+ int Function(StructAlignmentInt64)>("PassStructAlignmentInt64");
+
+/// Test alignment and padding of 64 byte int within struct.
+void testPassStructAlignmentInt64() {
+ StructAlignmentInt64 a0 = allocate<StructAlignmentInt64>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+
+ final result = passStructAlignmentInt64(a0);
+
+ print("result = $result");
+
+ Expect.equals(-2, result);
+
+ free(a0.addressOf);
+}
+
+final returnStruct1ByteInt = ffiTestFunctions.lookupFunction<
+ Struct1ByteInt Function(Int8),
+ Struct1ByteInt Function(int)>("ReturnStruct1ByteInt");
+
+/// Smallest struct with data.
+void testReturnStruct1ByteInt() {
+ int a0;
+
+ a0 = -1;
+
+ final result = returnStruct1ByteInt(a0);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+}
+
+final returnStruct3BytesInt = ffiTestFunctions.lookupFunction<
+ Struct3BytesInt Function(Int16, Int8),
+ Struct3BytesInt Function(int, int)>("ReturnStruct3BytesInt");
+
+/// Smaller than word size return value on all architectures.
+void testReturnStruct3BytesInt() {
+ int a0;
+ int a1;
+
+ a0 = -1;
+ a1 = 2;
+
+ final result = returnStruct3BytesInt(a0, a1);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+}
+
+final returnStruct4BytesHomogeneousInt16 = ffiTestFunctions.lookupFunction<
+ Struct4BytesHomogeneousInt16 Function(Int16, Int16),
+ Struct4BytesHomogeneousInt16 Function(
+ int, int)>("ReturnStruct4BytesHomogeneousInt16");
+
+/// Word size return value on 32 bit architectures..
+void testReturnStruct4BytesHomogeneousInt16() {
+ int a0;
+ int a1;
+
+ a0 = -1;
+ a1 = 2;
+
+ final result = returnStruct4BytesHomogeneousInt16(a0, a1);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+}
+
+final returnStruct7BytesInt = ffiTestFunctions.lookupFunction<
+ Struct7BytesInt Function(Int32, Int16, Int8),
+ Struct7BytesInt Function(int, int, int)>("ReturnStruct7BytesInt");
+
+/// Non-wordsize return value.
+void testReturnStruct7BytesInt() {
+ int a0;
+ int a1;
+ int a2;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+
+ final result = returnStruct7BytesInt(a0, a1, a2);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+}
+
+final returnStruct8BytesInt = ffiTestFunctions.lookupFunction<
+ Struct8BytesInt Function(Int16, Int16, Int32),
+ Struct8BytesInt Function(int, int, int)>("ReturnStruct8BytesInt");
+
+/// Return value in integer registers on many architectures.
+void testReturnStruct8BytesInt() {
+ int a0;
+ int a1;
+ int a2;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+
+ final result = returnStruct8BytesInt(a0, a1, a2);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+}
+
+final returnStruct8BytesHomogeneousFloat = ffiTestFunctions.lookupFunction<
+ Struct8BytesHomogeneousFloat Function(Float, Float),
+ Struct8BytesHomogeneousFloat Function(
+ double, double)>("ReturnStruct8BytesHomogeneousFloat");
+
+/// Return value in FP registers on many architectures.
+void testReturnStruct8BytesHomogeneousFloat() {
+ double a0;
+ double a1;
+
+ a0 = -1.0;
+ a1 = 2.0;
+
+ final result = returnStruct8BytesHomogeneousFloat(a0, a1);
+
+ print("result = $result");
+
+ Expect.approxEquals(a0, result.a0);
+ Expect.approxEquals(a1, result.a1);
+}
+
+final returnStruct8BytesMixed = ffiTestFunctions.lookupFunction<
+ Struct8BytesMixed Function(Float, Int16, Int16),
+ Struct8BytesMixed Function(double, int, int)>("ReturnStruct8BytesMixed");
+
+/// Return value split over FP and integer register in x64.
+void testReturnStruct8BytesMixed() {
+ double a0;
+ int a1;
+ int a2;
+
+ a0 = -1.0;
+ a1 = 2;
+ a2 = -3;
+
+ final result = returnStruct8BytesMixed(a0, a1, a2);
+
+ print("result = $result");
+
+ Expect.approxEquals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+}
+
+final returnStruct9BytesInt = ffiTestFunctions.lookupFunction<
+ Struct9BytesInt Function(Int64, Int8),
+ Struct9BytesInt Function(int, int)>("ReturnStruct9BytesInt");
+
+/// Return value in two integer registers on x64.
+/// The second register only contains a single byte.
+void testReturnStruct9BytesInt() {
+ int a0;
+ int a1;
+
+ a0 = -1;
+ a1 = 2;
+
+ final result = returnStruct9BytesInt(a0, a1);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+}
+
+final returnStruct9BytesHomogeneousUint82 = ffiTestFunctions.lookupFunction<
+ Struct9BytesHomogeneousUint82 Function(
+ Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8),
+ Struct9BytesHomogeneousUint82 Function(int, int, int, int, int, int, int,
+ int, int)>("ReturnStruct9BytesHomogeneousUint82");
+
+/// The minimum alignment of this struct is only 1 byte based on its fields.
+/// Test that the memory backing these structs is the right size and that
+/// dart:ffi trampolines do not write outside this size.
+void testReturnStruct9BytesHomogeneousUint82() {
+ int a0;
+ int a1;
+ int a2;
+ int a3;
+ int a4;
+ int a5;
+ int a6;
+ int a7;
+ int a8;
+
+ a0 = 1;
+ a1 = 2;
+ a2 = 3;
+ a3 = 4;
+ a4 = 5;
+ a5 = 6;
+ a6 = 7;
+ a7 = 8;
+ a8 = 9;
+
+ final result =
+ returnStruct9BytesHomogeneousUint82(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+ Expect.equals(a3, result.a3);
+ Expect.equals(a4, result.a4);
+ Expect.equals(a5, result.a5);
+ Expect.equals(a6, result.a6);
+ Expect.equals(a7, result.a7);
+ Expect.equals(a8, result.a8);
+}
+
+final returnStruct12BytesHomogeneousFloat = ffiTestFunctions.lookupFunction<
+ Struct12BytesHomogeneousFloat Function(Float, Float, Float),
+ Struct12BytesHomogeneousFloat Function(
+ double, double, double)>("ReturnStruct12BytesHomogeneousFloat");
+
+/// Return value in FPU registers, but does not use all registers on arm hardfp
+/// and arm64.
+void testReturnStruct12BytesHomogeneousFloat() {
+ double a0;
+ double a1;
+ double a2;
+
+ a0 = -1.0;
+ a1 = 2.0;
+ a2 = -3.0;
+
+ final result = returnStruct12BytesHomogeneousFloat(a0, a1, a2);
+
+ print("result = $result");
+
+ Expect.approxEquals(a0, result.a0);
+ Expect.approxEquals(a1, result.a1);
+ Expect.approxEquals(a2, result.a2);
+}
+
+final returnStruct16BytesHomogeneousFloat = ffiTestFunctions.lookupFunction<
+ Struct16BytesHomogeneousFloat Function(Float, Float, Float, Float),
+ Struct16BytesHomogeneousFloat Function(
+ double, double, double, double)>("ReturnStruct16BytesHomogeneousFloat");
+
+/// Return value in FPU registers on arm hardfp and arm64.
+void testReturnStruct16BytesHomogeneousFloat() {
+ double a0;
+ double a1;
+ double a2;
+ double a3;
+
+ a0 = -1.0;
+ a1 = 2.0;
+ a2 = -3.0;
+ a3 = 4.0;
+
+ final result = returnStruct16BytesHomogeneousFloat(a0, a1, a2, a3);
+
+ print("result = $result");
+
+ Expect.approxEquals(a0, result.a0);
+ Expect.approxEquals(a1, result.a1);
+ Expect.approxEquals(a2, result.a2);
+ Expect.approxEquals(a3, result.a3);
+}
+
+final returnStruct16BytesMixed = ffiTestFunctions.lookupFunction<
+ Struct16BytesMixed Function(Double, Int64),
+ Struct16BytesMixed Function(double, int)>("ReturnStruct16BytesMixed");
+
+/// Return value split over FP and integer register in x64.
+void testReturnStruct16BytesMixed() {
+ double a0;
+ int a1;
+
+ a0 = -1.0;
+ a1 = 2;
+
+ final result = returnStruct16BytesMixed(a0, a1);
+
+ print("result = $result");
+
+ Expect.approxEquals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+}
+
+final returnStruct16BytesMixed2 = ffiTestFunctions.lookupFunction<
+ Struct16BytesMixed2 Function(Float, Float, Float, Int32),
+ Struct16BytesMixed2 Function(
+ double, double, double, int)>("ReturnStruct16BytesMixed2");
+
+/// Return value split over FP and integer register in x64.
+/// The integer register contains half float half int.
+void testReturnStruct16BytesMixed2() {
+ double a0;
+ double a1;
+ double a2;
+ int a3;
+
+ a0 = -1.0;
+ a1 = 2.0;
+ a2 = -3.0;
+ a3 = 4;
+
+ final result = returnStruct16BytesMixed2(a0, a1, a2, a3);
+
+ print("result = $result");
+
+ Expect.approxEquals(a0, result.a0);
+ Expect.approxEquals(a1, result.a1);
+ Expect.approxEquals(a2, result.a2);
+ Expect.equals(a3, result.a3);
+}
+
+final returnStruct17BytesInt = ffiTestFunctions.lookupFunction<
+ Struct17BytesInt Function(Int64, Int64, Int8),
+ Struct17BytesInt Function(int, int, int)>("ReturnStruct17BytesInt");
+
+/// Rerturn value returned in preallocated space passed by pointer on most ABIs.
+/// Is non word size on purpose, to test that structs are rounded up to word size
+/// on all ABIs.
+void testReturnStruct17BytesInt() {
+ int a0;
+ int a1;
+ int a2;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+
+ final result = returnStruct17BytesInt(a0, a1, a2);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+}
+
+final returnStruct19BytesHomogeneousUint8 = ffiTestFunctions.lookupFunction<
+ Struct19BytesHomogeneousUint8 Function(
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8,
+ Uint8),
+ Struct19BytesHomogeneousUint8 Function(
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int)>("ReturnStruct19BytesHomogeneousUint8");
+
+/// The minimum alignment of this struct is only 1 byte based on its fields.
+/// Test that the memory backing these structs is the right size and that
+/// dart:ffi trampolines do not write outside this size.
+void testReturnStruct19BytesHomogeneousUint8() {
+ int a0;
+ int a1;
+ int a2;
+ int a3;
+ int a4;
+ int a5;
+ int a6;
+ int a7;
+ int a8;
+ int a9;
+ int a10;
+ int a11;
+ int a12;
+ int a13;
+ int a14;
+ int a15;
+ int a16;
+ int a17;
+ int a18;
+
+ a0 = 1;
+ a1 = 2;
+ a2 = 3;
+ a3 = 4;
+ a4 = 5;
+ a5 = 6;
+ a6 = 7;
+ a7 = 8;
+ a8 = 9;
+ a9 = 10;
+ a10 = 11;
+ a11 = 12;
+ a12 = 13;
+ a13 = 14;
+ a14 = 15;
+ a15 = 16;
+ a16 = 17;
+ a17 = 18;
+ a18 = 19;
+
+ final result = returnStruct19BytesHomogeneousUint8(a0, a1, a2, a3, a4, a5, a6,
+ a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+ Expect.equals(a3, result.a3);
+ Expect.equals(a4, result.a4);
+ Expect.equals(a5, result.a5);
+ Expect.equals(a6, result.a6);
+ Expect.equals(a7, result.a7);
+ Expect.equals(a8, result.a8);
+ Expect.equals(a9, result.a9);
+ Expect.equals(a10, result.a10);
+ Expect.equals(a11, result.a11);
+ Expect.equals(a12, result.a12);
+ Expect.equals(a13, result.a13);
+ Expect.equals(a14, result.a14);
+ Expect.equals(a15, result.a15);
+ Expect.equals(a16, result.a16);
+ Expect.equals(a17, result.a17);
+ Expect.equals(a18, result.a18);
+}
+
+final returnStruct20BytesHomogeneousInt32 = ffiTestFunctions.lookupFunction<
+ Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32, Int32),
+ Struct20BytesHomogeneousInt32 Function(
+ int, int, int, int, int)>("ReturnStruct20BytesHomogeneousInt32");
+
+/// Return value too big to go in cpu registers on arm64.
+void testReturnStruct20BytesHomogeneousInt32() {
+ int a0;
+ int a1;
+ int a2;
+ int a3;
+ int a4;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+ a3 = 4;
+ a4 = -5;
+
+ final result = returnStruct20BytesHomogeneousInt32(a0, a1, a2, a3, a4);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+ Expect.equals(a3, result.a3);
+ Expect.equals(a4, result.a4);
+}
+
+final returnStruct20BytesHomogeneousFloat = ffiTestFunctions.lookupFunction<
+ Struct20BytesHomogeneousFloat Function(Float, Float, Float, Float, Float),
+ Struct20BytesHomogeneousFloat Function(double, double, double, double,
+ double)>("ReturnStruct20BytesHomogeneousFloat");
+
+/// Return value too big to go in FPU registers on x64, arm hardfp and arm64.
+void testReturnStruct20BytesHomogeneousFloat() {
+ double a0;
+ double a1;
+ double a2;
+ double a3;
+ double a4;
+
+ a0 = -1.0;
+ a1 = 2.0;
+ a2 = -3.0;
+ a3 = 4.0;
+ a4 = -5.0;
+
+ final result = returnStruct20BytesHomogeneousFloat(a0, a1, a2, a3, a4);
+
+ print("result = $result");
+
+ Expect.approxEquals(a0, result.a0);
+ Expect.approxEquals(a1, result.a1);
+ Expect.approxEquals(a2, result.a2);
+ Expect.approxEquals(a3, result.a3);
+ Expect.approxEquals(a4, result.a4);
+}
+
+final returnStruct32BytesHomogeneousDouble = ffiTestFunctions.lookupFunction<
+ Struct32BytesHomogeneousDouble Function(Double, Double, Double, Double),
+ Struct32BytesHomogeneousDouble Function(double, double, double,
+ double)>("ReturnStruct32BytesHomogeneousDouble");
+
+/// Return value in FPU registers on arm64.
+void testReturnStruct32BytesHomogeneousDouble() {
+ double a0;
+ double a1;
+ double a2;
+ double a3;
+
+ a0 = -1.0;
+ a1 = 2.0;
+ a2 = -3.0;
+ a3 = 4.0;
+
+ final result = returnStruct32BytesHomogeneousDouble(a0, a1, a2, a3);
+
+ print("result = $result");
+
+ Expect.approxEquals(a0, result.a0);
+ Expect.approxEquals(a1, result.a1);
+ Expect.approxEquals(a2, result.a2);
+ Expect.approxEquals(a3, result.a3);
+}
+
+final returnStruct40BytesHomogeneousDouble = ffiTestFunctions.lookupFunction<
+ Struct40BytesHomogeneousDouble Function(
+ Double, Double, Double, Double, Double),
+ Struct40BytesHomogeneousDouble Function(double, double, double, double,
+ double)>("ReturnStruct40BytesHomogeneousDouble");
+
+/// Return value too big to go in FPU registers on arm64.
+void testReturnStruct40BytesHomogeneousDouble() {
+ double a0;
+ double a1;
+ double a2;
+ double a3;
+ double a4;
+
+ a0 = -1.0;
+ a1 = 2.0;
+ a2 = -3.0;
+ a3 = 4.0;
+ a4 = -5.0;
+
+ final result = returnStruct40BytesHomogeneousDouble(a0, a1, a2, a3, a4);
+
+ print("result = $result");
+
+ Expect.approxEquals(a0, result.a0);
+ Expect.approxEquals(a1, result.a1);
+ Expect.approxEquals(a2, result.a2);
+ Expect.approxEquals(a3, result.a3);
+ Expect.approxEquals(a4, result.a4);
+}
+
+final returnStruct1024BytesHomogeneousUint64 = ffiTestFunctions.lookupFunction<
+ Struct1024BytesHomogeneousUint64 Function(
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64,
+ Uint64),
+ Struct1024BytesHomogeneousUint64 Function(
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int)>("ReturnStruct1024BytesHomogeneousUint64");
+
+/// Test 1kb struct.
+void testReturnStruct1024BytesHomogeneousUint64() {
+ int a0;
+ int a1;
+ int a2;
+ int a3;
+ int a4;
+ int a5;
+ int a6;
+ int a7;
+ int a8;
+ int a9;
+ int a10;
+ int a11;
+ int a12;
+ int a13;
+ int a14;
+ int a15;
+ int a16;
+ int a17;
+ int a18;
+ int a19;
+ int a20;
+ int a21;
+ int a22;
+ int a23;
+ int a24;
+ int a25;
+ int a26;
+ int a27;
+ int a28;
+ int a29;
+ int a30;
+ int a31;
+ int a32;
+ int a33;
+ int a34;
+ int a35;
+ int a36;
+ int a37;
+ int a38;
+ int a39;
+ int a40;
+ int a41;
+ int a42;
+ int a43;
+ int a44;
+ int a45;
+ int a46;
+ int a47;
+ int a48;
+ int a49;
+ int a50;
+ int a51;
+ int a52;
+ int a53;
+ int a54;
+ int a55;
+ int a56;
+ int a57;
+ int a58;
+ int a59;
+ int a60;
+ int a61;
+ int a62;
+ int a63;
+ int a64;
+ int a65;
+ int a66;
+ int a67;
+ int a68;
+ int a69;
+ int a70;
+ int a71;
+ int a72;
+ int a73;
+ int a74;
+ int a75;
+ int a76;
+ int a77;
+ int a78;
+ int a79;
+ int a80;
+ int a81;
+ int a82;
+ int a83;
+ int a84;
+ int a85;
+ int a86;
+ int a87;
+ int a88;
+ int a89;
+ int a90;
+ int a91;
+ int a92;
+ int a93;
+ int a94;
+ int a95;
+ int a96;
+ int a97;
+ int a98;
+ int a99;
+ int a100;
+ int a101;
+ int a102;
+ int a103;
+ int a104;
+ int a105;
+ int a106;
+ int a107;
+ int a108;
+ int a109;
+ int a110;
+ int a111;
+ int a112;
+ int a113;
+ int a114;
+ int a115;
+ int a116;
+ int a117;
+ int a118;
+ int a119;
+ int a120;
+ int a121;
+ int a122;
+ int a123;
+ int a124;
+ int a125;
+ int a126;
+ int a127;
+
+ a0 = 1;
+ a1 = 2;
+ a2 = 3;
+ a3 = 4;
+ a4 = 5;
+ a5 = 6;
+ a6 = 7;
+ a7 = 8;
+ a8 = 9;
+ a9 = 10;
+ a10 = 11;
+ a11 = 12;
+ a12 = 13;
+ a13 = 14;
+ a14 = 15;
+ a15 = 16;
+ a16 = 17;
+ a17 = 18;
+ a18 = 19;
+ a19 = 20;
+ a20 = 21;
+ a21 = 22;
+ a22 = 23;
+ a23 = 24;
+ a24 = 25;
+ a25 = 26;
+ a26 = 27;
+ a27 = 28;
+ a28 = 29;
+ a29 = 30;
+ a30 = 31;
+ a31 = 32;
+ a32 = 33;
+ a33 = 34;
+ a34 = 35;
+ a35 = 36;
+ a36 = 37;
+ a37 = 38;
+ a38 = 39;
+ a39 = 40;
+ a40 = 41;
+ a41 = 42;
+ a42 = 43;
+ a43 = 44;
+ a44 = 45;
+ a45 = 46;
+ a46 = 47;
+ a47 = 48;
+ a48 = 49;
+ a49 = 50;
+ a50 = 51;
+ a51 = 52;
+ a52 = 53;
+ a53 = 54;
+ a54 = 55;
+ a55 = 56;
+ a56 = 57;
+ a57 = 58;
+ a58 = 59;
+ a59 = 60;
+ a60 = 61;
+ a61 = 62;
+ a62 = 63;
+ a63 = 64;
+ a64 = 65;
+ a65 = 66;
+ a66 = 67;
+ a67 = 68;
+ a68 = 69;
+ a69 = 70;
+ a70 = 71;
+ a71 = 72;
+ a72 = 73;
+ a73 = 74;
+ a74 = 75;
+ a75 = 76;
+ a76 = 77;
+ a77 = 78;
+ a78 = 79;
+ a79 = 80;
+ a80 = 81;
+ a81 = 82;
+ a82 = 83;
+ a83 = 84;
+ a84 = 85;
+ a85 = 86;
+ a86 = 87;
+ a87 = 88;
+ a88 = 89;
+ a89 = 90;
+ a90 = 91;
+ a91 = 92;
+ a92 = 93;
+ a93 = 94;
+ a94 = 95;
+ a95 = 96;
+ a96 = 97;
+ a97 = 98;
+ a98 = 99;
+ a99 = 100;
+ a100 = 101;
+ a101 = 102;
+ a102 = 103;
+ a103 = 104;
+ a104 = 105;
+ a105 = 106;
+ a106 = 107;
+ a107 = 108;
+ a108 = 109;
+ a109 = 110;
+ a110 = 111;
+ a111 = 112;
+ a112 = 113;
+ a113 = 114;
+ a114 = 115;
+ a115 = 116;
+ a116 = 117;
+ a117 = 118;
+ a118 = 119;
+ a119 = 120;
+ a120 = 121;
+ a121 = 122;
+ a122 = 123;
+ a123 = 124;
+ a124 = 125;
+ a125 = 126;
+ a126 = 127;
+ a127 = 128;
+
+ final result = returnStruct1024BytesHomogeneousUint64(
+ a0,
+ a1,
+ a2,
+ a3,
+ a4,
+ a5,
+ a6,
+ a7,
+ a8,
+ a9,
+ a10,
+ a11,
+ a12,
+ a13,
+ a14,
+ a15,
+ a16,
+ a17,
+ a18,
+ a19,
+ a20,
+ a21,
+ a22,
+ a23,
+ a24,
+ a25,
+ a26,
+ a27,
+ a28,
+ a29,
+ a30,
+ a31,
+ a32,
+ a33,
+ a34,
+ a35,
+ a36,
+ a37,
+ a38,
+ a39,
+ a40,
+ a41,
+ a42,
+ a43,
+ a44,
+ a45,
+ a46,
+ a47,
+ a48,
+ a49,
+ a50,
+ a51,
+ a52,
+ a53,
+ a54,
+ a55,
+ a56,
+ a57,
+ a58,
+ a59,
+ a60,
+ a61,
+ a62,
+ a63,
+ a64,
+ a65,
+ a66,
+ a67,
+ a68,
+ a69,
+ a70,
+ a71,
+ a72,
+ a73,
+ a74,
+ a75,
+ a76,
+ a77,
+ a78,
+ a79,
+ a80,
+ a81,
+ a82,
+ a83,
+ a84,
+ a85,
+ a86,
+ a87,
+ a88,
+ a89,
+ a90,
+ a91,
+ a92,
+ a93,
+ a94,
+ a95,
+ a96,
+ a97,
+ a98,
+ a99,
+ a100,
+ a101,
+ a102,
+ a103,
+ a104,
+ a105,
+ a106,
+ a107,
+ a108,
+ a109,
+ a110,
+ a111,
+ a112,
+ a113,
+ a114,
+ a115,
+ a116,
+ a117,
+ a118,
+ a119,
+ a120,
+ a121,
+ a122,
+ a123,
+ a124,
+ a125,
+ a126,
+ a127);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+ Expect.equals(a3, result.a3);
+ Expect.equals(a4, result.a4);
+ Expect.equals(a5, result.a5);
+ Expect.equals(a6, result.a6);
+ Expect.equals(a7, result.a7);
+ Expect.equals(a8, result.a8);
+ Expect.equals(a9, result.a9);
+ Expect.equals(a10, result.a10);
+ Expect.equals(a11, result.a11);
+ Expect.equals(a12, result.a12);
+ Expect.equals(a13, result.a13);
+ Expect.equals(a14, result.a14);
+ Expect.equals(a15, result.a15);
+ Expect.equals(a16, result.a16);
+ Expect.equals(a17, result.a17);
+ Expect.equals(a18, result.a18);
+ Expect.equals(a19, result.a19);
+ Expect.equals(a20, result.a20);
+ Expect.equals(a21, result.a21);
+ Expect.equals(a22, result.a22);
+ Expect.equals(a23, result.a23);
+ Expect.equals(a24, result.a24);
+ Expect.equals(a25, result.a25);
+ Expect.equals(a26, result.a26);
+ Expect.equals(a27, result.a27);
+ Expect.equals(a28, result.a28);
+ Expect.equals(a29, result.a29);
+ Expect.equals(a30, result.a30);
+ Expect.equals(a31, result.a31);
+ Expect.equals(a32, result.a32);
+ Expect.equals(a33, result.a33);
+ Expect.equals(a34, result.a34);
+ Expect.equals(a35, result.a35);
+ Expect.equals(a36, result.a36);
+ Expect.equals(a37, result.a37);
+ Expect.equals(a38, result.a38);
+ Expect.equals(a39, result.a39);
+ Expect.equals(a40, result.a40);
+ Expect.equals(a41, result.a41);
+ Expect.equals(a42, result.a42);
+ Expect.equals(a43, result.a43);
+ Expect.equals(a44, result.a44);
+ Expect.equals(a45, result.a45);
+ Expect.equals(a46, result.a46);
+ Expect.equals(a47, result.a47);
+ Expect.equals(a48, result.a48);
+ Expect.equals(a49, result.a49);
+ Expect.equals(a50, result.a50);
+ Expect.equals(a51, result.a51);
+ Expect.equals(a52, result.a52);
+ Expect.equals(a53, result.a53);
+ Expect.equals(a54, result.a54);
+ Expect.equals(a55, result.a55);
+ Expect.equals(a56, result.a56);
+ Expect.equals(a57, result.a57);
+ Expect.equals(a58, result.a58);
+ Expect.equals(a59, result.a59);
+ Expect.equals(a60, result.a60);
+ Expect.equals(a61, result.a61);
+ Expect.equals(a62, result.a62);
+ Expect.equals(a63, result.a63);
+ Expect.equals(a64, result.a64);
+ Expect.equals(a65, result.a65);
+ Expect.equals(a66, result.a66);
+ Expect.equals(a67, result.a67);
+ Expect.equals(a68, result.a68);
+ Expect.equals(a69, result.a69);
+ Expect.equals(a70, result.a70);
+ Expect.equals(a71, result.a71);
+ Expect.equals(a72, result.a72);
+ Expect.equals(a73, result.a73);
+ Expect.equals(a74, result.a74);
+ Expect.equals(a75, result.a75);
+ Expect.equals(a76, result.a76);
+ Expect.equals(a77, result.a77);
+ Expect.equals(a78, result.a78);
+ Expect.equals(a79, result.a79);
+ Expect.equals(a80, result.a80);
+ Expect.equals(a81, result.a81);
+ Expect.equals(a82, result.a82);
+ Expect.equals(a83, result.a83);
+ Expect.equals(a84, result.a84);
+ Expect.equals(a85, result.a85);
+ Expect.equals(a86, result.a86);
+ Expect.equals(a87, result.a87);
+ Expect.equals(a88, result.a88);
+ Expect.equals(a89, result.a89);
+ Expect.equals(a90, result.a90);
+ Expect.equals(a91, result.a91);
+ Expect.equals(a92, result.a92);
+ Expect.equals(a93, result.a93);
+ Expect.equals(a94, result.a94);
+ Expect.equals(a95, result.a95);
+ Expect.equals(a96, result.a96);
+ Expect.equals(a97, result.a97);
+ Expect.equals(a98, result.a98);
+ Expect.equals(a99, result.a99);
+ Expect.equals(a100, result.a100);
+ Expect.equals(a101, result.a101);
+ Expect.equals(a102, result.a102);
+ Expect.equals(a103, result.a103);
+ Expect.equals(a104, result.a104);
+ Expect.equals(a105, result.a105);
+ Expect.equals(a106, result.a106);
+ Expect.equals(a107, result.a107);
+ Expect.equals(a108, result.a108);
+ Expect.equals(a109, result.a109);
+ Expect.equals(a110, result.a110);
+ Expect.equals(a111, result.a111);
+ Expect.equals(a112, result.a112);
+ Expect.equals(a113, result.a113);
+ Expect.equals(a114, result.a114);
+ Expect.equals(a115, result.a115);
+ Expect.equals(a116, result.a116);
+ Expect.equals(a117, result.a117);
+ Expect.equals(a118, result.a118);
+ Expect.equals(a119, result.a119);
+ Expect.equals(a120, result.a120);
+ Expect.equals(a121, result.a121);
+ Expect.equals(a122, result.a122);
+ Expect.equals(a123, result.a123);
+ Expect.equals(a124, result.a124);
+ Expect.equals(a125, result.a125);
+ Expect.equals(a126, result.a126);
+ Expect.equals(a127, result.a127);
+}
+
+final returnStructArgumentStruct1ByteInt = ffiTestFunctions.lookupFunction<
+ Struct1ByteInt Function(Struct1ByteInt),
+ Struct1ByteInt Function(
+ Struct1ByteInt)>("ReturnStructArgumentStruct1ByteInt");
+
+/// Test that a struct passed in as argument can be returned.
+/// Especially for ffi callbacks.
+/// Struct is passed in int registers in most ABIs.
+void testReturnStructArgumentStruct1ByteInt() {
+ Struct1ByteInt a0 = allocate<Struct1ByteInt>().ref;
+
+ a0.a0 = -1;
+
+ final result = returnStructArgumentStruct1ByteInt(a0);
+
+ print("result = $result");
+
+ Expect.equals(a0.a0, result.a0);
+
+ free(a0.addressOf);
+}
+
+final returnStructArgumentInt32x8Struct1ByteInt =
+ ffiTestFunctions.lookupFunction<
+ Struct1ByteInt Function(Int32, Int32, Int32, Int32, Int32, Int32, Int32,
+ Int32, Struct1ByteInt),
+ Struct1ByteInt Function(int, int, int, int, int, int, int, int,
+ Struct1ByteInt)>("ReturnStructArgumentInt32x8Struct1ByteInt");
+
+/// Test that a struct passed in as argument can be returned.
+/// Especially for ffi callbacks.
+/// Struct is passed on stack on all ABIs.
+void testReturnStructArgumentInt32x8Struct1ByteInt() {
+ int a0;
+ int a1;
+ int a2;
+ int a3;
+ int a4;
+ int a5;
+ int a6;
+ int a7;
+ Struct1ByteInt a8 = allocate<Struct1ByteInt>().ref;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+ a3 = 4;
+ a4 = -5;
+ a5 = 6;
+ a6 = -7;
+ a7 = 8;
+ a8.a0 = -9;
+
+ final result = returnStructArgumentInt32x8Struct1ByteInt(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ print("result = $result");
+
+ Expect.equals(a8.a0, result.a0);
+
+ free(a8.addressOf);
+}
+
+final returnStructArgumentStruct8BytesHomogeneousFloat =
+ ffiTestFunctions.lookupFunction<
+ Struct8BytesHomogeneousFloat Function(Struct8BytesHomogeneousFloat),
+ Struct8BytesHomogeneousFloat Function(
+ Struct8BytesHomogeneousFloat)>(
+ "ReturnStructArgumentStruct8BytesHomogeneousFloat");
+
+/// Test that a struct passed in as argument can be returned.
+/// Especially for ffi callbacks.
+/// Struct is passed in float registers in most ABIs.
+void testReturnStructArgumentStruct8BytesHomogeneousFloat() {
+ Struct8BytesHomogeneousFloat a0 =
+ allocate<Struct8BytesHomogeneousFloat>().ref;
+
+ a0.a0 = -1.0;
+ a0.a1 = 2.0;
+
+ final result = returnStructArgumentStruct8BytesHomogeneousFloat(a0);
+
+ print("result = $result");
+
+ Expect.approxEquals(a0.a0, result.a0);
+ Expect.approxEquals(a0.a1, result.a1);
+
+ free(a0.addressOf);
+}
+
+final returnStructArgumentStruct20BytesHomogeneousInt32 =
+ ffiTestFunctions
+ .lookupFunction<
+ Struct20BytesHomogeneousInt32 Function(
+ Struct20BytesHomogeneousInt32),
+ Struct20BytesHomogeneousInt32 Function(
+ Struct20BytesHomogeneousInt32)>(
+ "ReturnStructArgumentStruct20BytesHomogeneousInt32");
+
+/// On arm64, both argument and return value are passed in by pointer.
+void testReturnStructArgumentStruct20BytesHomogeneousInt32() {
+ Struct20BytesHomogeneousInt32 a0 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+
+ a0.a0 = -1;
+ a0.a1 = 2;
+ a0.a2 = -3;
+ a0.a3 = 4;
+ a0.a4 = -5;
+
+ final result = returnStructArgumentStruct20BytesHomogeneousInt32(a0);
+
+ print("result = $result");
+
+ Expect.equals(a0.a0, result.a0);
+ Expect.equals(a0.a1, result.a1);
+ Expect.equals(a0.a2, result.a2);
+ Expect.equals(a0.a3, result.a3);
+ Expect.equals(a0.a4, result.a4);
+
+ free(a0.addressOf);
+}
+
+final returnStructArgumentInt32x8Struct20BytesHomogeneou =
+ ffiTestFunctions.lookupFunction<
+ Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32,
+ Int32, Int32, Int32, Int32, Struct20BytesHomogeneousInt32),
+ Struct20BytesHomogeneousInt32 Function(int, int, int, int, int, int,
+ int, int, Struct20BytesHomogeneousInt32)>(
+ "ReturnStructArgumentInt32x8Struct20BytesHomogeneou");
+
+/// On arm64, both argument and return value are passed in by pointer.
+/// Ints exhaust registers, so that pointer is passed on stack.
+void testReturnStructArgumentInt32x8Struct20BytesHomogeneou() {
+ int a0;
+ int a1;
+ int a2;
+ int a3;
+ int a4;
+ int a5;
+ int a6;
+ int a7;
+ Struct20BytesHomogeneousInt32 a8 =
+ allocate<Struct20BytesHomogeneousInt32>().ref;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+ a3 = 4;
+ a4 = -5;
+ a5 = 6;
+ a6 = -7;
+ a7 = 8;
+ a8.a0 = -9;
+ a8.a1 = 10;
+ a8.a2 = -11;
+ a8.a3 = 12;
+ a8.a4 = -13;
+
+ final result = returnStructArgumentInt32x8Struct20BytesHomogeneou(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8);
+
+ print("result = $result");
+
+ Expect.equals(a8.a0, result.a0);
+ Expect.equals(a8.a1, result.a1);
+ Expect.equals(a8.a2, result.a2);
+ Expect.equals(a8.a3, result.a3);
+ Expect.equals(a8.a4, result.a4);
+
+ free(a8.addressOf);
+}
+
+final returnStructAlignmentInt16 = ffiTestFunctions.lookupFunction<
+ StructAlignmentInt16 Function(Int8, Int16, Int8),
+ StructAlignmentInt16 Function(int, int, int)>("ReturnStructAlignmentInt16");
+
+/// Test alignment and padding of 16 byte int within struct.
+void testReturnStructAlignmentInt16() {
+ int a0;
+ int a1;
+ int a2;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+
+ final result = returnStructAlignmentInt16(a0, a1, a2);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+}
+
+final returnStructAlignmentInt32 = ffiTestFunctions.lookupFunction<
+ StructAlignmentInt32 Function(Int8, Int32, Int8),
+ StructAlignmentInt32 Function(int, int, int)>("ReturnStructAlignmentInt32");
+
+/// Test alignment and padding of 32 byte int within struct.
+void testReturnStructAlignmentInt32() {
+ int a0;
+ int a1;
+ int a2;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+
+ final result = returnStructAlignmentInt32(a0, a1, a2);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+}
+
+final returnStructAlignmentInt64 = ffiTestFunctions.lookupFunction<
+ StructAlignmentInt64 Function(Int8, Int64, Int8),
+ StructAlignmentInt64 Function(int, int, int)>("ReturnStructAlignmentInt64");
+
+/// Test alignment and padding of 64 byte int within struct.
+void testReturnStructAlignmentInt64() {
+ int a0;
+ int a1;
+ int a2;
+
+ a0 = -1;
+ a1 = 2;
+ a2 = -3;
+
+ final result = returnStructAlignmentInt64(a0, a1, a2);
+
+ print("result = $result");
+
+ Expect.equals(a0, result.a0);
+ Expect.equals(a1, result.a1);
+ Expect.equals(a2, result.a2);
+}
diff --git a/tests/ffi_2/generator/c_types.dart b/tests/ffi_2/generator/c_types.dart
new file mode 100644
index 0000000..f2948fa
--- /dev/null
+++ b/tests/ffi_2/generator/c_types.dart
@@ -0,0 +1,299 @@
+// Copyright (c) 2020, 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 'utils.dart';
+
+const int8 = FundamentalType(PrimitiveType.int8);
+const int16 = FundamentalType(PrimitiveType.int16);
+const int32 = FundamentalType(PrimitiveType.int32);
+const int64 = FundamentalType(PrimitiveType.int64);
+const uint8 = FundamentalType(PrimitiveType.uint8);
+const uint16 = FundamentalType(PrimitiveType.uint16);
+const uint32 = FundamentalType(PrimitiveType.uint32);
+const uint64 = FundamentalType(PrimitiveType.uint64);
+const intptr = FundamentalType(PrimitiveType.intptr);
+const float = FundamentalType(PrimitiveType.float);
+const double_ = FundamentalType(PrimitiveType.double_);
+
+enum PrimitiveType {
+ int8,
+ int16,
+ int32,
+ int64,
+ uint8,
+ uint16,
+ uint32,
+ uint64,
+ intptr,
+ float,
+ double_,
+}
+
+const primitiveNames = [
+ "int8",
+ "int16",
+ "int32",
+ "int64",
+ "uint8",
+ "uint16",
+ "uint32",
+ "uint64",
+ "intptr",
+ "float",
+ "double",
+];
+
+const intptrSize = -1;
+const primitiveSizesInBytes = [1, 2, 4, 8, 1, 2, 4, 8, intptrSize, 4, 8];
+
+abstract class CType {
+ String get cType;
+ String get dartCType;
+ String get dartType;
+ String get dartStructFieldAnnotation;
+
+ /// Has a known [size] that is the same for all architectures.
+ bool get hasSize;
+
+ /// Get a size in bytes that is the same on all architectures.
+ int get size;
+
+ String toString() => dartCType;
+
+ const CType();
+}
+
+class FundamentalType extends CType {
+ final PrimitiveType primitive;
+
+ const FundamentalType(this.primitive);
+
+ bool get isFloatingPoint =>
+ primitive == PrimitiveType.float || primitive == PrimitiveType.double_;
+ bool get isInteger => !isFloatingPoint;
+ bool get isUnsigned =>
+ primitive == PrimitiveType.uint8 ||
+ primitive == PrimitiveType.uint16 ||
+ primitive == PrimitiveType.uint32 ||
+ primitive == PrimitiveType.uint64;
+ bool get isSigned => !isUnsigned;
+
+ String get name => primitiveNames[primitive.index];
+
+ String get cType => "${name}${isInteger ? "_t" : ""}";
+ String get dartCType => name.upperCaseFirst();
+ String get dartType => isInteger ? "int" : "double";
+ String get dartStructFieldAnnotation => "@${dartCType}()";
+ bool get hasSize => primitive != PrimitiveType.intptr;
+ int get size {
+ if (!hasSize) {
+ throw "Size unknown.";
+ }
+ return primitiveSizesInBytes[primitive.index];
+ }
+}
+
+class PointerType extends CType {
+ final CType pointerTo;
+
+ PointerType(this.pointerTo);
+
+ String get cType => "${pointerTo.cType}*";
+ String get dartCType => "Pointer<${pointerTo.dartCType}>";
+ String get dartType => "Pointer<${pointerTo.dartType}>";
+ String get dartStructFieldAnnotation => "";
+ bool get hasSize => false;
+ int get size => throw "Size unknown";
+}
+
+/// Used to give [StructType] fields and [FunctionType] arguments names.
+class Member {
+ final CType type;
+ final String name;
+
+ Member(this.type, this.name);
+
+ String dartStructField(bool nnbd) {
+ final modifier = nnbd ? "external" : "";
+ return "${type.dartStructFieldAnnotation} $modifier ${type.dartType} $name;";
+ }
+
+ String get cStructField => "${type.cType} $name;";
+
+ String toString() => "$type $name";
+}
+
+List<Member> generateMemberNames(List<CType> memberTypes) {
+ int index = 0;
+ List<Member> result = [];
+ for (final type in memberTypes) {
+ result.add(Member(type, "a$index"));
+ index++;
+ }
+ return result;
+}
+
+class StructType extends CType {
+ final List<Member> members;
+
+ /// To disambiguate same size structs.
+ final String suffix;
+
+ StructType(List<CType> memberTypes)
+ : this.members = generateMemberNames(memberTypes),
+ this.suffix = "";
+ StructType.disambiguate(List<CType> memberTypes, this.suffix)
+ : this.members = generateMemberNames(memberTypes);
+
+ List<CType> get memberTypes => members.map((a) => a.type).toList();
+
+ String get cType => name;
+ String get dartCType => name;
+ String get dartType => name;
+ String get dartStructFieldAnnotation => "";
+
+ bool get hasSize =>
+ !memberTypes.map((e) => e.hasSize).contains(false) && !hasPadding;
+ int get size => memberTypes.fold(0, (int acc, e) => acc + e.size);
+
+ /// Rough approximation, to not redo all ABI logic here.
+ bool get hasPadding =>
+ members.length < 2 ? false : members[0].type.size < members[1].type.size;
+
+ bool get hasNestedStructs =>
+ members.map((e) => e.type is StructType).contains(true);
+
+ /// All members have the same type.
+ bool get isHomogeneous => memberTypes.toSet().length == 1;
+
+ /// All members have a floating point type.
+ bool get isOnlyFloatingPoint => !memberTypes.map((e) {
+ if (e is FundamentalType) {
+ return e.isFloatingPoint;
+ }
+ if (e is StructType) {
+ return e.isOnlyFloatingPoint;
+ }
+ }).contains(false);
+
+ /// All members have a integer type.
+ bool get isOnlyInteger => !memberTypes.map((e) {
+ if (e is FundamentalType) {
+ return e.isInteger;
+ }
+ if (e is StructType) {
+ return e.isOnlyInteger;
+ }
+ }).contains(false);
+
+ bool get isMixed => !isOnlyInteger && !isOnlyFloatingPoint;
+
+ String get name {
+ String result = "Struct";
+ if (hasSize) {
+ result += "${size}Byte" + (size != 1 ? "s" : "");
+ }
+ if (hasNestedStructs) {
+ result += "Nested";
+ }
+ if (members.length == 0) {
+ // No suffix.
+ } else if (hasPadding) {
+ result += "Alignment${memberTypes[1].dartCType}";
+ } else if (isHomogeneous && members.length > 1 && !hasNestedStructs) {
+ result += "Homogeneous${memberTypes.first.dartCType}";
+ } else if (isOnlyFloatingPoint) {
+ result += "Float";
+ } else if (isOnlyInteger) {
+ result += "Int";
+ } else {
+ result += "Mixed";
+ }
+ result += suffix;
+ return result;
+ }
+}
+
+class FunctionType extends CType {
+ final List<Member> arguments;
+ final CType returnValue;
+ final String reason;
+
+ List<CType> get argumentTypes => arguments.map((a) => a.type).toList();
+
+ FunctionType(List<CType> argumentTypes, this.returnValue, this.reason)
+ : this.arguments = generateMemberNames(argumentTypes);
+
+ String get cType =>
+ throw "Are not represented without function or variable name in C.";
+
+ String get dartCType {
+ final argumentsDartCType = argumentTypes.map((e) => e.dartCType).join(", ");
+ return "${returnValue.dartCType} Function($argumentsDartCType)";
+ }
+
+ String get dartType {
+ final argumentsDartType = argumentTypes.map((e) => e.dartType).join(", ");
+ return "${returnValue.dartType} Function($argumentsDartType)";
+ }
+
+ String get dartStructFieldAnnotation => throw "No nested function pointers.";
+
+ bool get hasSize => false;
+ int get size => throw "Unknown size.";
+
+ /// Group consecutive [arguments] by same type.
+ ///
+ /// Used for naming.
+ List<List<Member>> get argumentsGrouped {
+ List<List<Member>> result = [];
+ for (final a in arguments) {
+ if (result.isEmpty) {
+ result.add([a]);
+ } else if (result.last.first.type.dartCType == a.type.dartCType) {
+ result.last.add(a);
+ } else {
+ result.add([a]);
+ }
+ }
+ return result;
+ }
+
+ /// A suitable name based on the signature.
+ String get cName {
+ String result = "";
+ if (arguments.containsStructs && returnValue is FundamentalType) {
+ result = "Pass";
+ } else if (returnValue is StructType &&
+ argumentTypes.contains(returnValue)) {
+ result = "ReturnStructArgument";
+ } else if (returnValue is StructType) {
+ if (arguments.length == (returnValue as StructType).members.length) {
+ return "Return${returnValue.dartCType}";
+ }
+ } else {
+ result = "Uncategorized";
+ }
+
+ for (final group in argumentsGrouped) {
+ result += group.first.type.dartCType;
+ if (group.length > 1) {
+ result += "x${group.length}";
+ }
+ }
+ return result.limitTo(50);
+ }
+
+ String get dartTestName => "test$cName";
+
+ String get dartName => cName.lowerCaseFirst();
+
+ /// Only valid for [TestType.structReturnArgument].
+ Member get structReturnArgument =>
+ arguments.firstWhere((a) => a.type == returnValue);
+}
+
+extension MemberList on List<Member> {
+ bool get containsStructs => map((m) => m.type is StructType).contains(true);
+}
diff --git a/tests/ffi_2/generator/structs_by_value_tests_confguration.dart b/tests/ffi_2/generator/structs_by_value_tests_confguration.dart
new file mode 100644
index 0000000..487a68e
--- /dev/null
+++ b/tests/ffi_2/generator/structs_by_value_tests_confguration.dart
@@ -0,0 +1,373 @@
+// Copyright (c) 2020, 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 'c_types.dart';
+
+final functions = [
+ FunctionType(List.filled(10, struct1byteInt), int64, """
+Smallest struct with data.
+10 struct arguments will exhaust available registers."""),
+ FunctionType(List.filled(10, struct3bytesInt), int64, """
+Not a multiple of word size, not a power of two.
+10 struct arguments will exhaust available registers."""),
+ FunctionType(List.filled(10, struct4bytesInt), int64, """
+Exactly word size on 32-bit architectures.
+10 struct arguments will exhaust available registers."""),
+ FunctionType(List.filled(10, struct7bytesInt), int64, """
+Sub word size on 64 bit architectures.
+10 struct arguments will exhaust available registers."""),
+ FunctionType(List.filled(10, struct8bytesInt), int64, """
+Exactly word size struct on 64bit architectures.
+10 struct arguments will exhaust available registers."""),
+ FunctionType(List.filled(10, struct8bytesFloat), float, """
+Arguments passed in FP registers as long as they fit.
+10 struct arguments will exhaust available registers."""),
+ FunctionType(List.filled(10, struct8BytesMixed), float, """
+On x64, arguments go in int registers because it is not only float.
+10 struct arguments will exhaust available registers."""),
+ FunctionType(List.filled(10, struct9bytesInt), int64, """
+Argument is a single byte over a multiple of word size.
+10 struct arguments will exhaust available registers.
+Tests upper bytes in the integer registers that are partly filled.
+Tests stack alignment of non word size stack arguments."""),
+ FunctionType(List.filled(10, struct9bytesInt2), int64, """
+Argument is a single byte over a multiple of word size.
+10 struct arguments will exhaust available registers.
+Struct only has 1-byte aligned fields to test struct alignment itself.
+"""),
+ FunctionType(List.filled(6, struct12bytesFloat), float, """
+Arguments in FPU registers on arm hardfp and arm64.
+Struct arguments will exhaust available registers, and leave some empty.
+The last argument is to test whether arguments are backfilled."""),
+ FunctionType(List.filled(5, struct16bytesFloat), float, """
+On Linux x64 argument is transferred on stack because it is over 16 bytes.
+Arguments in FPU registers on arm hardfp and arm64.
+5 struct arguments will exhaust available registers."""),
+ FunctionType(List.filled(10, struct16bytesMixed), double_, """
+On x64, arguments are split over FP and int registers.
+On x64, it will exhaust the integer registers with the 6th argument.
+The rest goes on the stack.
+On arm, arguments are 8 byte aligned."""),
+ FunctionType(List.filled(10, struct16bytesMixed2), float, """
+On x64, arguments are split over FP and int registers.
+On x64, it will exhaust the integer registers with the 6th argument.
+The rest goes on the stack.
+On arm, arguments are 4 byte aligned."""),
+ FunctionType(List.filled(10, struct17bytesInt), int64, """
+Arguments are passed as pointer to copy on arm64.
+Tests that the memory allocated for copies are rounded up to word size."""),
+ FunctionType(List.filled(10, struct19bytesInt), int64, """
+The minimum alignment of this struct is only 1 byte based on its fields.
+Test that the memory backing these structs is extended to the right size.
+"""),
+ FunctionType(List.filled(10, struct20bytesInt), int32, """
+Argument too big to go into integer registers on arm64.
+The arguments are passed as pointers to copies.
+The amount of arguments exhausts the number of integer registers, such that
+pointers to copies are also passed on the stack."""),
+ FunctionType(
+ [struct20bytesFloat],
+ float,
+ """
+Argument too big to go into FPU registers in hardfp and arm64."""),
+ FunctionType(List.filled(5, struct32bytesDouble), double_, """
+Arguments in FPU registers on arm64.
+5 struct arguments will exhaust available registers."""),
+ FunctionType(
+ [struct40bytesDouble],
+ double_,
+ """
+Argument too big to go into FPU registers in arm64."""),
+ FunctionType(
+ [struct1024bytesInt],
+ uint64,
+ """
+Test 1kb struct."""),
+ FunctionType(
+ [
+ float,
+ struct16bytesFloat,
+ float,
+ struct16bytesFloat,
+ float,
+ struct16bytesFloat,
+ float,
+ struct16bytesFloat,
+ float
+ ],
+ float,
+ """
+Tests the alignment of structs in FPU registers and backfilling."""),
+ FunctionType(
+ [
+ float,
+ struct32bytesDouble,
+ float,
+ struct32bytesDouble,
+ float,
+ struct32bytesDouble,
+ float,
+ struct32bytesDouble,
+ float
+ ],
+ double_,
+ """
+Tests the alignment of structs in FPU registers and backfilling."""),
+ FunctionType(
+ [
+ int8,
+ struct16bytesMixed,
+ int8,
+ struct16bytesMixed,
+ int8,
+ struct16bytesMixed,
+ int8,
+ struct16bytesMixed,
+ int8
+ ],
+ double_,
+ """
+Tests the alignment of structs in integers registers and on the stack.
+Arm32 aligns this struct at 8.
+Also, arm32 allocates the second struct partially in registers, partially
+on stack.
+Test backfilling of integer registers."""),
+ FunctionType(
+ [
+ double_,
+ double_,
+ double_,
+ double_,
+ double_,
+ double_,
+ struct16bytesMixed,
+ struct16bytesMixed,
+ struct16bytesMixed,
+ struct16bytesMixed,
+ int32,
+ ],
+ double_,
+ """
+On Linux x64, it will exhaust xmm registers first, after 6 doubles and 2
+structs. The rest of the structs will go on the stack.
+The int will be backfilled into the int register."""),
+ FunctionType(
+ [
+ int32,
+ int32,
+ int32,
+ int32,
+ struct16bytesMixed,
+ struct16bytesMixed,
+ struct16bytesMixed,
+ struct16bytesMixed,
+ double_,
+ ],
+ double_,
+ """
+On Linux x64, it will exhaust int registers first.
+The rest of the structs will go on the stack.
+The double will be backfilled into the xmm register."""),
+ FunctionType(
+ [
+ struct40bytesDouble,
+ struct4bytesInt,
+ struct8bytesFloat,
+ ],
+ double_,
+ """
+On various architectures, first struct is allocated on stack.
+Check that the other two arguments are allocated on registers."""),
+ FunctionType(
+ [structAlignmentInt16],
+ int64,
+ """
+Test alignment and padding of 16 byte int within struct."""),
+ FunctionType(
+ [structAlignmentInt32],
+ int64,
+ """
+Test alignment and padding of 32 byte int within struct."""),
+ FunctionType(
+ [structAlignmentInt64],
+ int64,
+ """
+Test alignment and padding of 64 byte int within struct."""),
+ FunctionType(struct1byteInt.memberTypes, struct1byteInt, """
+Smallest struct with data."""),
+ FunctionType(struct3bytesInt.memberTypes, struct3bytesInt, """
+Smaller than word size return value on all architectures."""),
+ FunctionType(struct4bytesInt.memberTypes, struct4bytesInt, """
+Word size return value on 32 bit architectures.."""),
+ FunctionType(struct7bytesInt.memberTypes, struct7bytesInt, """
+Non-wordsize return value."""),
+ FunctionType(struct8bytesInt.memberTypes, struct8bytesInt, """
+Return value in integer registers on many architectures."""),
+ FunctionType(struct8bytesFloat.memberTypes, struct8bytesFloat, """
+Return value in FP registers on many architectures."""),
+ FunctionType(struct8BytesMixed.memberTypes, struct8BytesMixed, """
+Return value split over FP and integer register in x64."""),
+ FunctionType(struct9bytesInt.memberTypes, struct9bytesInt, """
+Return value in two integer registers on x64.
+The second register only contains a single byte."""),
+ FunctionType(struct9bytesInt2.memberTypes, struct9bytesInt2, """
+The minimum alignment of this struct is only 1 byte based on its fields.
+Test that the memory backing these structs is the right size and that
+dart:ffi trampolines do not write outside this size."""),
+ FunctionType(struct12bytesFloat.memberTypes, struct12bytesFloat, """
+Return value in FPU registers, but does not use all registers on arm hardfp
+and arm64."""),
+ FunctionType(struct16bytesFloat.memberTypes, struct16bytesFloat, """
+Return value in FPU registers on arm hardfp and arm64."""),
+ FunctionType(struct16bytesMixed.memberTypes, struct16bytesMixed, """
+Return value split over FP and integer register in x64."""),
+ FunctionType(struct16bytesMixed2.memberTypes, struct16bytesMixed2, """
+Return value split over FP and integer register in x64.
+The integer register contains half float half int."""),
+ FunctionType(struct17bytesInt.memberTypes, struct17bytesInt, """
+Rerturn value returned in preallocated space passed by pointer on most ABIs.
+Is non word size on purpose, to test that structs are rounded up to word size
+on all ABIs."""),
+ FunctionType(struct19bytesInt.memberTypes, struct19bytesInt, """
+The minimum alignment of this struct is only 1 byte based on its fields.
+Test that the memory backing these structs is the right size and that
+dart:ffi trampolines do not write outside this size."""),
+ FunctionType(struct20bytesInt.memberTypes, struct20bytesInt, """
+Return value too big to go in cpu registers on arm64."""),
+ FunctionType(struct20bytesFloat.memberTypes, struct20bytesFloat, """
+Return value too big to go in FPU registers on x64, arm hardfp and arm64."""),
+ FunctionType(struct32bytesDouble.memberTypes, struct32bytesDouble, """
+Return value in FPU registers on arm64."""),
+ FunctionType(struct40bytesDouble.memberTypes, struct40bytesDouble, """
+Return value too big to go in FPU registers on arm64."""),
+ FunctionType(struct1024bytesInt.memberTypes, struct1024bytesInt, """
+Test 1kb struct."""),
+ FunctionType(
+ [struct1byteInt],
+ struct1byteInt,
+ """
+Test that a struct passed in as argument can be returned.
+Especially for ffi callbacks.
+Struct is passed in int registers in most ABIs."""),
+ FunctionType(
+ [int32, int32, int32, int32, int32, int32, int32, int32, struct1byteInt],
+ struct1byteInt,
+ """
+Test that a struct passed in as argument can be returned.
+Especially for ffi callbacks.
+Struct is passed on stack on all ABIs."""),
+ FunctionType(
+ [struct8bytesFloat],
+ struct8bytesFloat,
+ """
+Test that a struct passed in as argument can be returned.
+Especially for ffi callbacks.
+Struct is passed in float registers in most ABIs."""),
+ FunctionType(
+ [struct20bytesInt],
+ struct20bytesInt,
+ """
+On arm64, both argument and return value are passed in by pointer."""),
+ FunctionType(
+ [
+ int32,
+ int32,
+ int32,
+ int32,
+ int32,
+ int32,
+ int32,
+ int32,
+ struct20bytesInt
+ ],
+ struct20bytesInt,
+ """
+On arm64, both argument and return value are passed in by pointer.
+Ints exhaust registers, so that pointer is passed on stack."""),
+ FunctionType(structAlignmentInt16.memberTypes, structAlignmentInt16, """
+Test alignment and padding of 16 byte int within struct."""),
+ FunctionType(structAlignmentInt32.memberTypes, structAlignmentInt32, """
+Test alignment and padding of 32 byte int within struct."""),
+ FunctionType(structAlignmentInt64.memberTypes, structAlignmentInt64, """
+Test alignment and padding of 64 byte int within struct."""),
+];
+
+final structs = [
+ struct0bytes,
+ struct1byteInt,
+ struct3bytesInt,
+ struct4bytesInt,
+ struct7bytesInt,
+ struct8bytesInt,
+ struct8bytesFloat,
+ struct8BytesMixed,
+ struct9bytesInt,
+ struct9bytesInt2,
+ struct12bytesFloat,
+ struct16bytesFloat,
+ struct16bytesMixed,
+ struct16bytesMixed2,
+ struct17bytesInt,
+ struct19bytesInt,
+ struct20bytesInt,
+ struct20bytesFloat,
+ struct32bytesDouble,
+ struct40bytesDouble,
+ struct1024bytesInt,
+ structAlignmentInt16,
+ structAlignmentInt32,
+ structAlignmentInt64,
+];
+
+/// Using empty structs is undefined behavior in C.
+final struct0bytes = StructType([]);
+
+final struct1byteInt = StructType([int8]);
+final struct3bytesInt = StructType([int16, int8]);
+final struct4bytesInt = StructType([int16, int16]);
+final struct7bytesInt = StructType([int32, int16, int8]);
+final struct8bytesInt = StructType([int16, int16, int32]);
+final struct8bytesFloat = StructType([float, float]);
+final struct8BytesMixed = StructType([float, int16, int16]);
+final struct9bytesInt = StructType([int64, int8]);
+final struct9bytesInt2 = StructType.disambiguate(List.filled(9, uint8), "2");
+final struct12bytesFloat = StructType([float, float, float]);
+
+/// The largest homogenous float that goes into FPU registers on softfp and
+/// arm64.
+final struct16bytesFloat = StructType([float, float, float, float]);
+
+/// This struct will be 8 byte aligned on arm.
+final struct16bytesMixed = StructType([double_, int64]);
+
+/// This struct will be 4 byte aligned on arm.
+final struct16bytesMixed2 =
+ StructType.disambiguate([float, float, float, int32], "2");
+
+final struct17bytesInt = StructType([int64, int64, int8]);
+
+/// This struct has only 1 byte field-alignmnent requirements.
+final struct19bytesInt = StructType(List.filled(19, uint8));
+
+/// The first homogenous integer struct that does not go into registers
+/// anymore on arm64.
+final struct20bytesInt = StructType([int32, int32, int32, int32, int32]);
+
+/// The first homogenous float that does not go into FPU registers anymore on
+/// softfp and arm64.
+final struct20bytesFloat = StructType([float, float, float, float, float]);
+
+/// Largest homogenous doubles in arm64 that goes into FPU registers.
+final struct32bytesDouble = StructType([double_, double_, double_, double_]);
+
+/// The first homogenous doubles that does not go into FPU registers anymore on
+/// arm64.
+final struct40bytesDouble =
+ StructType([double_, double_, double_, double_, double_]);
+
+final struct1024bytesInt = StructType(List.filled(128, uint64));
+
+final structAlignmentInt16 = StructType([int8, int16, int8]);
+final structAlignmentInt32 = StructType([int8, int32, int8]);
+final structAlignmentInt64 = StructType([int8, int64, int8]);
diff --git a/tests/ffi_2/generator/structs_by_value_tests_generator.dart b/tests/ffi_2/generator/structs_by_value_tests_generator.dart
new file mode 100644
index 0000000..e233753
--- /dev/null
+++ b/tests/ffi_2/generator/structs_by_value_tests_generator.dart
@@ -0,0 +1,930 @@
+// Copyright (c) 2020, 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 'dart:io';
+
+import 'c_types.dart';
+import 'structs_by_value_tests_confguration.dart';
+import 'utils.dart';
+
+/// The test type determines how to convert the arguments into return values
+/// such that the caller knows what to check.
+enum TestType {
+ /// Tested by getting all the individual fields out of the structs and
+ /// summing their values.
+ structArguments,
+
+ /// Tested by passing assigning the arguments to the struct fields.
+ structReturn,
+
+ /// Tested by returning the struct passed in.
+ structReturnArgument,
+}
+
+extension on FunctionType {
+ TestType get testType {
+ if (arguments.containsStructs && returnValue is FundamentalType) {
+ return TestType.structArguments;
+ }
+ if (returnValue is StructType && argumentTypes.contains(returnValue)) {
+ return TestType.structReturnArgument;
+ }
+ if (returnValue is StructType) {
+ if (arguments.length == (returnValue as StructType).members.length) {
+ return TestType.structReturn;
+ }
+ }
+ throw Exception("Unknown test type: $this");
+ }
+}
+
+/// We use the class structure as an algebraic data type in order to keep the
+/// relevant parts of the code generation closer together.
+extension on CType {
+ /// The part of the cout expression after `std::cout` and before the `;`.
+ String coutExpression(String variableName) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ if (this == uint8 || this == int8) {
+ return "<< static_cast<int>($variableName)";
+ }
+ return "<< $variableName";
+
+ case StructType:
+ final this_ = this as StructType;
+ return this_.members.coutExpression("$variableName.");
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+
+ /// A statement recursively outputting all members.
+ String coutStatement(String variableName) {
+ final coutExpr = this.coutExpression(variableName);
+ return 'std::cout << "$variableName = " $coutExpr << "\\n";';
+ }
+}
+
+extension on List<Member> {
+ /// The part of the cout expression after `std::cout` and before the `;`.
+ String coutExpression([String namePrefix = ""]) {
+ String result = '<< "("';
+ result += this
+ .map((m) => m.type.coutExpression("$namePrefix${m.name}"))
+ .join('<< ", "');
+ result += '<< ")"';
+ return result.trimCouts();
+ }
+}
+
+extension on CType {
+ /// A list of statements adding all members recurisvely to `result`.
+ ///
+ /// Both valid in Dart and C.
+ String addToResultStatements(String variableName) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ return "result += $variableName;\n";
+
+ case StructType:
+ final this_ = this as StructType;
+ return this_.members.addToResultStatements("$variableName.");
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+}
+
+extension on List<Member> {
+ /// A list of statements adding all members recurisvely to `result`.
+ ///
+ /// Both valid in Dart and C.
+ String addToResultStatements([String namePrefix = ""]) {
+ return map((m) => m.type.addToResultStatements("$namePrefix${m.name}"))
+ .join();
+ }
+}
+
+extension on CType {
+ /// A list of statements recursively assigning all members with [a].
+ ///
+ /// Both valid in Dart and C.
+ String assignValueStatements(ArgumentValueAssigner a, String variableName) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ final this_ = this as FundamentalType;
+ return "$variableName = ${a.nextValue(this_)};\n";
+
+ case StructType:
+ final this_ = this as StructType;
+ return this_.members.assignValueStatements(a, "$variableName.");
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+
+ /// A list of statements recursively coping all members from [source].
+ ///
+ /// Both valid in Dart and C.
+ String copyValueStatements(String source, String destination) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ return "$destination = $source;\n";
+
+ case StructType:
+ final this_ = this as StructType;
+ return this_.members.copyValueStatements("$source.", "$destination.");
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+}
+
+extension on List<Member> {
+ /// A list of statements recursively assigning all members with [a].
+ ///
+ /// Both valid in Dart and C.
+ String assignValueStatements(ArgumentValueAssigner a,
+ [String namePrefix = ""]) {
+ return map((m) => m.type.assignValueStatements(a, "$namePrefix${m.name}"))
+ .join();
+ }
+
+ /// A list of statements recursively coping all members from [source].
+ ///
+ /// Both valid in Dart and C.
+ String copyValueStatements([sourcePrefix = "", destinationPrefix = ""]) {
+ return map((m) => m.type.copyValueStatements(
+ "$sourcePrefix${m.name}", "$destinationPrefix${m.name}")).join();
+ }
+}
+
+/// A helper class that assigns values to fundamental types.
+///
+/// Also keeps track of a sum of all values, to be used for testing the result.
+class ArgumentValueAssigner {
+ int i = 1;
+ int sum = 0;
+ String nextValue(FundamentalType type) {
+ int argumentValue = i;
+ i++;
+ if (type.isSigned && i % 2 == 0) {
+ argumentValue = -argumentValue;
+ }
+ sum += argumentValue;
+ if (type.isFloatingPoint) {
+ return argumentValue.toDouble().toString();
+ } else {
+ return argumentValue.toString();
+ }
+ }
+
+ String sumValue(FundamentalType type) {
+ if (type.isFloatingPoint) {
+ return sum.toDouble().toString();
+ } else {
+ return sum.toString();
+ }
+ }
+}
+
+extension on CType {
+ /// A list of Dart statements recursively allocating all members.
+ String dartAllocateStatements(String variableName) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ return "${dartType} ${variableName};\n";
+
+ case StructType:
+ return "${dartType} ${variableName} = allocate<$dartType>().ref;\n";
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+
+ /// A list of Dart statements allocating as zero or nullptr.
+ String dartAllocateZeroStatements(String variableName) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ final this_ = this as FundamentalType;
+ if (this_.isInteger) {
+ return "${dartType} ${variableName} = 0;\n";
+ }
+ return "${dartType} ${variableName} = 0.0;\n";
+
+ case StructType:
+ return "${dartType} ${variableName} = ${dartType}();\n";
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+}
+
+extension on List<Member> {
+ /// A list of Dart statements recursively allocating all members.
+ String dartAllocateStatements([String namePrefix = ""]) {
+ return map((m) => m.type.dartAllocateStatements("$namePrefix${m.name}"))
+ .join();
+ }
+
+ /// A list of Dart statements as zero or nullptr.
+ String dartAllocateZeroStatements([String namePrefix = ""]) {
+ return map((m) => m.type.dartAllocateZeroStatements("$namePrefix${m.name}"))
+ .join();
+ }
+}
+
+extension on CType {
+ /// A list of Dart statements recursively freeing all members.
+ String dartFreeStatements(String variableName) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ return "";
+
+ case StructType:
+ return "free($variableName.addressOf);\n";
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+}
+
+extension on List<Member> {
+ /// A list of Dart statements recursively freeing all members.
+ String dartFreeStatements([String namePrefix = ""]) {
+ return map((m) => m.type.dartFreeStatements("$namePrefix${m.name}")).join();
+ }
+}
+
+extension on CType {
+ /// A list of C statements recursively allocating all members.
+ String cAllocateStatements(String variableName) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ case StructType:
+ return "${cType} ${variableName};\n";
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+}
+
+extension on List<Member> {
+ /// A list of C statements recursively allocating all members.
+ String cAllocateStatements([String namePrefix = ""]) {
+ return map((m) => m.type.cAllocateStatements("$namePrefix${m.name}"))
+ .join();
+ }
+}
+
+extension on CType {
+ /// A list of Dart statements recursively checking all members.
+ String dartExpectsStatements(String expected, String actual) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ final this_ = this as FundamentalType;
+ if (this_.isInteger) {
+ return "Expect.equals(${expected}, ${actual});";
+ }
+ assert(this_.isFloatingPoint);
+ return "Expect.approxEquals(${expected}, ${actual});";
+
+ case StructType:
+ final this_ = this as StructType;
+ return this_.members.dartExpectsStatements("$expected.", "$actual.");
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+}
+
+extension on List<Member> {
+ /// A list of Dart statements recursively checking all members.
+ String dartExpectsStatements(
+ [String expectedPrefix = "", String actualPrefix = ""]) {
+ return map((m) => m.type.dartExpectsStatements(
+ "$expectedPrefix${m.name}", "$actualPrefix${m.name}")).join();
+ }
+}
+
+extension on CType {
+ /// A list of C statements recursively checking all members.
+ String cExpectsStatements(String expected, String actual) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ final this_ = this as FundamentalType;
+ if (this_.isInteger) {
+ return "CHECK_EQ(${expected}, ${actual});";
+ }
+ assert(this_.isFloatingPoint);
+ return "CHECK_APPROX(${expected}, ${actual});";
+
+ case StructType:
+ final this_ = this as StructType;
+ return this_.members.cExpectsStatements("$expected.", "$actual.");
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+
+ /// A list of C statements recursively checking all members for zero.
+ String cExpectsZeroStatements(String actual) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ final this_ = this as FundamentalType;
+ if (this_.isInteger) {
+ return "CHECK_EQ(0, ${actual});";
+ }
+ assert(this_.isFloatingPoint);
+ return "CHECK_APPROX(0.0, ${actual});";
+
+ case StructType:
+ final this_ = this as StructType;
+ return this_.members.cExpectsZeroStatements("$actual.");
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+}
+
+extension on List<Member> {
+ /// A list of C statements recursively checking all members.
+ String cExpectsStatements(
+ [String expectedPrefix = "", String actualPrefix = ""]) {
+ return map((m) => m.type.cExpectsStatements(
+ "$expectedPrefix${m.name}", "$actualPrefix${m.name}")).join();
+ }
+
+ /// A list of C statements recursively checking all members for zero.
+ String cExpectsZeroStatements([String actualPrefix = ""]) {
+ return map((m) => m.type.cExpectsZeroStatements("$actualPrefix${m.name}"))
+ .join();
+ }
+}
+
+extension on CType {
+ /// Expression denoting the first FundamentalType field.
+ ///
+ /// Both valid in Dart and C.
+ String firstArgumentName(String variableName) {
+ switch (this.runtimeType) {
+ case FundamentalType:
+ return variableName;
+
+ case StructType:
+ final this_ = this as StructType;
+ return this_.members.firstArgumentName("$variableName.");
+ }
+
+ throw Exception("Not implemented for ${this.runtimeType}");
+ }
+}
+
+extension on List<Member> {
+ /// Expression denoting the first FundamentalType field.
+ ///
+ /// Both valid in Dart and C.
+ String firstArgumentName([String prefix = ""]) {
+ return this[0].type.firstArgumentName("$prefix${this[0].name}");
+ }
+}
+
+extension on StructType {
+ String dartClass(bool nnbd) {
+ String dartFields = "";
+ for (final member in members) {
+ dartFields += "${member.dartStructField(nnbd)}\n\n";
+ }
+ String toStringBody = members.map((m) => "\$\{${m.name}\}").join(", ");
+ return """
+ class $name extends Struct {
+ $dartFields
+
+ String toString() => "($toStringBody)";
+ }
+ """;
+ }
+
+ String get cDefinition {
+ String cFields = "";
+ for (final member in members) {
+ cFields += " ${member.cStructField}\n";
+ }
+ return """
+ struct $name {
+ $cFields
+ };
+
+ """;
+ }
+}
+
+extension on FunctionType {
+ String get dartCallCode {
+ final a = ArgumentValueAssigner();
+ final assignValues = arguments.assignValueStatements(a);
+ final argumentFrees = arguments.dartFreeStatements();
+
+ final argumentNames = arguments.map((e) => e.name).join(", ");
+
+ String expects;
+ switch (testType) {
+ case TestType.structArguments:
+ // Check against sum value.
+ final expectedResult = a.sumValue(returnValue as FundamentalType);
+ expects = returnValue.dartExpectsStatements(expectedResult, "result");
+ break;
+ case TestType.structReturn:
+ // Check against input arguments.
+ expects = arguments.dartExpectsStatements("", "result.");
+ break;
+ case TestType.structReturnArgument:
+ expects = returnValue.dartExpectsStatements(
+ structReturnArgument.name, "result");
+ break;
+ }
+
+ return """
+ final $dartName =
+ ffiTestFunctions.lookupFunction<$dartCType, $dartType>("$cName");
+
+ ${reason.makeDartDocComment()}
+ void $dartTestName() {
+ ${arguments.dartAllocateStatements()}
+
+ ${assignValues}
+
+ final result = $dartName($argumentNames);
+
+ print("result = \$result");
+
+ $expects
+
+ $argumentFrees
+ }
+ """;
+ }
+
+ String dartCallbackCode(bool nnbd) {
+ final argumentss =
+ arguments.map((a) => "${a.type.dartType} ${a.name}").join(", ");
+
+ final prints = arguments.map((a) => "\$\{${a.name}\}").join(", ");
+
+ String buildReturnValue = "";
+ switch (testType) {
+ case TestType.structArguments:
+ // Sum all input values.
+ buildReturnValue = """
+ ${returnValue.dartType} result = 0;
+
+ ${arguments.addToResultStatements('${dartName}_')}
+ """;
+ break;
+ case TestType.structReturn:
+ // Allocate a struct.
+ buildReturnValue = """
+ ${returnValue.dartType} result = allocate<${returnValue.dartType}>().ref;
+
+ ${arguments.copyValueStatements("${dartName}_", "result.")}
+ """;
+ break;
+ case TestType.structReturnArgument:
+ buildReturnValue = """
+ ${returnValue.cType} result = ${dartName}_${structReturnArgument.name};
+ """;
+ break;
+ }
+
+ final globals = arguments.dartAllocateZeroStatements("${dartName}_");
+
+ final copyToGlobals =
+ arguments.map((a) => '${dartName}_${a.name} = ${a.name};').join("\n");
+
+ // Simulate assigning values the same way as in C, so that we know what the
+ // final return value should be.
+ final a = ArgumentValueAssigner();
+ arguments.assignValueStatements(a);
+ String afterCallbackExpects = "";
+ String afterCallbackFrees = "";
+ switch (testType) {
+ case TestType.structArguments:
+ // Check that the input structs are still available.
+ // Check against sum value.
+ final expectedResult = a.sumValue(returnValue as FundamentalType);
+ afterCallbackExpects =
+ returnValue.dartExpectsStatements(expectedResult, "result");
+ break;
+ case TestType.structReturn:
+ // We're passing allocating structs in [buildReturnValue].
+ afterCallbackFrees =
+ returnValue.dartFreeStatements("${dartName}Result");
+ break;
+ case TestType.structReturnArgument:
+ break;
+ }
+
+ String returnNull = "";
+ if (!nnbd) {
+ returnNull = """
+ if (${arguments.firstArgumentName()} == $returnNullValue) {
+ print("returning null!");
+ return null;
+ }
+ """;
+ }
+
+ return """
+ typedef ${cName}Type = $dartCType;
+
+ // Global variables to be able to test inputs after callback returned.
+ $globals
+
+ // Result variable also global, so we can delete it after the callback.
+ ${returnValue.dartAllocateZeroStatements("${dartName}Result")}
+
+ ${returnValue.dartType} ${dartName}CalculateResult() {
+ $buildReturnValue
+
+ ${dartName}Result = result;
+
+ return result;
+ }
+
+ ${reason.makeDartDocComment()}
+ ${returnValue.dartType} $dartName($argumentss) {
+ print("$dartName($prints)");
+
+ // In legacy mode, possibly return null.
+ $returnNull
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (${arguments.firstArgumentName()} == $throwExceptionValue ||
+ ${arguments.firstArgumentName()} == $returnNullValue) {
+ print("throwing!");
+ throw Exception("$cName throwing on purpuse!");
+ }
+
+ $copyToGlobals
+
+ final result = ${dartName}CalculateResult();
+
+ print(\"result = \$result\");
+
+ return result;
+ }
+
+ void ${dartName}AfterCallback() {
+ $afterCallbackFrees
+
+ final result = ${dartName}CalculateResult();
+
+ print(\"after callback result = \$result\");
+
+ $afterCallbackExpects
+
+ $afterCallbackFrees
+ }
+
+ """;
+ }
+
+ String get dartCallbackTestConstructor {
+ String exceptionalReturn = "";
+ if (returnValue is FundamentalType) {
+ if ((returnValue as FundamentalType).isFloatingPoint) {
+ exceptionalReturn = ", 0.0";
+ } else {
+ exceptionalReturn = ", 0";
+ }
+ }
+ return """
+ CallbackTest.withCheck("$cName",
+ Pointer.fromFunction<${cName}Type>($dartName$exceptionalReturn),
+ ${dartName}AfterCallback),
+ """;
+ }
+
+ String get cCallCode {
+ String body = "";
+ switch (testType) {
+ case TestType.structArguments:
+ body = """
+ ${returnValue.cType} result = 0;
+
+ ${arguments.addToResultStatements()}
+ """;
+ break;
+ case TestType.structReturn:
+ body = """
+ ${returnValue.cType} result;
+
+ ${arguments.copyValueStatements("", "result.")}
+ """;
+ break;
+ case TestType.structReturnArgument:
+ body = """
+ ${returnValue.cType} result = ${structReturnArgument.name};
+ """;
+ break;
+ }
+
+ final argumentss =
+ arguments.map((e) => "${e.type.cType} ${e.name}").join(", ");
+
+ return """
+ // Used for testing structs by value.
+ ${reason.makeCComment()}
+ DART_EXPORT ${returnValue.cType} $cName($argumentss) {
+ std::cout << \"$cName\" ${arguments.coutExpression()} << \"\\n\";
+
+ $body
+
+ ${returnValue.coutStatement("result")}
+
+ return result;
+ }
+
+ """;
+ }
+
+ String get cCallbackCode {
+ final a = ArgumentValueAssigner();
+ final argumentAllocations = arguments.cAllocateStatements();
+ final assignValues = arguments.assignValueStatements(a);
+
+ final argumentss =
+ arguments.map((e) => "${e.type.cType} ${e.name}").join(", ");
+
+ final argumentNames = arguments.map((e) => e.name).join(", ");
+
+ String expects = "";
+ String expectsZero = "";
+ switch (testType) {
+ case TestType.structArguments:
+ // Check against sum value.
+ final returnValue_ = returnValue as FundamentalType;
+ final expectedResult = a.sumValue(returnValue_);
+ expects = returnValue.cExpectsStatements(expectedResult, "result");
+
+ expectsZero = returnValue.cExpectsZeroStatements("result");
+ break;
+ case TestType.structReturn:
+ // Check against input statements.
+ expects = arguments.cExpectsStatements("", "result.");
+
+ expectsZero = arguments.cExpectsZeroStatements("result.");
+ break;
+ case TestType.structReturnArgument:
+ // Check against input struct fields.
+ expects =
+ returnValue.cExpectsStatements(structReturnArgument.name, "result");
+
+ expectsZero = returnValue.cExpectsZeroStatements("result");
+ break;
+ }
+
+ return """
+ // Used for testing structs by value.
+ ${reason.makeCComment()}
+ DART_EXPORT intptr_t
+ Test$cName(
+ // NOLINTNEXTLINE(whitespace/parens)
+ ${returnValue.cType} (*f)($argumentss)) {
+ $argumentAllocations
+
+ $assignValues
+
+ std::cout << \"Calling Test$cName(\" ${arguments.coutExpression()} << \")\\n\";
+
+ ${returnValue.cType} result = f($argumentNames);
+
+ ${returnValue.coutStatement("result")}
+
+ $expects
+
+ // Pass argument that will make the Dart callback throw.
+ ${arguments.firstArgumentName()} = $throwExceptionValue;
+
+ result = f($argumentNames);
+
+ $expectsZero
+
+ // Pass argument that will make the Dart callback return null.
+ ${arguments.firstArgumentName()} = $returnNullValue;
+
+ result = f($argumentNames);
+
+ $expectsZero
+
+ return 0;
+ }
+
+ """;
+ }
+}
+
+/// Some value between 0 and 127 (works in every native type).
+const throwExceptionValue = 42;
+
+/// Some value between 0 and 127 (works in every native type).
+const returnNullValue = 84;
+
+const headerDartCallTest = """
+// Copyright (c) 2020, 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.
+//
+// This file has been automatically generated. Please do not edit it manually.
+//
+// SharedObjects=ffi_test_functions
+// VMOptions=
+// VMOptions=--deterministic --optimization-counter-threshold=5
+// VMOptions=--use-slow-path
+// VMOptions=--use-slow-path --stacktrace-every=100
+
+import 'dart:ffi';
+
+import "package:expect/expect.dart";
+import "package:ffi/ffi.dart";
+
+import 'dylib_utils.dart';
+
+final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
+""";
+
+void writeDartCallTest() {
+ for (bool nnbd in [true, false]) {
+ final StringBuffer buffer = StringBuffer();
+ buffer.write(headerDartCallTest);
+
+ buffer.write("""
+ void main() {
+ for (int i = 0; i < 10; ++i) {
+ ${functions.map((e) => "${e.dartTestName}();").join("\n")}
+ }
+ }
+ """);
+ buffer.writeAll(structs.map((e) => e.dartClass(nnbd)));
+ buffer.writeAll(functions.map((e) => e.dartCallCode));
+
+ final path = callTestPath(nnbd);
+ File(path).writeAsStringSync(buffer.toString());
+ Process.runSync("dartfmt", ["-w", path]);
+ }
+}
+
+String callTestPath(bool nnbd) {
+ final folder = nnbd ? "ffi" : "ffi_2";
+ return Platform.script
+ .resolve("../../$folder/function_structs_by_value_generated_test.dart")
+ .path;
+}
+
+const headerDartCallbackTest = """
+// Copyright (c) 2020, 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.
+//
+// This file has been automatically generated. Please do not edit it manually.
+//
+// SharedObjects=ffi_test_functions
+// VMOptions=
+// VMOptions=--deterministic --optimization-counter-threshold=10
+// VMOptions=--use-slow-path
+// VMOptions=--use-slow-path --stacktrace-every=100
+
+import 'dart:ffi';
+
+import "package:expect/expect.dart";
+import "package:ffi/ffi.dart";
+
+import 'callback_tests_utils.dart';
+
+// Reuse the struct classes.
+import 'function_structs_by_value_generated_test.dart';
+
+
+void main() {
+ testCases.forEach((t) {
+ print("==== Running " + t.name);
+ t.run();
+ });
+}
+
+
+""";
+
+void writeDartCallbackTest() {
+ for (bool nnbd in [true, false]) {
+ final StringBuffer buffer = StringBuffer();
+ buffer.write(headerDartCallbackTest);
+
+ buffer.write("""
+ final testCases = [
+ ${functions.map((e) => e.dartCallbackTestConstructor).join("\n")}
+ ];
+ """);
+
+ buffer.writeAll(functions.map((e) => e.dartCallbackCode(nnbd)));
+
+ final path = callbackTestPath(nnbd);
+ File(path).writeAsStringSync(buffer.toString());
+ Process.runSync("dartfmt", ["-w", path]);
+ }
+}
+
+String callbackTestPath(bool nnbd) {
+ final folder = nnbd ? "ffi" : "ffi_2";
+ return Platform.script
+ .resolve(
+ "../../$folder/function_callbacks_structs_by_value_generated_test.dart")
+ .path;
+}
+
+const headerC = """
+// Copyright (c) 2020, 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.
+//
+// This file has been automatically generated. Please do not edit it manually.
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include <cmath>
+#include <iostream>
+#include <limits>
+
+#if defined(_WIN32)
+#define DART_EXPORT extern "C" __declspec(dllexport)
+#else
+#define DART_EXPORT \\
+ extern "C" __attribute__((visibility("default"))) __attribute((used))
+#endif
+
+namespace dart {
+
+#define CHECK(X) \\
+ if (!(X)) { \\
+ fprintf(stderr, "%s\\n", "Check failed: " #X); \\
+ return 1; \\
+ }
+
+#define CHECK_EQ(X, Y) CHECK((X) == (Y))
+
+// Works for positive, negative and zero.
+#define CHECK_APPROX(EXPECTED, ACTUAL) \\
+ CHECK(((EXPECTED * 0.99) <= (ACTUAL) && (EXPECTED * 1.01) >= (ACTUAL)) || \\
+ ((EXPECTED * 0.99) >= (ACTUAL) && (EXPECTED * 1.01) <= (ACTUAL)))
+
+""";
+
+const footerC = """
+
+} // namespace dart
+""";
+
+void writeC() {
+ final StringBuffer buffer = StringBuffer();
+ buffer.write(headerC);
+
+ buffer.writeAll(structs.map((e) => e.cDefinition));
+ buffer.writeAll(functions.map((e) => e.cCallCode));
+ buffer.writeAll(functions.map((e) => e.cCallbackCode));
+
+ buffer.write(footerC);
+
+ File(ccPath).writeAsStringSync(buffer.toString());
+ Process.runSync("clang-format", ["-i", ccPath]);
+}
+
+final ccPath = Platform.script
+ .resolve("../../../runtime/bin/ffi_test/ffi_test_functions_generated.cc")
+ .path;
+
+void printUsage() {
+ print("""
+Generates structs by value tests.
+
+Generates:
+- $ccPath
+- ${callbackTestPath(true)}
+- ${callTestPath(true)}
+- ${callbackTestPath(false)}
+- ${callTestPath(false)}
+""");
+}
+
+void main(List<String> arguments) {
+ if (arguments.length != 0) {
+ printUsage();
+ return;
+ }
+
+ writeDartCallTest();
+ writeDartCallbackTest();
+ writeC();
+}
diff --git a/tests/ffi_2/generator/utils.dart b/tests/ffi_2/generator/utils.dart
new file mode 100644
index 0000000..735e769
--- /dev/null
+++ b/tests/ffi_2/generator/utils.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2020, 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.
+
+extension TestGeneratorStringExtension on String {
+ String upperCaseFirst() => "${this[0].toUpperCase()}${this.substring(1)}";
+
+ String lowerCaseFirst() => "${this[0].toLowerCase()}${this.substring(1)}";
+
+ String makeCComment() => "// " + split("\n").join("\n// ");
+
+ String makeDartDocComment() => "/// " + split("\n").join("\n/// ");
+
+ String limitTo(int lenght) {
+ if (this.length > lenght) {
+ return substring(0, lenght);
+ }
+ return this;
+ }
+
+ String trimCouts() => replaceAll('" << "', '').replaceAll('"<< "', '');
+}
diff --git a/tools/VERSION b/tools/VERSION
index 9b98b0f..94efa75 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 11
PATCH 0
-PRERELEASE 260
+PRERELEASE 261
PRERELEASE_PATCH 0
\ No newline at end of file