blob: 48a6183db8eb055c4aff205f82ce6b168554173d [file] [log] [blame]
Reid Kleckner2c6a3892020-02-11 16:03:26 -08001// 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
Reid Kleckner2c6a3892020-02-11 16:03:26 -08007struct NonTrivial {
8 NonTrivial();
9 NonTrivial(const NonTrivial &o);
10 int x;
11};
12
13struct __declspec(align(64)) OverAligned {
14 OverAligned();
15 int buf[16];
16};
17
Reid Kleckner3b3a1652020-09-18 11:22:15 -070018struct __declspec(align(8)) Both {
19 Both();
20 Both(const Both &o);
21 int x, y;
22};
23
Reid Kleckner2c6a3892020-02-11 16:03:26 -080024extern int gvi32;
25
26int 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
33int 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.
CJ Johnson69cd7762020-11-16 15:04:55 -080044// CHECK: call x86_thiscallcc %struct.OverAligned* @"??0OverAligned@@QAE@XZ"(%struct.OverAligned* {{[^,]*}} [[TMP]])
Reid Kleckner2c6a3892020-02-11 16:03:26 -080045
46// Construct NonTrivial into the GEP.
47// CHECK: [[GEP:%[^ ]*]] = getelementptr inbounds <{ %struct.NonTrivial, %struct.OverAligned* }>, <{ %struct.NonTrivial, %struct.OverAligned* }>* %{{.*}}, i32 0, i32 0
CJ Johnson69cd7762020-11-16 15:04:55 -080048// CHECK: call x86_thiscallcc %struct.NonTrivial* @"??0NonTrivial@@QAE@XZ"(%struct.NonTrivial* {{[^,]*}} [[GEP]])
Reid Kleckner2c6a3892020-02-11 16:03:26 -080049
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)
Reid Kleckner3b3a1652020-09-18 11:22:15 -070054
55int 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
62int 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
CJ Johnson69cd7762020-11-16 15:04:55 -080069// CHECK: call x86_thiscallcc %struct.Both* @"??0Both@@QAE@XZ"(%struct.Both* {{[^,]*}} [[TMP]])
Reid Kleckner3b3a1652020-09-18 11:22:15 -070070// CHECK: call i32 @"?receive_both@@Y{{.*}}"(%struct.Both* [[TMP]])
71
72int 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
79int 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
CJ Johnson69cd7762020-11-16 15:04:55 -080086// CHECK: call x86_thiscallcc %struct.Both* @"??0Both@@QAE@XZ"(%struct.Both* {{[^,]*}} [[TMP]])
Reid Kleckner3b3a1652020-09-18 11:22:15 -070087// CHECK: call i32 @"?receive_inalloca_both@@Y{{.*}}"(<{ %struct.NonTrivial, %struct.Both* }>* inalloca %argmem)
Reid Klecknerb8a50e92020-09-24 13:42:41 -070088
89// Here we have a type that is:
90// - overaligned
91// - not trivially copyable
92// - can be "passed in registers" due to [[trivial_abi]]
93// Clang should pass it directly.
94struct [[trivial_abi]] alignas(8) MyPtr {
95 MyPtr();
96 MyPtr(const MyPtr &o);
97 ~MyPtr();
98 int *ptr;
99};
100
101int receiveMyPtr(MyPtr o) { return *o.ptr; }
102
103// CHECK-LABEL: define dso_local i32 @"?receiveMyPtr@@Y{{.*}}"
104// CHECK-SAME: (%struct.MyPtr* %o)
105
106int passMyPtr() { return receiveMyPtr(MyPtr()); }
107
108// CHECK-LABEL: define dso_local i32 @"?passMyPtr@@Y{{.*}}"
109// CHECK: [[TMP:%[^ ]*]] = alloca %struct.MyPtr, align 8
CJ Johnson69cd7762020-11-16 15:04:55 -0800110// CHECK: call x86_thiscallcc %struct.MyPtr* @"??0MyPtr@@QAE@XZ"(%struct.MyPtr* {{[^,]*}} [[TMP]])
Reid Klecknerb8a50e92020-09-24 13:42:41 -0700111// CHECK: call i32 @"?receiveMyPtr@@Y{{.*}}"(%struct.MyPtr* [[TMP]])