[MS] On x86_32, pass overaligned, non-copyable arguments indirectly
[lldb.git] / clang / test / CodeGenCXX / inalloca-overaligned.cpp
1 // RUN: %clang_cc1 -fms-extensions -w -triple i386-pc-win32 -emit-llvm -o - %s | FileCheck %s
2
3 // PR44395
4 // MSVC passes overaligned types indirectly since MSVC 2015. Make sure that
5 // works with inalloca.
6
7 struct NonTrivial {
8   NonTrivial();
9   NonTrivial(const NonTrivial &o);
10   int x;
11 };
12
13 struct __declspec(align(64)) OverAligned {
14   OverAligned();
15   int buf[16];
16 };
17
18 struct __declspec(align(8)) Both {
19   Both();
20   Both(const Both &o);
21   int x, y;
22 };
23
24 extern int gvi32;
25
26 int receive_inalloca_overaligned(NonTrivial nt, OverAligned o) {
27   return nt.x + o.buf[0];
28 }
29
30 // CHECK-LABEL: define dso_local i32 @"?receive_inalloca_overaligned@@Y{{.*}}"
31 // CHECK-SAME: (<{ %struct.NonTrivial, %struct.OverAligned* }>* inalloca %0)
32
33 int pass_inalloca_overaligned() {
34   gvi32 = receive_inalloca_overaligned(NonTrivial(), OverAligned());
35   return gvi32;
36 }
37
38 // CHECK-LABEL: define dso_local i32 @"?pass_inalloca_overaligned@@Y{{.*}}"
39 // CHECK: [[TMP:%[^ ]*]] = alloca %struct.OverAligned, align 64
40 // CHECK: call i8* @llvm.stacksave()
41 // CHECK: alloca inalloca <{ %struct.NonTrivial, %struct.OverAligned* }>
42
43 // Construct OverAligned into TMP.
44 // CHECK: call x86_thiscallcc %struct.OverAligned* @"??0OverAligned@@QAE@XZ"(%struct.OverAligned* [[TMP]])
45
46 // Construct NonTrivial into the GEP.
47 // CHECK: [[GEP:%[^ ]*]] = getelementptr inbounds <{ %struct.NonTrivial, %struct.OverAligned* }>, <{ %struct.NonTrivial, %struct.OverAligned* }>* %{{.*}}, i32 0, i32 0
48 // CHECK: call x86_thiscallcc %struct.NonTrivial* @"??0NonTrivial@@QAE@XZ"(%struct.NonTrivial* [[GEP]])
49
50 // Store the address of an OverAligned temporary into the struct.
51 // CHECK: getelementptr inbounds <{ %struct.NonTrivial, %struct.OverAligned* }>, <{ %struct.NonTrivial, %struct.OverAligned* }>* %{{.*}}, i32 0, i32 1
52 // CHECK: store %struct.OverAligned* [[TMP]], %struct.OverAligned** %{{.*}}, align 4
53 // CHECK: call i32 @"?receive_inalloca_overaligned@@Y{{.*}}"(<{ %struct.NonTrivial, %struct.OverAligned* }>* inalloca %argmem)
54
55 int receive_both(Both o) {
56   return o.x + o.y;
57 }
58
59 // CHECK-LABEL: define dso_local i32 @"?receive_both@@Y{{.*}}"
60 // CHECK-SAME: (%struct.Both* %o)
61
62 int pass_both() {
63   gvi32 = receive_both(Both());
64   return gvi32;
65 }
66
67 // CHECK-LABEL: define dso_local i32 @"?pass_both@@Y{{.*}}"
68 // CHECK: [[TMP:%[^ ]*]] = alloca %struct.Both, align 8
69 // CHECK: call x86_thiscallcc %struct.Both* @"??0Both@@QAE@XZ"(%struct.Both* [[TMP]])
70 // CHECK: call i32 @"?receive_both@@Y{{.*}}"(%struct.Both* [[TMP]])
71
72 int receive_inalloca_both(NonTrivial nt, Both o) {
73   return nt.x + o.x + o.y;
74 }
75
76 // CHECK-LABEL: define dso_local i32 @"?receive_inalloca_both@@Y{{.*}}"
77 // CHECK-SAME: (<{ %struct.NonTrivial, %struct.Both* }>* inalloca %0)
78
79 int pass_inalloca_both() {
80   gvi32 = receive_inalloca_both(NonTrivial(), Both());
81   return gvi32;
82 }
83
84 // CHECK-LABEL: define dso_local i32 @"?pass_inalloca_both@@Y{{.*}}"
85 // CHECK: [[TMP:%[^ ]*]] = alloca %struct.Both, align 8
86 // CHECK: call x86_thiscallcc %struct.Both* @"??0Both@@QAE@XZ"(%struct.Both* [[TMP]])
87 // CHECK: call i32 @"?receive_inalloca_both@@Y{{.*}}"(<{ %struct.NonTrivial, %struct.Both* }>* inalloca %argmem)