@@ -159,7 +159,7 @@ template <typename dataT,
159
159
access::target accessTarget,
160
160
access::placeholder isPlaceholder,
161
161
typename PropertyListT = ext::oneapi::property_list<>>
162
- class accessor {/* ... */};
162
+ class __attribute__((sycl_special_class)) accessor {/* ... */};
163
163
164
164
} // namespace sycl
165
165
```
@@ -176,7 +176,8 @@ accessor acc(buf, cgh, property_list{no_alias_v, foo_v<32>});
176
176
177
177
As before, the header file represents the properties with an internal C++
178
178
attribute, where the initial parameters are the names of the properties and
179
- the subsequent parameters are the property values.
179
+ the subsequent parameters are the property values. However, this time the
180
+ attribute decorates one of the member variables.
180
181
181
182
```
182
183
namespace sycl {
@@ -187,7 +188,7 @@ template <typename dataT,
187
188
access::target accessTarget,
188
189
access::placeholder isPlaceholder,
189
190
typename PropertyListT = ext::oneapi::property_list<>>
190
- class accessor {/* ... */};
191
+ class __attribute__((sycl_special_class)) accessor {/* ... */};
191
192
192
193
// Partial specialization to make PropertyListT visible as a parameter pack
193
194
// of properties.
@@ -197,18 +198,20 @@ template <typename dataT,
197
198
access::target accessTarget,
198
199
access::placeholder isPlaceholder,
199
200
typename ...Props>
200
- class
201
+ class __attribute__((sycl_special_class)) accessor<dataT,
202
+ dimensions,
203
+ accessmode,
204
+ accessTarget,
205
+ isPlaceholder,
206
+ property_list<Props...>> {
207
+ dataT *ptr
201
208
#ifdef __SYCL_DEVICE_ONLY__
202
209
[[__sycl_detail__::add_ir_kernel_parameter_attributes(
203
210
Props::meta_name..., Props::meta_value...
204
211
)]]
205
212
#endif
206
- accessor<dataT,
207
- dimensions,
208
- accessmode,
209
- accessTarget,
210
- isPlaceholder,
211
- property_list<Props...>> {/*...*/};
213
+ ;
214
+ };
212
215
213
216
} // namespace sycl
214
217
```
@@ -218,7 +221,9 @@ Illustrating this with the previous example:
218
221
```
219
222
namespace sycl {
220
223
221
- template </* ... */> class
224
+ template </* ... */>
225
+ class __attribute__((sycl_special_class)) accessor</* ... */> {
226
+ dataT *ptr
222
227
#ifdef __SYCL_DEVICE_ONLY__
223
228
[[__sycl_detail__::add_ir_kernel_parameter_attributes(
224
229
"sycl-no-alias", // Name of first property
@@ -227,47 +232,34 @@ template </* ... */> class
227
232
32 // Value of second property
228
233
)]]
229
234
#endif
230
- accessor</* ... */> {/* ... */};
235
+ ;
236
+ };
231
237
232
238
} // namespace sycl
233
239
```
234
240
235
- As the name of the C++ attribute suggests, the device compiler front-end uses
236
- the attribute only when the decorated type is the type of a kernel argument,
241
+ As the name implies, this C++ attribute is only used to decorate a member
242
+ variable of a class type that is as SYCL "special class" (i.e. a class that is
243
+ decorated with ` __attribute__((sycl_special_class)) ` ). The device compiler
244
+ front-end ignores the attribute when it is used in any other syntactic
245
+ position.
246
+
247
+ The device compiler front-end uses this attribute only when the class type
248
+ containing the decorated member variable is the type of a kernel argument,
237
249
and it silently ignores the attribute when the class is used in any other way.
238
250
239
- When the device compiler front-end creates a kernel argument in this way, it
240
- adds one LLVM IR attribute to the kernel function's parameter for each property
241
- in the list. For example, this can be done by calling
251
+ When the front-end creates a kernel argument from a SYCL "special class", it
252
+ passes each member variable of the class as a separate kernel argument. If the
253
+ member variable is decorated with
254
+ ` [[__sycl_detail__::add_ir_kernel_parameter_attributes()]] ` , the front-end adds
255
+ one LLVM IR attribute to the kernel function's parameter for each property in
256
+ the list. For example, this can be done by calling
242
257
[ ` Function::addParamAttrs(unsigned ArgNo, const AttrBuilder &) ` ] [ 7 ] . As
243
258
before, the IR attributes are added as strings, so the front-end must convert
244
259
the property value to a string if it is not already a string.
245
260
246
261
[ 7 ] : < https://llvm.org/doxygen/classllvm_1_1Function.html#a092beb46ecce99e6b39628ee92ccd95a >
247
262
248
- ** TODO** : There are a number of open issues with this attribute and with the
249
- semantics of properties that are represented as attributes on kernel
250
- arguments. Suppose there are two SYCL types that take properties: _ A_ and
251
- _ B_ . (For example, this could be two specializations of ` annotated_ptr ` , each
252
- decorated with different properties.) Now suppose the application creates a
253
- struct that contains members with both of these types, and it passes that
254
- struct as a kernel argument. What is the intended semantic? Does the argument
255
- get decorated with the union of the properties on both _ A_ and _ B_ ? What if
256
- those properties are mutually exclusive? A similar case exists when the
257
- application creates a struct that inherits from both _ A_ and _ B_ .
258
-
259
- The previous example shows a case when a single kernel argument gets properties
260
- from two (or more) types. However, the opposite can also occur. Certain SYCL
261
- classes are decorated with ` __attribute__((sycl_special_class)) ` , which causes
262
- the compiler to pass each member of that class as a separate kernel argument.
263
- What should happen with the properties that decorate the class? Should the
264
- compiler duplicate the properties on each such kernel argument? Or, maybe it
265
- should be the header file's responsibility not to decorate such a class with
266
- ` [[__sycl_detail__::add_ir_kernel_parameter_attributes()]] ` , and instead it
267
- should decorate specific member variable(s) with this attribute? How does the
268
- header decide which properties are used to decorate which member variables,
269
- though?
270
-
271
263
272
264
## Properties on kernel functions
273
265
@@ -402,8 +394,8 @@ void foo(int *p) {
402
394
}
403
395
```
404
396
405
- We again implement the property list in the header via a C++ attribute, though
406
- this time the attribute decorates a member variable of the class:
397
+ We again implement the property list in the header via a C++ attribute, where
398
+ the attribute decorates a member variable of the class:
407
399
408
400
```
409
401
namespace sycl::ext::oneapi {
@@ -652,24 +644,21 @@ template <typename dataT,
652
644
access::target accessTarget,
653
645
access::placeholder isPlaceholder,
654
646
typename ...Props>
655
- class
647
+ class __attribute__((sycl_special_class)) accessor<dataT,
648
+ dimensions,
649
+ accessmode,
650
+ accessTarget,
651
+ isPlaceholder,
652
+ property_list<Props...>> {
653
+ T *ptr
656
654
#ifdef __SYCL_DEVICE_ONLY__
657
- [[__sycl_detail__::add_ir_kernel_parameter_attributes(
655
+ [[__sycl_detail__::add_ir_kernel_parameter_attributes(
658
656
659
- // The properties in this list are "kernel parameter attributes".
660
- {"sycl-no-alias", "sycl-foo"},
657
+ // The properties in this list are "kernel parameter attributes".
658
+ {"sycl-no-alias", "sycl-foo"},
661
659
662
- Props::meta_name..., Props::meta_value...
663
- )]]
664
- #endif
665
- accessor<dataT,
666
- dimensions,
667
- accessmode,
668
- accessTarget,
669
- isPlaceholder,
670
- property_list<Props...>> {
671
- T *ptr
672
- #ifdef __SYCL_DEVICE_ONLY__
660
+ Props::meta_name..., Props::meta_value...
661
+ )]]
673
662
[[__sycl_detail__::add_ir_member_annotation(
674
663
675
664
// The properties in this list are "member annotations".
0 commit comments