xref: /llvm-project/clang/test/CodeGen/arm64-microsoft-arguments.cpp (revision 3ab4ae9e58c09dfd8203547ba8916f3458a0a481)
1 // RUN: %clang_cc1 -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 %0)
7 struct S1 {
8   int a[2];
9 };
10 
11 S1 func1(S1 x);
f1()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] %0)
20 struct S2 {
21   int a[4];
22 };
23 
24 S2 func2(S2 x);
f2()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{{.*}}(ptr dead_on_unwind noalias writable sret(%struct.S3) align 4 %agg.result)
32 // CHECK: call void {{.*}}func3{{.*}}(ptr dead_on_unwind writable sret(%struct.S3) align 4 %agg.result, ptr noundef %agg.tmp)
33 struct S3 {
34   int a[5];
35 };
36 
37 S3 func3(S3 x);
f3()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{{.*}}(ptr dead_on_unwind inreg noalias writable sret(%struct.S4) align 4 %agg.result)
46 // CHECK: call void {{.*}}func4{{.*}}(ptr dead_on_unwind inreg writable sret(%struct.S4) align 4 %agg.result, [2 x i64] %0)
47 struct S4 {
48   int a[3];
49   ~S4();
50 };
51 
52 S4 func4(S4 x);
f4()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{{.*}}(ptr {{[^,]*}} %this, ptr dead_on_unwind inreg noalias writable sret(%class.P1) align 1 %agg.result)
60 // CHECK: call void {{.*}}foo@P1{{.*}}(ptr noundef{{[^,]*}} %ref.tmp, ptr dead_on_unwind inreg writable sret(%class.P1) align 1 %agg.result, i8 %0)
61 
62 class P1 {
63 public:
64   P1 foo(P1 x);
65 };
66 
67 class Q1 {
68 public:
69   P1 bar();
70 };
71 
bar()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{{.*}}(ptr noundef{{[^,]*}} %ref.tmp, ptr dead_on_unwind inreg writable sret(%class.P2) align 1 %retval, i8 %0)
80 class P2 {
81 public:
82   P2 foo(P2 x);
83 };
84 
bar()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{{.*}}(ptr dead_on_unwind inreg noalias writable sret(%struct.S5) align 4 %agg.result)
93 // CHECK: call void {{.*}}func5{{.*}}(ptr dead_on_unwind inreg writable sret(%struct.S5) align 4 %agg.result, i64 {{.*}})
94 struct S5 {
95   S5();
96   int x;
97 };
98 
99 S5 func5(S5 x);
f5()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);
f6()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);
f7()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{{.*}}(ptr dead_on_unwind inreg noalias writable sret(%struct.S8) align 4 {{.*}})
150 // CHECK: call void {{.*}}func8{{.*}}(ptr dead_on_unwind inreg writable sret(%struct.S8) align 4 {{.*}}, i64 {{.*}})
151 S8 func8(S8 x);
f8()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"(ptr dead_on_unwind inreg noalias writable sret(%struct.S9) align 4 {{.*}})
161 // CHECK: call void {{.*}}func9{{.*}}(ptr dead_on_unwind inreg writable sret(%struct.S9) align 4 {{.*}}, i64 {{.*}})
162 struct S9 {
163   S9& operator=(const S9&);
164   int x;
165 };
166 
167 S9 func9(S9 x);
f9()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{{.*}}(ptr dead_on_unwind inreg noalias writable sret(%struct.S10) align 4 {{.*}})
178 // CHECK: call void {{.*}}func10{{.*}}(ptr dead_on_unwind inreg writable sret(%struct.S10) align 4 {{.*}}, [2 x i64] {{.*}})
179 struct S10 : public S1 {
180   int x;
181 };
182 
183 S10 func10(S10 x);
f10()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{{.*}}(ptr dead_on_unwind inreg noalias writable sret(%struct.S11) align 8 {{.*}})
193 // CHECK: call void {{.*}}func11{{.*}}(ptr dead_on_unwind inreg writable sret(%struct.S11) align 8 {{.*}}, ptr {{.*}})
194 struct S11 {
195   virtual void f();
196   int a[5];
197 };
198 
199 S11 func11(S11 x);
f11()200 S11 f11() {
201   S11 x;
202   return func11(x);
203 }
204 
205 // GH86384
206 // Pass and return object with template constructor (pass directly,
207 // return indirectly).
208 // CHECK: define dso_local void @"?f12@@YA?AUS12@@XZ"(ptr dead_on_unwind inreg noalias writable sret(%struct.S12) align 4 {{.*}})
209 // CHECK: call void @"?func12@@YA?AUS12@@U1@@Z"(ptr dead_on_unwind inreg writable sret(%struct.S12) align 4 {{.*}}, i64 {{.*}})
210 struct S12 {
S12S12211   template<typename T> S12(T*) {}
212   int x;
213 };
214 S12 func12(S12 x);
f12()215 S12 f12() {
216   S12 x((int*)0);
217   return func12(x);
218 }
219