Reid Kleckner | 2c6a389 | 2020-02-11 16:03:26 -0800 | [diff] [blame^] | 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 | // FIXME: Pass non-trivial *and* overaligned types indirectly. Right now the C++ |
| 8 | // ABI rules say to use inalloca, and they take precedence, so it's not easy to |
| 9 | // implement this. |
| 10 | |
| 11 | |
| 12 | struct NonTrivial { |
| 13 | NonTrivial(); |
| 14 | NonTrivial(const NonTrivial &o); |
| 15 | int x; |
| 16 | }; |
| 17 | |
| 18 | struct __declspec(align(64)) OverAligned { |
| 19 | OverAligned(); |
| 20 | int buf[16]; |
| 21 | }; |
| 22 | |
| 23 | extern int gvi32; |
| 24 | |
| 25 | int receive_inalloca_overaligned(NonTrivial nt, OverAligned o) { |
| 26 | return nt.x + o.buf[0]; |
| 27 | } |
| 28 | |
| 29 | // CHECK-LABEL: define dso_local i32 @"?receive_inalloca_overaligned@@Y{{.*}}" |
| 30 | // CHECK-SAME: (<{ %struct.NonTrivial, %struct.OverAligned* }>* inalloca %0) |
| 31 | |
| 32 | int pass_inalloca_overaligned() { |
| 33 | gvi32 = receive_inalloca_overaligned(NonTrivial(), OverAligned()); |
| 34 | return gvi32; |
| 35 | } |
| 36 | |
| 37 | // CHECK-LABEL: define dso_local i32 @"?pass_inalloca_overaligned@@Y{{.*}}" |
| 38 | // CHECK: [[TMP:%[^ ]*]] = alloca %struct.OverAligned, align 64 |
| 39 | // CHECK: call i8* @llvm.stacksave() |
| 40 | // CHECK: alloca inalloca <{ %struct.NonTrivial, %struct.OverAligned* }> |
| 41 | |
| 42 | // Construct OverAligned into TMP. |
| 43 | // CHECK: call x86_thiscallcc %struct.OverAligned* @"??0OverAligned@@QAE@XZ"(%struct.OverAligned* [[TMP]]) |
| 44 | |
| 45 | // Construct NonTrivial into the GEP. |
| 46 | // CHECK: [[GEP:%[^ ]*]] = getelementptr inbounds <{ %struct.NonTrivial, %struct.OverAligned* }>, <{ %struct.NonTrivial, %struct.OverAligned* }>* %{{.*}}, i32 0, i32 0 |
| 47 | // CHECK: call x86_thiscallcc %struct.NonTrivial* @"??0NonTrivial@@QAE@XZ"(%struct.NonTrivial* [[GEP]]) |
| 48 | |
| 49 | // Store the address of an OverAligned temporary into the struct. |
| 50 | // CHECK: getelementptr inbounds <{ %struct.NonTrivial, %struct.OverAligned* }>, <{ %struct.NonTrivial, %struct.OverAligned* }>* %{{.*}}, i32 0, i32 1 |
| 51 | // CHECK: store %struct.OverAligned* [[TMP]], %struct.OverAligned** %{{.*}}, align 4 |
| 52 | // CHECK: call i32 @"?receive_inalloca_overaligned@@Y{{.*}}"(<{ %struct.NonTrivial, %struct.OverAligned* }>* inalloca %argmem) |