| // RUN: %clang_cc1 -triple aarch64-pc-windows-msvc -fobjc-runtime=gnustep-2.2 -fobjc-dispatch-method=non-legacy -emit-llvm -o - %s | FileCheck %s | 
 |  | 
 | // Pass and return for type size <= 8 bytes. | 
 | struct S1 { | 
 |   int a[2]; | 
 | }; | 
 |  | 
 | // Pass and return hfa <= 8 bytes | 
 | struct F1 { | 
 |   float a[2]; | 
 | }; | 
 |  | 
 | // Pass and return for type size > 16 bytes. | 
 | struct S2 { | 
 |   int a[5]; | 
 | }; | 
 |  | 
 | // Pass and return aggregate (of size < 16 bytes) with non-trivial destructor. | 
 | // Sret and inreg: Returned in x0 | 
 | struct S3 { | 
 |   int a[3]; | 
 |   ~S3(); | 
 | }; | 
 | S3::~S3() { | 
 | } | 
 |  | 
 |  | 
 | @interface MsgTest { id isa; } @end | 
 | @implementation MsgTest  | 
 | - (S1) smallS1 { | 
 |   S1 x; | 
 |   x.a[0] = 0; | 
 |   x.a[1] = 1; | 
 |   return x; | 
 |  | 
 | } | 
 | - (F1) smallF1 { | 
 |   F1 x; | 
 |   x.a[0] = 0.2f; | 
 |   x.a[1] = 0.5f; | 
 |   return x; | 
 | } | 
 | - (S2) stretS2 { | 
 |   S2 x; | 
 |   for (int i = 0; i < 5; i++) { | 
 |     x.a[i] = i; | 
 |   } | 
 |   return x; | 
 | } | 
 | - (S3) stretInRegS3 { | 
 |   S3 x; | 
 |   for (int i = 0; i < 3; i++) { | 
 |     x.a[i] = i; | 
 |   } | 
 |   return x; | 
 | } | 
 | + (S3) msgTestStretInRegS3 { | 
 |   S3 x; | 
 |   for (int i = 0; i < 3; i++) { | 
 |     x.a[i] = i; | 
 |   } | 
 |   return x; | 
 | } | 
 | @end | 
 |  | 
 | void test0(MsgTest *t) { | 
 |     // CHECK: call {{.*}} @objc_msgSend | 
 |     S1 ret = [t smallS1]; | 
 |     // CHECK: call {{.*}} @objc_msgSend | 
 |     F1 ret2 = [t smallF1]; | 
 |     // CHECK: call {{.*}} @objc_msgSend_stret | 
 |     S2 ret3 = [t stretS2]; | 
 |     // CHECK: call {{.*}} @objc_msgSend_stret2 | 
 |     S3 ret4 = [t stretInRegS3]; | 
 |     // CHECK: call {{.*}} @objc_msgSend_stret2 | 
 |     S3 ret5 = [MsgTest msgTestStretInRegS3]; | 
 | } |