diff options
| author | Marco Antognini <marco.antognini@arm.com> | 2019-07-18 10:04:18 +0000 |
|---|---|---|
| committer | Marco Antognini <marco.antognini@arm.com> | 2019-07-18 10:04:18 +0000 |
| commit | 83748cc5abc199a5219b0e7d9ba308984a8df613 (patch) | |
| tree | 8abe72eb817fff18c645aec8d52fc22f610bf113 /clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl | |
| parent | 46b55fa58dead05222211e327ed90ffab949040b (diff) | |
| download | bcm5719-llvm-83748cc5abc199a5219b0e7d9ba308984a8df613.tar.gz bcm5719-llvm-83748cc5abc199a5219b0e7d9ba308984a8df613.zip | |
[OpenCL] Improve destructor support in C++ for OpenCL
Summary:
This patch does mainly three things:
1. It fixes a false positive error detection in Sema that is similar to
D62156. The error happens when explicitly calling an overloaded
destructor for different address spaces.
2. It selects the correct destructor when multiple overloads for
address spaces are available.
3. It inserts the expected address space cast when invoking a
destructor, if needed, and therefore fixes a crash due to the unmet
assertion in llvm::CastInst::Create.
The following is a reproducer of the three issues:
struct MyType {
~MyType() {}
~MyType() __constant {}
};
__constant MyType myGlobal{};
kernel void foo() {
myGlobal.~MyType(); // 1 and 2.
// 1. error: cannot initialize object parameter of type
// '__generic MyType' with an expression of type '__constant MyType'
// 2. error: no matching member function for call to '~MyType'
}
kernel void bar() {
// 3. The implicit call to the destructor crashes due to:
// Assertion `castIsValid(op, S, Ty) && "Invalid cast!"' failed.
// in llvm::CastInst::Create.
MyType myLocal;
}
The added test depends on D62413 and covers a few more things than the
above reproducer.
Subscribers: yaxunl, Anastasia, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64569
llvm-svn: 366422
Diffstat (limited to 'clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl')
| -rw-r--r-- | clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl | 59 |
1 files changed, 59 insertions, 0 deletions
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) |

