[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