|
| 1 | +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -target-cpu core2 -emit-llvm -o - %s | FileCheck %s |
| 2 | +// RUN: %clang_cc1 -triple arm64-apple-ios9 -target-cpu cyclone -emit-llvm -o - %s | FileCheck %s |
| 3 | +// RUN: %clang_cc1 -triple armv7-apple-darwin9 -emit-llvm -o - %s | FileCheck %s |
| 4 | +// RUN: %clang_cc1 -triple armv7s-apple-ios9 -emit-llvm -o - %s | FileCheck %s |
| 5 | +// RUN: %clang_cc1 -triple armv7k-apple-ios9 -emit-llvm -o - %s | FileCheck %s |
| 6 | + |
| 7 | +// Test tail call behavior when a swiftasynccall function is called |
| 8 | +// from another swiftasynccall function. |
| 9 | + |
| 10 | +#define SWIFTCALL __attribute__((swiftcall)) |
| 11 | +#define SWIFTASYNCCALL __attribute__((swiftasynccall)) |
| 12 | +#define ASYNC_CONTEXT __attribute__((swift_async_context)) |
| 13 | + |
| 14 | +// CHECK-LABEL: swifttailcc void @async_leaf1(i8* swiftasync |
| 15 | +SWIFTASYNCCALL void async_leaf1(char * ASYNC_CONTEXT ctx) { |
| 16 | + *ctx += 1; |
| 17 | +} |
| 18 | + |
| 19 | +// CHECK-LABEL: swifttailcc void @async_leaf2(i8* swiftasync |
| 20 | +SWIFTASYNCCALL void async_leaf2(char * ASYNC_CONTEXT ctx) { |
| 21 | + *ctx += 2; |
| 22 | +} |
| 23 | + |
| 24 | +// CHECK-LABEL: swifttailcc void @async_branch |
| 25 | +// CHECK: tail call swifttailcc void @async_leaf1 |
| 26 | +// CHECK: tail call swifttailcc void @async_leaf2 |
| 27 | +SWIFTASYNCCALL void async_branch(_Bool b, char * ASYNC_CONTEXT ctx) { |
| 28 | + if (b) { |
| 29 | + return async_leaf1(ctx); |
| 30 | + } else { |
| 31 | + return async_leaf2(ctx); |
| 32 | + } |
| 33 | +} |
| 34 | + |
| 35 | +// CHECK-LABEL: swifttailcc void @async_loop |
| 36 | +// CHECK: tail call swifttailcc void @async_leaf1 |
| 37 | +// CHECK: tail call swifttailcc void @async_leaf2 |
| 38 | +// CHECK: tail call swifttailcc void @async_loop |
| 39 | +SWIFTASYNCCALL void async_loop(unsigned u, char * ASYNC_CONTEXT ctx) { |
| 40 | + if (u == 0) { |
| 41 | + return async_leaf1(ctx); |
| 42 | + } else if (u == 1) { |
| 43 | + return async_leaf2(ctx); |
| 44 | + } |
| 45 | + return async_loop(u - 2, ctx); |
| 46 | +} |
| 47 | + |
| 48 | +// Forward-declaration + mutual recursion is okay. |
| 49 | + |
| 50 | +SWIFTASYNCCALL void async_mutual_loop2(unsigned u, char * ASYNC_CONTEXT ctx); |
| 51 | + |
| 52 | +// CHECK: swifttailcc void @async_mutual_loop |
| 53 | +// CHECK: tail call swifttailcc void @async_leaf |
| 54 | +// CHECK: tail call swifttailcc void @async_leaf |
| 55 | +// CHECK: tail call swifttailcc void @async_mutual_loop |
| 56 | +SWIFTASYNCCALL void async_mutual_loop1(unsigned u, char * ASYNC_CONTEXT ctx) { |
| 57 | + if (u == 0) { |
| 58 | + return async_leaf1(ctx); |
| 59 | + } else if (u == 1) { |
| 60 | + return async_leaf2(ctx); |
| 61 | + } |
| 62 | + return async_mutual_loop2(u - 2, ctx); |
| 63 | +} |
| 64 | + |
| 65 | +// CHECK: swifttailcc void @async_mutual_loop |
| 66 | +// CHECK: tail call swifttailcc void @async_leaf1 |
| 67 | +// CHECK: tail call swifttailcc void @async_leaf2 |
| 68 | +// CHECK: tail call swifttailcc void @async_mutual_loop1 |
| 69 | +SWIFTASYNCCALL void async_mutual_loop2(unsigned u, char * ASYNC_CONTEXT ctx) { |
| 70 | + if (u == 0) { |
| 71 | + return async_leaf1(ctx); |
| 72 | + } else if (u == 1) { |
| 73 | + return async_leaf2(ctx); |
| 74 | + } |
| 75 | + return async_mutual_loop1(u - 2, ctx); |
| 76 | +} |
| 77 | + |
| 78 | +// When swiftasynccall functions are called by non-swiftasynccall functions, |
| 79 | +// the call isn't marked as a tail call. |
| 80 | + |
| 81 | +// CHECK-LABEL: swiftcc i8 @sync_calling_async |
| 82 | +// CHECK-NOT: tail call |
| 83 | +// CHECK: call swifttailcc void @async_branch |
| 84 | +// CHECK-NOT: tail call |
| 85 | +// CHECK: call swifttailcc void @async_loop |
| 86 | +SWIFTCALL char sync_calling_async(_Bool b, unsigned u) { |
| 87 | + char x = 'a'; |
| 88 | + async_branch(b, &x); |
| 89 | + async_loop(u, &x); |
| 90 | + return x; |
| 91 | +} |
| 92 | + |
| 93 | +// CHECK-LABEL: i8 @c_calling_async |
| 94 | +// CHECK-NOT: tail call |
| 95 | +// CHECK: call swifttailcc void @async_branch |
| 96 | +// CHECK-NOT: tail call |
| 97 | +// CHECK: call swifttailcc void @async_loop |
| 98 | +char c_calling_async(_Bool b, unsigned u) { |
| 99 | + char x = 'a'; |
| 100 | + async_branch(b, &x); |
| 101 | + async_loop(u, &x); |
| 102 | + return x; |
| 103 | +} |
| 104 | + |
0 commit comments