diff options
| author | Marco Antognini <marco.antognini@arm.com> | 2019-07-22 09:39:13 +0000 |
|---|---|---|
| committer | Marco Antognini <marco.antognini@arm.com> | 2019-07-22 09:39:13 +0000 |
| commit | 88559637641e993895337e1047a0bd787fecc647 (patch) | |
| tree | 639b057daba633db68b8fa4d34a957913786c64f /clang/test | |
| parent | 6771a89fa01ffb1ea8702d7b07e259750ae62f1c (diff) | |
| download | bcm5719-llvm-88559637641e993895337e1047a0bd787fecc647.tar.gz bcm5719-llvm-88559637641e993895337e1047a0bd787fecc647.zip | |
[OpenCL] Improve destructor support in C++ for OpenCL
This re-applies r366422 with a fix for Bug PR42665 and a new regression
test.
llvm-svn: 366670
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/CodeGenCXX/PR42665.cpp | 61 | ||||
| -rw-r--r-- | clang/test/CodeGenOpenCLCXX/addrspace-ctor.cl | 14 | ||||
| -rw-r--r-- | clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl | 59 |
3 files changed, 120 insertions, 14 deletions
diff --git a/clang/test/CodeGenCXX/PR42665.cpp b/clang/test/CodeGenCXX/PR42665.cpp new file mode 100644 index 00000000000..4a460cfa107 --- /dev/null +++ b/clang/test/CodeGenCXX/PR42665.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -std=c++17 -O0 %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -std=c++17 -O0 %s -o - | FileCheck %s + +// Minimal reproducer for PR42665. + +struct Foo { + Foo() = default; + virtual ~Foo() = default; +}; + +template <typename Deleter> +struct Pair { + Foo first; + Deleter second; +}; + +template <typename Deleter> +Pair(Foo, Deleter) -> Pair<Deleter>; + +template <typename T> +void deleter(T& t) { t.~T(); } + +auto make_pair() { + return Pair{ Foo(), deleter<Foo> }; +} + +void foobar() { + auto p = make_pair(); + auto& f = p.first; + auto& d = p.second; + d(f); // Invoke virtual destructor of Foo through d. +} // p's destructor is invoked. + +// Regexes are used to handle both kind of mangling. +// +// CHECK-LABEL: define linkonce_odr{{( dso_local)?}} void @{{.*deleter.*Foo.*}}(%struct.Foo* dereferenceable({{[0-9]+}}) +// CHECK-SAME: [[T:%.*]]) +// CHECK: [[T_ADDR:%.*]] = alloca %struct.Foo* +// CHECK: store %struct.Foo* [[T]], %struct.Foo** [[T_ADDR]] +// CHECK: [[R0:%.*]] = load %struct.Foo*, %struct.Foo** [[T_ADDR]] +// CHECK: [[R1:%.*]] = bitcast %struct.Foo* [[R0]] to [[TYPE:.*struct\.Foo.*]]*** +// CHECK: [[VTABLE:%.*]] = load [[TYPE]]**, [[TYPE]]*** [[R1]] +// CHECK: [[VFUN:%.*]] = getelementptr inbounds [[TYPE]]*, [[TYPE]]** [[VTABLE]], i64 0 +// CHECK: [[DTOR:%.*]] = load [[TYPE]]*, [[TYPE]]** [[VFUN]] +// CHECK: call {{(void|i8\*)}} [[DTOR]](%struct.Foo* [[R0]] +// +// CHECK-LABEL: define{{( dso_local)?}} void @{{.*foobar.*}}() +// CHECK: [[P:%.*]] = alloca %struct.Pair +// CHECK: [[F:%.*]] = alloca %struct.Foo* +// CHECK: [[D:%.*]] = alloca [[TYPE:void \(%struct.Foo\*\)]]** +// CHECK: call void @{{.*make_pair.*}}(%struct.Pair* sret [[P]]) +// CHECK: [[FIRST:%.*]] = getelementptr inbounds %struct.Pair, %struct.Pair* [[P]], i32 0, i32 0 +// CHECK: store %struct.Foo* [[FIRST]], %struct.Foo** [[F]] +// CHECK: [[SECOND:%.*]] = getelementptr inbounds %struct.Pair, %struct.Pair* [[P]], i32 0, i32 1 +// CHECK: store void (%struct.Foo*)** [[SECOND]], [[TYPE]]*** [[D]] +// CHECK: [[R0:%.*]] = load [[TYPE]]**, [[TYPE]]*** [[D]] +// CHECK: [[R1:%.*]] = load [[TYPE]]*, [[TYPE]]** [[R0]] +// CHECK: [[R2:%.*]] = load %struct.Foo*, %struct.Foo** [[F]] +// CHECK: call void [[R1]](%struct.Foo* dereferenceable({{[0-9]+}}) [[R2]]) +// CHECK: call void @{{.*Pair.*Foo.*}}(%struct.Pair* [[P]]) + diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-ctor.cl b/clang/test/CodeGenOpenCLCXX/addrspace-ctor.cl deleted file mode 100644 index 42c2e6e9077..00000000000 --- a/clang/test/CodeGenOpenCLCXX/addrspace-ctor.cl +++ /dev/null @@ -1,14 +0,0 @@ -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s - -struct MyType { - MyType(int i) : i(i) {} - MyType(int i) __constant : i(i) {} - int i; -}; - -//CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const1, i32 1) -__constant MyType const1 = 1; -//CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const2, i32 2) -__constant MyType const2(2); -//CHECK: call void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* addrspacecast (%struct.MyType addrspace(1)* @glob to %struct.MyType addrspace(4)*), i32 1) -MyType glob(1); diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl b/clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl new file mode 100644 index 00000000000..21ba1ca251d --- /dev/null +++ b/clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl @@ -0,0 +1,59 @@ +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s --check-prefix=CHECK-DEFINITIONS + +// This test ensures the proper address spaces and address space cast are used +// for constructors, member functions and destructors. +// See also atexit.cl and global_init.cl for other specific tests. + +// CHECK: %struct.MyType = type { i32 } +struct MyType { + MyType(int i) : i(i) {} + MyType(int i) __constant : i(i) {} + ~MyType() {} + ~MyType() __constant {} + int bar() { return i + 2; } + int bar() __constant { return i + 1; } + int i; +}; + +// CHECK: @const1 = addrspace(2) global %struct.MyType zeroinitializer +__constant MyType const1 = 1; +// CHECK: @const2 = addrspace(2) global %struct.MyType zeroinitializer +__constant MyType const2(2); +// CHECK: @glob = addrspace(1) global %struct.MyType zeroinitializer +MyType glob(1); + +// CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const1, i32 1) +// CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const2, i32 2) +// CHECK: call void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* addrspacecast (%struct.MyType addrspace(1)* @glob to %struct.MyType addrspace(4)*), i32 1) + +// CHECK-LABEL: define spir_kernel void @fooGlobal() +kernel void fooGlobal() { + // CHECK: call i32 @_ZNU3AS46MyType3barEv(%struct.MyType addrspace(4)* addrspacecast (%struct.MyType addrspace(1)* @glob to %struct.MyType addrspace(4)*)) + glob.bar(); + // CHECK: call i32 @_ZNU3AS26MyType3barEv(%struct.MyType addrspace(2)* @const1) + const1.bar(); + // CHECK: call void @_ZNU3AS26MyTypeD1Ev(%struct.MyType addrspace(2)* @const1) + const1.~MyType(); +} + +// CHECK-LABEL: define spir_kernel void @fooLocal() +kernel void fooLocal() { + // CHECK: [[VAR:%.*]] = alloca %struct.MyType + // CHECK: [[REG:%.*]] = addrspacecast %struct.MyType* [[VAR]] to %struct.MyType addrspace(4)* + // CHECK: call void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* [[REG]], i32 3) + MyType myLocal(3); + // CHECK: [[REG:%.*]] = addrspacecast %struct.MyType* [[VAR]] to %struct.MyType addrspace(4)* + // CHECK: call i32 @_ZNU3AS46MyType3barEv(%struct.MyType addrspace(4)* [[REG]]) + myLocal.bar(); + // CHECK: [[REG:%.*]] = addrspacecast %struct.MyType* [[VAR]] to %struct.MyType addrspace(4)* + // CHECK: call void @_ZNU3AS46MyTypeD1Ev(%struct.MyType addrspace(4)* [[REG]]) +} + +// Ensure all members are defined for all the required address spaces. +// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* %this, i32 %i) +// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* %this, i32 %i) +// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS26MyTypeD1Ev(%struct.MyType addrspace(2)* %this) +// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS46MyTypeD1Ev(%struct.MyType addrspace(4)* %this) +// CHECK-DEFINITIONS-DAG: define linkonce_odr i32 @_ZNU3AS26MyType3barEv(%struct.MyType addrspace(2)* %this) +// CHECK-DEFINITIONS-DAG: define linkonce_odr i32 @_ZNU3AS46MyType3barEv(%struct.MyType addrspace(4)* %this) |

