1 // RUN: %clang_cc1 -no-opaque-pointers -triple aarch64-windows -ffreestanding -emit-llvm -O0 \ 2 // RUN: -x c++ -o - %s | FileCheck %s 3 4 // Pass and return for type size <= 8 bytes. 5 // CHECK: define {{.*}} i64 @{{.*}}f1{{.*}}() 6 // CHECK: call i64 {{.*}}func1{{.*}}(i64 %3) 7 struct S1 { 8 int a[2]; 9 }; 10 11 S1 func1(S1 x); 12 S1 f1() { 13 S1 x; 14 return func1(x); 15 } 16 17 // Pass and return type size <= 16 bytes. 18 // CHECK: define {{.*}} [2 x i64] @{{.*}}f2{{.*}}() 19 // CHECK: call [2 x i64] {{.*}}func2{{.*}}([2 x i64] %3) 20 struct S2 { 21 int a[4]; 22 }; 23 24 S2 func2(S2 x); 25 S2 f2() { 26 S2 x; 27 return func2(x); 28 } 29 30 // Pass and return for type size > 16 bytes. 31 // CHECK: define {{.*}} void @{{.*}}f3{{.*}}(%struct.S3* noalias sret(%struct.S3) align 4 %agg.result) 32 // CHECK: call void {{.*}}func3{{.*}}(%struct.S3* sret(%struct.S3) align 4 %agg.result, %struct.S3* noundef %agg.tmp) 33 struct S3 { 34 int a[5]; 35 }; 36 37 S3 func3(S3 x); 38 S3 f3() { 39 S3 x; 40 return func3(x); 41 } 42 43 // Pass and return aggregate (of size < 16 bytes) with non-trivial destructor. 44 // Passed directly but returned indirectly. 45 // CHECK: define {{.*}} void {{.*}}f4{{.*}}(%struct.S4* inreg noalias sret(%struct.S4) align 4 %agg.result) 46 // CHECK: call void {{.*}}func4{{.*}}(%struct.S4* inreg sret(%struct.S4) align 4 %agg.result, [2 x i64] %5) 47 struct S4 { 48 int a[3]; 49 ~S4(); 50 }; 51 52 S4 func4(S4 x); 53 S4 f4() { 54 S4 x; 55 return func4(x); 56 } 57 58 // Pass and return from instance method called from instance method. 59 // CHECK: define {{.*}} void @{{.*}}bar@Q1{{.*}}(%class.Q1* {{[^,]*}} %this, %class.P1* inreg noalias sret(%class.P1) align 1 %agg.result) 60 // CHECK: call void {{.*}}foo@P1{{.*}}(%class.P1* noundef{{[^,]*}} %ref.tmp, %class.P1* inreg sret(%class.P1) align 1 %agg.result, i8 %1) 61 62 class P1 { 63 public: 64 P1 foo(P1 x); 65 }; 66 67 class Q1 { 68 public: 69 P1 bar(); 70 }; 71 72 P1 Q1::bar() { 73 P1 p1; 74 return P1().foo(p1); 75 } 76 77 // Pass and return from instance method called from free function. 78 // CHECK: define {{.*}} void {{.*}}bar{{.*}}() 79 // CHECK: call void {{.*}}foo@P2{{.*}}(%class.P2* noundef{{[^,]*}} %ref.tmp, %class.P2* inreg sret(%class.P2) align 1 %retval, i8 %0) 80 class P2 { 81 public: 82 P2 foo(P2 x); 83 }; 84 85 P2 bar() { 86 P2 p2; 87 return P2().foo(p2); 88 } 89 90 // Pass and return an object with a user-provided constructor (passed directly, 91 // returned indirectly) 92 // CHECK: define {{.*}} void @{{.*}}f5{{.*}}(%struct.S5* inreg noalias sret(%struct.S5) align 4 %agg.result) 93 // CHECK: call void {{.*}}func5{{.*}}(%struct.S5* inreg sret(%struct.S5) align 4 %agg.result, i64 {{.*}}) 94 struct S5 { 95 S5(); 96 int x; 97 }; 98 99 S5 func5(S5 x); 100 S5 f5() { 101 S5 x; 102 return func5(x); 103 } 104 105 // Pass and return an object with a non-trivial explicitly defaulted constructor 106 // (passed directly, returned directly) 107 // CHECK: define {{.*}} i8 @"?f6@@YA?AUS6@@XZ"() 108 // CHECK: call i8 {{.*}}func6{{.*}}(i64 {{.*}}) 109 struct S6a { 110 S6a(); 111 }; 112 113 struct S6 { 114 S6() = default; 115 S6a x; 116 }; 117 118 S6 func6(S6 x); 119 S6 f6() { 120 S6 x; 121 return func6(x); 122 } 123 124 // Pass and return an object with a non-trivial implicitly defaulted constructor 125 // (passed directly, returned directly) 126 // CHECK: define {{.*}} i8 @"?f7@@YA?AUS7@@XZ"() 127 // CHECK: call i8 {{.*}}func7{{.*}}(i64 {{.*}}) 128 struct S7 { 129 S6a x; 130 }; 131 132 S7 func7(S7 x); 133 S7 f7() { 134 S7 x; 135 return func7(x); 136 } 137 138 struct S8a { 139 ~S8a(); 140 }; 141 142 // Pass and return an object with a non-trivial default destructor (passed 143 // directly, returne indirectly) 144 struct S8 { 145 S8a x; 146 int y; 147 }; 148 149 // CHECK: define {{.*}} void {{.*}}?f8{{.*}}(%struct.S8* inreg noalias sret(%struct.S8) align 4 {{.*}}) 150 // CHECK: call void {{.*}}func8{{.*}}(%struct.S8* inreg sret(%struct.S8) align 4 {{.*}}, i64 {{.*}}) 151 S8 func8(S8 x); 152 S8 f8() { 153 S8 x; 154 return func8(x); 155 } 156 157 158 // Pass and return an object with a non-trivial copy-assignment operator and 159 // a trivial copy constructor (passed directly, returned indirectly) 160 // CHECK: define {{.*}} void @"?f9@@YA?AUS9@@XZ"(%struct.S9* inreg noalias sret(%struct.S9) align 4 {{.*}}) 161 // CHECK: call void {{.*}}func9{{.*}}(%struct.S9* inreg sret(%struct.S9) align 4 {{.*}}, i64 {{.*}}) 162 struct S9 { 163 S9& operator=(const S9&); 164 int x; 165 }; 166 167 S9 func9(S9 x); 168 S9 f9() { 169 S9 x; 170 S9 y = x; 171 x = y; 172 return func9(x); 173 } 174 175 // Pass and return an object with a base class (passed directly, returned 176 // indirectly). 177 // CHECK: define dso_local void {{.*}}f10{{.*}}(%struct.S10* inreg noalias sret(%struct.S10) align 4 {{.*}}) 178 // CHECK: call void {{.*}}func10{{.*}}(%struct.S10* inreg sret(%struct.S10) align 4 {{.*}}, [2 x i64] {{.*}}) 179 struct S10 : public S1 { 180 int x; 181 }; 182 183 S10 func10(S10 x); 184 S10 f10() { 185 S10 x; 186 return func10(x); 187 } 188 189 190 // Pass and return a non aggregate object exceeding > 128 bits (passed 191 // indirectly, returned indirectly) 192 // CHECK: define dso_local void {{.*}}f11{{.*}}(%struct.S11* inreg noalias sret(%struct.S11) align 8 {{.*}}) 193 // CHECK: call void {{.*}}func11{{.*}}(%struct.S11* inreg sret(%struct.S11) align 8 {{.*}}, %struct.S11* {{.*}}) 194 struct S11 { 195 virtual void f(); 196 int a[5]; 197 }; 198 199 S11 func11(S11 x); 200 S11 f11() { 201 S11 x; 202 return func11(x); 203 } 204