Skip to content

Commit 211d598

Browse files
[C++ for OpenCL] Minor editorial fixes (#742)
This commit contains the following small fixups: - Formatting and styling improvements; - Corrections to cross-references; - Wording improvements and clarifications; - Improvements to code examples. Aside from these, it also contains clarification about releasing version 2021 as provisional. Co-authored-by: Sven van Haastregt <sven.vanhaastregt@arm.com>
1 parent 1525c7b commit 211d598

6 files changed

Lines changed: 129 additions & 89 deletions

File tree

cxx4opencl/address_spaces.txt

Lines changed: 88 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ therefore, no valid conversion between `+__constant+` and any other address spac
2828
exists. This is aligned with rules from `OpenCL C 3.0 s6.7.9` and this logic
2929
regulates semantics described in this section.
3030

31+
[[address_space_casts]]
3132
==== Casts
3233

3334
C-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.
8687
By default references refer to generic address space objects if generic
8788
address space is supported or private address space otherwise, except
8889
for 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
------------
103104
void 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
132135
generic address space if it is supported and in the private address space
133136
otherwise. All concrete objects passed as an argument to the
134137
implicit `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
138142
on member functions (see <<addrspace-member-function-qualifiers,
139143
_Member function qualifier_>>). For example, use of member functions with
140144
objects 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
148152
Address 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
343347
no address space conversions (i.e. to generic address space) are performed.
344348

345349
==== Templates
346350

347351
There is no deduction of address spaces in non-pointer/non-reference
348352
template 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
350354
during type deduction if it is not explicitly provided in the
351355
instantiation.
352356

@@ -385,7 +389,7 @@ void bar() {
385389
------------
386390

387391
Once 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

495500
Non-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+`,
498504
which is defined if and only if such destructors are supported by an
499505
implementation, can be used to check whether this functionality can be used
500506
in kernel sources. Additionally destructors with global objects might not be
501507
supported even if address spaces are supported with destructors in general.
502508
Such 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+
------------
568597
template<typename T>
569598
void 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

577606
void bar() {
578607
__global int* ptr;
579608
foo(ptr);
580609
}
581-
----------
610+
------------

cxx4opencl/cxxcasts.txt

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
[[cxxcasts]]
66
=== {cpp} casts
77

8-
{cpp} has 3 casts in addition to C-style casts. `static_cast` and `const_cast`
9-
function the same way as in {cpp}, but `reinterpret_cast` has some additional
10-
functionality:
8+
{cpp} has three cast operators in addition to C-style casts. Additional
9+
logic specific to address spaces are applied to all casts as detailed in
10+
<<address_space_casts, _conversions with address spaces_>>.
11+
`reinterpret_cast` has some additional functionality:
1112

1213
* Conversion between vectors and scalars are allowed.
1314
* Conversion between OpenCL types are disallowed.
@@ -20,26 +21,27 @@ pointers. In {cpp} for openCL this also includes vector types, and so using
2021
size of the vectors are the same.
2122

2223
[source,cpp]
23-
----------
24+
------------
2425
int i;
2526
short2 s2 = reinterpret_cast<short2>(i); // legal.
2627
int2 i2 = reinterpret_cast<int2>(i); // illegal.
2728

2829
short8 s8;
2930
int4 i4 = reinterpret_cast<int4>(s8); // legal.
3031
long l4 = reinterpret_cast<long>(s8); // illegal.
31-
----------
32+
------------
3233

3334
==== OpenCL types
3435

35-
Some of the OpenCL types are the same size as integers, or can be implemented as
36-
integers, but since they are not conceptually integral, they can not be used
37-
with `reinterpret_cast`. Therefore these are all illegal conversions:
36+
Some of the OpenCL-specific types, defined as "Other Built-in Data Types" in
37+
`OpenCL C 3.0 s6.3.3`, are convertible to integer literals, but since they
38+
are not conceptually integral, they can not be used with `reinterpret_cast`.
39+
Therefore conversions of an OpenCL-specific type to any distinct type are
40+
illegal.
3841

3942
[source,cpp]
40-
----------
41-
reserve_id_t id;
42-
reserve_id_t id2 = reinterpret_cast<reserve_id_t>(id); // illegal.
43-
int i = reinterpret_cast<int>(r); // illegal.
44-
long l = reinterpret_cast<long>(r); // illegal.
45-
----------
43+
------------
44+
queue_t q;
45+
reserve_id_t id = reinterpret_cast<reserve_id_t>(q); // illegal.
46+
int i = reinterpret_cast<int>(id); // illegal.
47+
------------

cxx4opencl/diff2cxx.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,4 @@ macro{fn-feature-macro}.
3535
The list above only contains extra restrictions that are not detailed in OpenCL
3636
C specification. As OpenCL restricts a number of C features, the same restrictions
3737
are inherited by C++ for OpenCL. The detailed list of C feature restrictions
38-
is provided in `OpenCL C 3.0 section 6.11`.
38+
is provided in `OpenCL C 3.0 s6.11`.

0 commit comments

Comments
 (0)