@@ -28,6 +28,7 @@ therefore, no valid conversion between `+__constant+` and any other address spac
2828exists. This is aligned with rules from `OpenCL C 3.0 s6.7.9` and this logic
2929regulates semantics described in this section.
3030
31+ [[address_space_casts]]
3132==== Casts
3233
3334C-style casts follow rules of `OpenCL C 3.0 s6.7.9`. Conversions of
@@ -86,7 +87,7 @@ __private int & ref = ...; // references int in __private address space.
8687By default references refer to generic address space objects if generic
8788address space is supported or private address space otherwise, except
8889for dependent types that are not template specializations (see
89- <<addrspace-deduction, _Deduction_ >>).
90+ <<addrspace-deduction, _Address space inference_ >>).
9091
9192[source,cpp]
9293------------
@@ -101,11 +102,13 @@ conversion (`OpenCL C 3.0 s6.7.9`).
101102[source,cpp]
102103------------
103104void f(float &ref, __global float &globref) {
104- const int& tmp = ref; // legal - reference to generic/__private address space object can
105- // bind to a temporary object created in __private address space.
105+ const int& tmp = ref; // legal - reference to generic/__private address space object
106+ // can bind to a temporary object created in __private
107+ // address space.
106108
107- __global const int& globtmp = globref; // error reference to global address space object cannot bind
108- // to a temporary object created in __private address space.
109+ __global const int& globtmp = globref; // error: reference to global address space
110+ // object cannot bind to a temporary object
111+ // created in __private address space.
109112}
110113------------
111114
@@ -132,9 +135,10 @@ that is a pointer type. By default the `this` pointer parameter is in the
132135generic address space if it is supported and in the private address space
133136otherwise. All concrete objects passed as an argument to the
134137implicit `this` parameter will be converted to this default (generic or private)
135- address space first if such conversion is valid. Therefore, programs using objects
136- in disjoint address spaces will not be compiled unless the address spaces for the
137- object parameter `this` is explicitly specified using address space qualifiers
138+ address space first if such conversion is valid. Therefore, when member functions
139+ are called with objects created in disjoint address spaces from the default one,
140+ the compilation must fail. To prevent the failure the address space on implicit
141+ object parameter `this` must be specified using address space qualifiers
138142on member functions (see <<addrspace-member-function-qualifiers,
139143_Member function qualifier_>>). For example, use of member functions with
140144objects in `+__constant+` address space will always require a `+__constant+`
@@ -148,7 +152,7 @@ be implemented to exploit memory access coalescing for segments with memory bank
148152Address spaces are not deduced for:
149153
150154 * non-pointer/non-reference template parameters except for template
151- specializations or non-type type based template parameters.
155+ specializations or non-type based template parameters.
152156 * non-pointer/non-reference class members except for static data members
153157 that are deduced to the `+__global+` address space for {cpp} for OpenCL 1.0
154158 or {cpp} for OpenCL 2021 with the
@@ -316,37 +320,37 @@ class C {
316320
317321 // C(const C & par); /* 'this'/'par' is a pointer/reference to */
318322 /* object in generic address space */
319- /* if supported */
323+ /* if supported, or */
320324 /* in private address space otherwise. */
321325
322326 // C(C && par); /* 'this'/'par' is a pointer/r-val reference to */
323- /* object in generic address space if supported */
327+ /* object in generic address space if supported, or */
324328 /* in private address space otherwise. */
325329
326330 // C & operator=(const C & par); /* 'this'/'par'/return value is */
327331 /* a pointer/reference/reference to */
328332 /* object in generic address space */
329- /* if supported */
333+ /* if supported, or */
330334 /* in private address space otherwise. */
331335
332336 // C & operator=(C && par)'; /* 'this'/'par'/return value is */
333337 /* a pointer/r-val reference/reference to */
334338 /* object in generic address space, */
335- /* if it is supported or */
339+ /* if supported, or */
336340 /* in private address space otherwise. */
337341};
338342------------
339343
340344==== Builtin operators
341345
342- All builtin operators are available in the specific named address spaces, thus
346+ All builtin operators are available with the specific address spaces, thus
343347no address space conversions (i.e. to generic address space) are performed.
344348
345349==== Templates
346350
347351There is no deduction of address spaces in non-pointer/non-reference
348352template parameters and dependent types (see <<addrspace-deduction,
349- _Deduction_ >>). The address space of a template parameter is deduced
353+ _Address space inference_ >>). The address space of a template parameter is deduced
350354during type deduction if it is not explicitly provided in the
351355instantiation.
352356
@@ -385,7 +389,7 @@ void bar() {
385389------------
386390
387391Once a template has been instantiated, regular restrictions for
388- address spaces will apply.
392+ address spaces will apply as described in `OpenCL C 3.0 s6.7` .
389393
390394[source,cpp]
391395------------
@@ -418,10 +422,11 @@ void foo() {
418422 // of parameter reference.
419423}
420424
421- __global const int& f(__global float &ref) {
422- return ref; // error: address space mismatch between temporary object
423- // created to hold value converted float->int and return
424- // value type (can't convert from __private to __global).
425+ void f(__global float &ref) {
426+ __global const int& newref = ref; // error: address space mismatch between
427+ // temporary object created to hold value
428+ // converted float->int and local variable
429+ // (can't convert from __private to __global).
425430}
426431------------
427432
@@ -458,8 +463,8 @@ public:
458463};
459464__kernel void foo() {
460465 __local C locobj{}; // error: local address space objects can't be initialized
461- __local C locobj; // uninitialised object
462- locobj = {}; // calling copy assignment operator is allowed
466+ __local C locobj; // uninitialised object.
467+ locobj = {}; // calling copy assignment operator is allowed.
463468 locobj.~C(); // local address space object destructors are not invoked
464469 // automatically.
465470}
@@ -474,7 +479,7 @@ Objects in `+__constant+` address space can be initialized using:
474479 * Literal expressions;
475480 * Uniform initialization syntax `{}`;
476481 * Using implicit constructors.
477- * Using constexpr constructors.
482+ * Using ` constexpr` constructors.
478483
479484[source,cpp]
480485------------
@@ -487,44 +492,67 @@ struct C2 {
487492 constexpr C2(int init) __constant : m(init) {};
488493};
489494
490- __constant C1 cobj1 = {1};
491- __constant C1 cobj2 = C1();
492- __constant C2 cobj3 (1);
495+ __constant C1 c1obj1 = {1};
496+ __constant C1 c1obj2 = C1();
497+ __constant C2 c2obj1 (1);
493498------------
494499
495500Non-trivial destructors for objects in non-default address spaces (i.e. all
496- other than generic address space) are not required to be supported by
497- implementations. The macro `+__opencl_cpp_destructor_with_address_spaces+`,
501+ other than generic address space when it is supported or `+__private+`
502+ otherwise) are not required to be supported by implementations.
503+ The macro `+__opencl_cpp_destructor_with_address_spaces+`,
498504which is defined if and only if such destructors are supported by an
499505implementation, can be used to check whether this functionality can be used
500506in kernel sources. Additionally destructors with global objects might not be
501507supported even if address spaces are supported with destructors in general.
502508Such functionality is indicated by the presence of the
503509`+__opencl_cpp_global_destructor+` macro. If the macro
504510`+__opencl_cpp_global_destructor+` is defined then
505- `+__opencl_cpp_destructor_with_address_spaces+` must also be defined. Note that
506- the destruction of objects in named address spaces global, local, or private
507- can be performed using destructors with default address space (i.e. generic)
508- by utilising address space conversions.
511+ `+__opencl_cpp_destructor_with_address_spaces+` must also be defined.
512+
513+ Note that the destruction of objects in named address spaces `+__global+`,
514+ `+__local+`, or `+__private+` can be performed using destructors with
515+ default address space (i.e. generic) by utilising address space conversions.
509516
510517[source,cpp]
511518------------
512- 1 class C {
513- 2 public:
514- 3 #ifdef __opencl_cpp_destructor_with_address_spaces
515- 4 ~C() __local;
516- 5 #else
517- 6 ~C();
518- 7 #endif
519- 8 };
520- 9
521- 10 kernel void foo() {
522- 11 __local C locobj;
523- 12 locobj.~C(); // uses destructor in local address space (on line 4)
524- 13 // if such destructors are supported,
525- 14 // otherwise uses generic address space destructor (on line 6)
526- 15 // converting to generic address prior to call into destructor.
527- 16 }
519+ 1 // Example assumes generic address space support.
520+ 2 class C {
521+ 3 public:
522+ 4 #ifdef __opencl_cpp_destructor_with_address_spaces
523+ 5 ~C() __local;
524+ 6 #else
525+ 7 ~C();
526+ 8 #endif
527+ 9 };
528+ 10
529+ 11 kernel void foo() {
530+ 12 __local C locobj;
531+ 13 locobj.~C(); // uses destructor in local address space (on line 5)
532+ 14 // if such destructors are supported,
533+ 15 // otherwise uses generic address space destructor (on line 7)
534+ 16 // converting to generic address prior to call into destructor.
535+ 17 }
536+ ------------
537+
538+ However, when generic address space feature is unsupported, absence of
539+ destructor support with address spaces results in a compilation failure
540+ when such destructors overloaded with non-default address spaces are
541+ encountered in the kernel code.
542+
543+ [source,cpp]
544+ ------------
545+ // Example assumes generic address space is not supported.
546+ class C {
547+ public:
548+ ~C();
549+ };
550+
551+ kernel void foo() {
552+ __local C locobj;
553+ locobj.~C(); // error due to illegal conversion of 'this' from __local
554+ // to __private address space pointer.
555+ }
528556------------
529557
530558==== Nested pointers
@@ -553,29 +581,30 @@ defdefptr = reinterpret_cast<int * *>(cnstdefptr); // legal.
553581------------
554582
555583[[remove-addrspace]]
556- ==== Address space removal
584+ ==== Address space removal type trait
557585
558586`+template<class T> struct __remove_address_space;+`
559587
560- {cpp} for OpenCL 2021 supports utility `+__remove_address_space+` which allows to
561- derive types that have address space qualifiers removed. Its effect is analogous
562- to `+__remove_const+` and other similar traits in {cpp}17 `[meta.trans]`. The
563- utility only removes an address space qualifier from a given type, therefore, other
564- type qualifiers such as `+const+` or `+volatile+` remain unchanged.
588+ {cpp} for OpenCL 2021 supports the type trait `+__remove_address_space+`
589+ that provides the member `typedef type` which is the same as `T`, except
590+ that its topmost address space qualifier is removed. Its effect is analogous
591+ to `+remove_const+` and other similar type traits in {cpp}17 `[meta.trans]`.
592+ The trait only removes an address space qualifier from a given type, therefore,
593+ all other type qualifiers such as `+const+` or `+volatile+` remain unchanged.
565594
566595[source,cpp]
567- ----------
596+ ------------
568597template<typename T>
569598void foo(T *par) {
570599 T var1; // error: function scope variable cannot be declared in global
571- // address space
600+ // address space.
572601 __private T var2; // error: conflicting address space qualifiers are provided
573- // between types '__private T' and '__global int'
574- __private __remove_address_space<T>::type var3; // type of var3 is __private int
602+ // between types '__private T' and '__global int'.
603+ __private __remove_address_space<T>::type var3; // type of var3 is __private int.
575604}
576605
577606void bar() {
578607 __global int* ptr;
579608 foo(ptr);
580609}
581- ----------
610+ ------------
0 commit comments