Revert "[llvm] Improve llvm.objectsize computation by computing GEP, alloca and mallo...
[llvm-project.git] / clang / test / CodeGen / swift-async-call-conv.c
blob39511698bbae9d6523f1025c08ab6733f67af960
1 // RUN: %clang_cc1 -no-enable-noundef-analysis -triple x86_64-apple-darwin10 -target-cpu core2 -emit-llvm -o - %s | FileCheck %s
2 // RUN: %clang_cc1 -no-enable-noundef-analysis -triple arm64-apple-ios9 -target-cpu cyclone -emit-llvm -o - %s | FileCheck %s
3 // RUN: %clang_cc1 -no-enable-noundef-analysis -triple armv7-apple-darwin9 -emit-llvm -o - %s | FileCheck %s
4 // RUN: %clang_cc1 -no-enable-noundef-analysis -triple armv7s-apple-ios9 -emit-llvm -o - %s | FileCheck %s
5 // RUN: %clang_cc1 -no-enable-noundef-analysis -triple armv7k-apple-ios9 -emit-llvm -o - %s | FileCheck %s
7 // RUN: %clang_cc1 -no-enable-noundef-analysis -x c++ -triple x86_64-apple-darwin10 -target-cpu core2 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CPPONLY
8 // RUN: %clang_cc1 -no-enable-noundef-analysis -x c++ -triple arm64-apple-ios9 -target-cpu cyclone -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CPPONLY
9 // RUN: %clang_cc1 -no-enable-noundef-analysis -x c++ -triple armv7-apple-darwin9 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CPPONLY
10 // RUN: %clang_cc1 -no-enable-noundef-analysis -x c++ -triple armv7s-apple-ios9 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CPPONLY
11 // RUN: %clang_cc1 -no-enable-noundef-analysis -x c++ -triple armv7k-apple-ios9 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CPPONLY
13 // Test tail call behavior when a swiftasynccall function is called
14 // from another swiftasynccall function.
16 #define SWIFTCALL __attribute__((swiftcall))
17 #define SWIFTASYNCCALL __attribute__((swiftasynccall))
18 #define ASYNC_CONTEXT __attribute__((swift_async_context))
20 // CHECK-LABEL: swifttailcc void {{.*}}async_leaf1{{.*}}(ptr swiftasync
21 SWIFTASYNCCALL void async_leaf1(char * ASYNC_CONTEXT ctx) {
22 *ctx += 1;
25 // CHECK-LABEL: swifttailcc void {{.*}}async_leaf2{{.*}}(ptr swiftasync
26 SWIFTASYNCCALL void async_leaf2(char * ASYNC_CONTEXT ctx) {
27 *ctx += 2;
30 #if __cplusplus
31 #define MYBOOL bool
32 #else
33 #define MYBOOL _Bool
34 #endif
36 // CHECK-LABEL: swifttailcc void {{.*}}async_branch{{.*}}ptr swiftasync
37 // CHECK: musttail call swifttailcc void @{{.*}}async_leaf1
38 // CHECK-NEXT: ret void
39 // CHECK: musttail call swifttailcc void @{{.*}}async_leaf2
40 // CHECK-NEXT: ret void
41 SWIFTASYNCCALL void async_branch(MYBOOL b, char * ASYNC_CONTEXT ctx) {
42 if (b) {
43 return async_leaf1(ctx);
44 } else {
45 return async_leaf2(ctx);
49 // CHECK-LABEL: swifttailcc void {{.*}}async_not_all_tail
50 // CHECK-NOT: musttail call swifttailcc void @{{.*}}async_leaf1
51 // CHECK: call swifttailcc void @{{.*}}async_leaf1
52 // CHECK-NOT: ret void
53 // CHECK: musttail call swifttailcc void @{{.*}}async_leaf2
54 // CHECK-NEXT: ret void
55 SWIFTASYNCCALL void async_not_all_tail(char * ASYNC_CONTEXT ctx) {
56 async_leaf1(ctx);
57 return async_leaf2(ctx);
60 // CHECK-LABEL: swifttailcc void {{.*}}async_loop
61 // CHECK: musttail call swifttailcc void @{{.*}}async_leaf1
62 // CHECK-NEXT: ret void
63 // CHECK: musttail call swifttailcc void @{{.*}}async_leaf2
64 // CHECK-NEXT: ret void
65 // CHECK: musttail call swifttailcc void @{{.*}}async_loop
66 // CHECK-NEXT: ret void
67 SWIFTASYNCCALL void async_loop(unsigned u, char * ASYNC_CONTEXT ctx) {
68 if (u == 0) {
69 return async_leaf1(ctx);
70 } else if (u == 1) {
71 return async_leaf2(ctx);
73 return async_loop(u - 2, ctx);
76 // Forward-declaration + mutual recursion is okay.
78 SWIFTASYNCCALL void async_mutual_loop2(unsigned u, char * ASYNC_CONTEXT ctx);
80 // CHECK-LABEL: swifttailcc void {{.*}}async_mutual_loop1
81 // CHECK: musttail call swifttailcc void @{{.*}}async_leaf1
82 // CHECK-NEXT: ret void
83 // CHECK: musttail call swifttailcc void @{{.*}}async_leaf2
84 // CHECK-NEXT: ret void
85 // There is some bugginess around FileCheck's greediness/matching,
86 // so skipping the check for async_mutual_loop2 here.
87 SWIFTASYNCCALL void async_mutual_loop1(unsigned u, char * ASYNC_CONTEXT ctx) {
88 if (u == 0) {
89 return async_leaf1(ctx);
90 } else if (u == 1) {
91 return async_leaf2(ctx);
93 return async_mutual_loop2(u - 2, ctx);
96 // CHECK-LABEL: swifttailcc void {{.*}}async_mutual_loop2
97 // CHECK: musttail call swifttailcc void @{{.*}}async_leaf1
98 // CHECK-NEXT: ret void
99 // CHECK: musttail call swifttailcc void @{{.*}}async_leaf2
100 // CHECK-NEXT: ret void
101 // CHECK: musttail call swifttailcc void @{{.*}}async_mutual_loop1
102 // CHECK-NEXT: ret void
103 SWIFTASYNCCALL void async_mutual_loop2(unsigned u, char * ASYNC_CONTEXT ctx) {
104 if (u == 0) {
105 return async_leaf1(ctx);
106 } else if (u == 1) {
107 return async_leaf2(ctx);
109 return async_mutual_loop1(u - 2, ctx);
112 // When swiftasynccall functions are called by non-swiftasynccall functions,
113 // the call isn't marked as a tail call.
115 // CHECK-LABEL: swiftcc i8 {{.*}}sync_calling_async
116 // CHECK-NOT: tail call
117 // CHECK: call swifttailcc void @{{.*}}async_branch
118 // CHECK-NOT: tail call
119 // CHECK: call swifttailcc void @{{.*}}async_loop
120 SWIFTCALL char sync_calling_async(MYBOOL b, unsigned u) {
121 char x = 'a';
122 async_branch(b, &x);
123 async_loop(u, &x);
124 return x;
127 // CHECK-LABEL: i8 {{.*}}c_calling_async
128 // CHECK-NOT: tail call
129 // CHECK: call swifttailcc void @{{.*}}async_branch
130 // CHECK-NOT: tail call
131 // CHECK: call swifttailcc void @{{.*}}async_loop
132 char c_calling_async(MYBOOL b, unsigned u) {
133 char x = 'a';
134 async_branch(b, &x);
135 async_loop(u, &x);
136 return x;
139 #if __cplusplus
140 struct S {
141 SWIFTASYNCCALL void (*fptr)(char * ASYNC_CONTEXT);
143 SWIFTASYNCCALL void async_leaf_method(char * ASYNC_CONTEXT ctx) {
144 *ctx += 1;
146 SWIFTASYNCCALL void async_nonleaf_method1(char * ASYNC_CONTEXT ctx) {
147 return async_leaf_method(ctx);
149 SWIFTASYNCCALL void async_nonleaf_method2(char * ASYNC_CONTEXT ctx) {
150 return this->async_leaf_method(ctx);
154 SWIFTASYNCCALL void (S::*async_leaf_method_ptr)(char * ASYNC_CONTEXT) = &S::async_leaf_method;
156 // CPPONLY-LABEL: swifttailcc void {{.*}}async_struct_field_and_methods
157 // CPPONLY: musttail call swifttailcc void %{{[0-9]+}}
158 // CPPONLY: musttail call swifttailcc void @{{.*}}async_nonleaf_method1
159 // CPPONLY: musttail call swifttailcc void %{{[0-9]+}}
160 // CPPONLY: musttail call swifttailcc void @{{.*}}async_nonleaf_method2
161 // CPPONLY-NOT: musttail call swifttailcc void @{{.*}}async_leaf_method
162 // ^ TODO: Member pointers should also work.
163 SWIFTASYNCCALL void async_struct_field_and_methods(int i, S &sref, S *sptr) {
164 char x = 'a';
165 if (i == 0) {
166 return (*sref.fptr)(&x);
167 } else if (i == 1) {
168 return sref.async_nonleaf_method1(&x);
169 } else if (i == 2) {
170 return (*(sptr->fptr))(&x);
171 } else if (i == 3) {
172 return sptr->async_nonleaf_method2(&x);
173 } else if (i == 4) {
174 return (sref.*async_leaf_method_ptr)(&x);
176 return (sptr->*async_leaf_method_ptr)(&x);
179 // CPPONLY-LABEL: define{{.*}} swifttailcc void @{{.*}}async_nonleaf_method1
180 // CPPONLY: musttail call swifttailcc void @{{.*}}async_leaf_method
182 // CPPONLY-LABEL: define{{.*}} swifttailcc void @{{.*}}async_nonleaf_method2
183 // CPPONLY: musttail call swifttailcc void @{{.*}}async_leaf_method
184 #endif
186 // Passing this as an argument requires a coerce-and-expand operation,
187 // which requires a temporary. Make sure that cleaning up that temporary
188 // doesn't mess around with the musttail handling.
189 struct coerce_and_expand {
190 char a,b,c,d;
192 struct coerce_and_expand return_coerced(void);
193 SWIFTASYNCCALL void take_coerced_async(struct coerce_and_expand);
195 // CHECK-LABEL: swifttailcc void @{{.*}}test_coerced
196 SWIFTASYNCCALL void test_coerced() {
197 // CHECK: musttail call swifttailcc void @{{.*}}take_coerced_async
198 // CHECK-NEXT: ret void
199 return take_coerced_async(return_coerced());