[cfe-dev] Allow implicit copy constructor between address spaces in C++
Adam Strzelecki
ono at java.pl
Sat May 3 06:17:01 PDT 2014
Hello,
It is completely legit to initialize (copy) between address spaces in C while it fails in C++. This makes address spaces completely unusable in C++, at least I don't see any way to copy initialize in C++.
The reason being is I am trying to use OpenCL++ (OpenCL in C++11 mode), which works pretty fine [minor changes to Clang], except being unable to initialize from __global to __private.
Please consider following code:
// RUN: %clang_cc1 -fsyntax-only -verify %s
struct Point {
float x, y;
};
typedef struct Point Point;
typedef struct Point Point_1 __attribute__((address_space(1)));
float test(int i, const Point_1 *a) {
Point r = a[i];
return r.x * r.y;
}
Running it in `-x c` works fine, running with `-x c++ -std=c++11` generates:
File test.cc Line 3: candidate constructor (the implicit copy constructor) not viable: 1st argument ('const Point_1' (aka 'const __attribute__((address_space(1))) Point')) is in address space 1, but parameter must be in address space 0
File test.cc Line 3: candidate constructor (the implicit move constructor) not viable: 1st argument ('const Point_1' (aka 'const __attribute__((address_space(1))) Point')) is in address space 1, but parameter must be in address space 0
File test.cc Line 3: candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided
Can anyone point me any workaround, or how to fix it in Clang code? I believe this has to be relaxed in SemaOverload.cpp TryCopyInitialization, but I wish to not try solution that wouldn't be accepted into upstream.
FYI I have tried reinterpret_cast hinted in tests/SemaCXX/address-space-conversion.cpp:
Point r = reinterpret_cast<const Point *>(a)[i]
But I believe emitted ll is INVALID, since @llvm.memcpy looses address space qualifier for source pointer:
%7 = getelementptr inbounds %struct.Point* %6, i64 %4
%8 = bitcast %struct.Point* %r to i8*
%9 = bitcast %struct.Point* %7 to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %8, i8* %9, i64 8, i32 4, i1 false)
Comparing to ll emitted in plain C mode:
%6 = getelementptr inbounds %struct.Point addrspace(1)* %5, i64 %4
%7 = bitcast %struct.Point* %r to i8*
%8 = bitcast %struct.Point addrspace(1)* %6 to i8 addrspace(1)*
call void @llvm.memcpy.p0i8.p1i8.i64(i8* %7, i8 addrspace(1)* %8, i64 8, i32 4, i1 false)
Regards,
--
Adam
More information about the cfe-dev
mailing list