1
+ // RUN: %clang_cc1 -triple=arm %s -emit-llvm -O3 -o - | FileCheck %s --check-prefix=CHECK-ARM
2
+ // RUN: %clang_cc1 -triple=arm64 %s -emit-llvm -O3 -o - | FileCheck %s --check-prefix=CHECK-ARM64
3
+ // RUN: %clang_cc1 -triple=i686 %s -emit-llvm -O3 -o - | FileCheck %s --check-prefix=CHECK-X86
4
+ // RUN: %clang_cc1 -triple=x86_64 %s -emit-llvm -O3 -o - | FileCheck %s --check-prefix=CHECK-X64
5
+
6
+ // Sret tests
7
+ struct Big {
8
+ int a, b, c, d, e, f, g, h;
9
+ };
10
+
11
+ struct Big F1 (signed short P0);
12
+
13
+ struct Big F2 (signed short P0) {
14
+ signed short P1 = 20391 ;
15
+ [[clang::musttail]] return F1 (P1);
16
+ }
17
+
18
+ // CHECK-NOT: alloca
19
+ // CHECK-ARM: musttail call arm_aapcscc void @_Z2F1s(ptr dead_on_unwind writable sret(%struct.Big) align 4 %agg.result, i16 noundef signext 20391)
20
+ // CHECK-ARM64: musttail call void @_Z2F1s(ptr dead_on_unwind writable sret(%struct.Big) align 4 %agg.result, i16 noundef 20391)
21
+ // CHECK-X86: musttail call void @_Z2F1s(ptr dead_on_unwind writable sret(%struct.Big) align 4 %agg.result, i16 noundef signext 20391)
22
+ // CHECK-X64: musttail call void @_Z2F1s(ptr dead_on_unwind writable sret(%struct.Big) align 4 %agg.result, i16 noundef signext 20391)
23
+
24
+ struct ReallyBig {
25
+ int a[100 ];
26
+ };
27
+
28
+ // Indirect sret tests
29
+ // Function pointer for testing indirect musttail call.
30
+ struct FunctionPointers {
31
+ ReallyBig (*F3)(int , int , int , int , float , double );
32
+ ReallyBig (*F4)(int , int , int , char , float , double );
33
+ };
34
+
35
+ struct ReallyBig F3 (int P0, int P1, int P2, int P3, float P4, double P5);
36
+ struct ReallyBig F4 (int P0, int P1, int P2, char P3, float P4, double P5);
37
+
38
+ static struct FunctionPointers FP = {F3, F4};
39
+
40
+ struct ReallyBig F5 (int P0, int P1, int P2, int P3, float P4, double P5) {
41
+ [[clang::musttail]] return FP.F3 (P0, P1, P2, P3, P4, P5);
42
+ }
43
+
44
+ // CHECK-NOT: alloca
45
+ // CHECK-ARM: musttail call arm_aapcscc void @_Z2F3iiiifd(ptr dead_on_unwind writable sret(%struct.ReallyBig) align 4 %agg.result, i32 noundef %P0, i32 noundef %P1, i32 noundef %P2, i32 noundef %P3, float noundef %P4, double noundef %P5)
46
+ // CHECK-ARM64: musttail call void @_Z2F3iiiifd(ptr dead_on_unwind writable sret(%struct.ReallyBig) align 4 %agg.result, i32 noundef %P0, i32 noundef %P1, i32 noundef %P2, i32 noundef %P3, float noundef %P4, double noundef %P5)
47
+ // CHECK-X86: musttail call void @_Z2F3iiiifd(ptr dead_on_unwind writable sret(%struct.ReallyBig) align 4 %agg.result, i32 noundef %P0, i32 noundef %P1, i32 noundef %P2, i32 noundef %P3, float noundef %P4, double noundef %P5)
48
+ // CHECK-X64: musttail call void @_Z2F3iiiifd(ptr dead_on_unwind writable sret(%struct.ReallyBig) align 4 %agg.result, i32 noundef %P0, i32 noundef %P1, i32 noundef %P2, i32 noundef %P3, float noundef %P4, double noundef %P5)
49
+
50
+ struct ReallyBig F6 (int P0, int P1, int P2, char P3, float P4, double P5) {
51
+ [[clang::musttail]] return FP.F4 (P0, P1, P2, P3, P4, P5);
52
+ }
53
+
54
+ // Complex and BitInt. Special cases for sret.
55
+ // CHECK-NOT: alloca
56
+ // CHECK-ARM: musttail call arm_aapcscc void @_Z2F4iiicfd(ptr dead_on_unwind writable sret(%struct.ReallyBig) align 4 %agg.result, i32 noundef %P0, i32 noundef %P1, i32 noundef %P2, i8 noundef signext %P3, float noundef %P4, double noundef %P5)
57
+ // CHECK-ARM64: musttail call void @_Z2F4iiicfd(ptr dead_on_unwind writable sret(%struct.ReallyBig) align 4 %agg.result, i32 noundef %P0, i32 noundef %P1, i32 noundef %P2, i8 noundef %P3, float noundef %P4, double noundef %P5)
58
+ // CHECK-X86: musttail call void @_Z2F4iiicfd(ptr dead_on_unwind writable sret(%struct.ReallyBig) align 4 %agg.result, i32 noundef %P0, i32 noundef %P1, i32 noundef %P2, i8 noundef signext %P3, float noundef %P4, double noundef %P5)
59
+ // CHECK-X64: musttail call void @_Z2F4iiicfd(ptr dead_on_unwind writable sret(%struct.ReallyBig) align 4 %agg.result, i32 noundef %P0, i32 noundef %P1, i32 noundef %P2, i8 noundef signext %P3, float noundef %P4, double noundef %P5)
60
+
61
+ double _Complex F7 (signed short P0);
62
+
63
+ double _Complex F8 (signed short P0) {
64
+ signed short P1 = 20391 ;
65
+ [[clang::musttail]] return F7 (P1);
66
+ }
67
+
68
+ // CHECK-NOT: alloca
69
+ // CHECK-ARM: musttail call arm_aapcscc void @_Z2F7s(ptr dead_on_unwind writable sret({ double, double }) align 8 %agg.result, i16 noundef signext 20391)
70
+ // CHECK-ARM64: musttail call noundef { double, double } @_Z2F7s(i16 noundef 20391)
71
+ // CHECK-X86: musttail call void @_Z2F7s(ptr dead_on_unwind writable sret({ double, double }) align 4 %agg.result, i16 noundef signext 20391)
72
+ // CHECK-X64: musttail call noundef { double, double } @_Z2F7s(i16 noundef signext 20391)
73
+
74
+ signed _BitInt (100 ) F9(float P0, float P1, double P2, char P3);
75
+
76
+ signed _BitInt (100 ) F10(float P0, float P1, double P2, char P3) {
77
+ [[clang::musttail]] return F9 (P0, P1, P2, P3);
78
+ }
79
+
80
+ // CHECK-NOT: alloca
81
+ // CHECK-ARM: musttail call arm_aapcscc void @_Z2F9ffdc(ptr dead_on_unwind writable sret(i128) align 8 %agg.result, float noundef %P0, float noundef %P1, double noundef %P2, i8 noundef signext %P3)
82
+ // CHECK-ARM64: musttail call noundef i100 @_Z2F9ffdc(float noundef %P0, float noundef %P1, double noundef %P2, i8 noundef %P3)
83
+ // CHECK-X86: musttail call void @_Z2F9ffdc(ptr dead_on_unwind writable sret(i128) align 4 %agg.result, float noundef %P0, float noundef %P1, double noundef %P2, i8 noundef signext %P3)
84
+ // CHECK-X64: musttail call noundef { i64, i64 } @_Z2F9ffdc(float noundef %P0, float noundef %P1, double noundef %P2, i8 noundef signext %P3)
0 commit comments