From 035192677f17af0084c8adc36e9ae491bf0ee2b4 Mon Sep 17 00:00:00 2001 From: Brox Chen Date: Wed, 29 Nov 2023 17:17:38 -0500 Subject: [PATCH] [SYCL] Forbid non-trivially-copyable type in annotated_ptr/ref class (#11798) 1. Explicitly state that use non-trivially-copyable type in annotated_ptr and annotated_ref is not supported and error out if annotated_ptr is constructed with non-trivially-copyable type 2. `void` is allowed on annotated_ptr as an exception 3. Use pass-by-value in annotated_ref operator= now, and updated the spec this fix volatile type not supported in the following code ``` void func(const T& a) { ... } volatile T b; func(b); // this will error out ``` --- .../sycl_ext_oneapi_annotated_ptr.asciidoc | 33 ++++++++++++++++--- .../annotated_ptr/annotated_ptr.hpp | 14 ++++++-- .../Annotated_arg_ptr/annotated_ptr.cpp | 17 ++++++++++ .../annotated_ptr/annotated_ptr.cpp | 12 +++++++ 4 files changed, 70 insertions(+), 6 deletions(-) diff --git a/sycl/doc/extensions/experimental/sycl_ext_oneapi_annotated_ptr.asciidoc b/sycl/doc/extensions/experimental/sycl_ext_oneapi_annotated_ptr.asciidoc index ab52b10876ae2..de8691e47c1f2 100644 --- a/sycl/doc/extensions/experimental/sycl_ext_oneapi_annotated_ptr.asciidoc +++ b/sycl/doc/extensions/experimental/sycl_ext_oneapi_annotated_ptr.asciidoc @@ -183,6 +183,31 @@ information provided as compile-time constant properties through all uses of the pointer unless noted otherwise. .Unsupported Usage Example +[source,c++] +---- +using sycl::ext::oneapi::experimental; +struct MyType { + MyType(const MyType& otherM) { + ... + } +}; + +struct MyKernel { + annotated_ptr> a; //non-trivially-copyable type is not allowed + annotated_ptr> b; //void is legal + ... + void operator()() const { + ... + *b = ...; //deference is not allowed + } +}; +---- +It is ill-formed to instantiate`annotated_ptr` and `annotated_ref` for a non-trivially-copyable +type `T`. The only exception is that `annotated_ptr` is allowed to be instantiated with `void`. + +In the above example, encapsulating `annotated_ptr` within `MyType` is illegal. Encapsulating +`annotated_ptr` with `void` is legal, but it can not be deferenced. + [source,c++] ---- using sycl::ext::oneapi::experimental; @@ -524,10 +549,10 @@ class annotated_ref { public: annotated_ref(const annotated_ref&) = delete; operator T() const; - T operator=(const T &) const; + T operator=(T) const; T operator=(const annotated_ref&) const; // OP is: +=, -=, *=, /=, %=, <<=, >>=, &=, |=, ^= - T operatorOP(const T &) const; + T operatorOP(T) const; T operator++() const; T operator++(int) const; T operator--() const; @@ -556,7 +581,7 @@ annotations when the object is loaded from memory. a| [source,c++] ---- -T operator=(const T &) const; +T operator=(T) const; ---- | Writes an object of type `T` to the location referenced by this wrapper, @@ -583,7 +608,7 @@ Does not rebind the reference! a| [source,c++] ---- -T operatorOP(const T &) const; +T operatorOP(T) const; ---- a| Where [code]#OP# is: [code]#pass:[+=]#, [code]#-=#,[code]#*=#, [code]#/=#, [code]#%=#, [code]#+<<=+#, [code]#>>=#, [code]#&=#, [code]#\|=#, [code]#^=#. diff --git a/sycl/include/sycl/ext/oneapi/experimental/annotated_ptr/annotated_ptr.hpp b/sycl/include/sycl/ext/oneapi/experimental/annotated_ptr/annotated_ptr.hpp index d7a9d8a09ec35..eff081bdc9316 100644 --- a/sycl/include/sycl/ext/oneapi/experimental/annotated_ptr/annotated_ptr.hpp +++ b/sycl/include/sycl/ext/oneapi/experimental/annotated_ptr/annotated_ptr.hpp @@ -32,7 +32,7 @@ namespace experimental { namespace { #define PROPAGATE_OP(op) \ - T operator op##=(const T &rhs) const { \ + T operator op##=(T rhs) const { \ T t = *this; \ t op## = rhs; \ *this = t; \ @@ -78,6 +78,10 @@ template class annotated_ref> { using property_list_t = detail::properties_t; + static_assert( + std::is_trivially_copyable_v, + "annotated_ref can only encapsulate a trivially-copyable type!"); + private: T *m_Ptr; annotated_ref(T *Ptr) : m_Ptr(Ptr) {} @@ -95,7 +99,7 @@ class annotated_ref> { #endif } - T operator=(const T &Obj) const { + T operator=(T Obj) const { #ifdef __SYCL_DEVICE_ONLY__ *__builtin_intel_sycl_ptr_annotation( m_Ptr, detail::PropertyMetaInfo::name..., @@ -178,6 +182,11 @@ class __SYCL_SPECIAL_CLASS __SYCL_TYPE(annotated_ptr) annotated_ptr> { using property_list_t = detail::properties_t; + static_assert(std::is_same_v || std::is_trivially_copyable_v, + "annotated_ptr can only encapsulate either " + "a trivially-copyable type " + "or void!"); + // buffer_location and alignment are allowed for annotated_ref // Cache controls are allowed for annotated_ptr using allowed_properties = @@ -249,6 +258,7 @@ __SYCL_TYPE(annotated_ptr) annotated_ptr> { template explicit annotated_ptr(T *Ptr, const PropertyValueTs &...props) noexcept : m_Ptr(Ptr) { + static constexpr bool has_same_properties = std::is_same< property_list_t, detail::merged_properties_t(4, Q); auto d_ptr = annotated_ptr{d}; + + auto *e1 = malloc_shared(1, Q); + *e1 = 0; + volatile int *e1_vol = e1; + auto e1_ptr = annotated_ptr{e1_vol}; + + auto *e2 = malloc_shared(1, Q); + *e2 = 5; + const volatile int *e2_vol = e2; + auto e2_ptr = annotated_ptr{e2_vol}; + for (int i = 0; i < 4; i++) d_ptr[i] = i; Q.single_task([=]() { @@ -60,6 +71,8 @@ int main() { }; d_ptr[3] = func(d_ptr[0], d_ptr[1], d_ptr[2]); + + e1_ptr[0] = e2_ptr[0]; }).wait(); assert(a_ptr[0] == -1 && "a_ptr[0] value does not match."); @@ -78,11 +91,15 @@ int main() { assert(d_ptr[3] == -1 && "d_ptr[3] value does not match."); + assert(e1_ptr[0] == 5 && "e_ptr[0] value does not match."); + free(a, Q); free(b, Q); free(c->b, Q); free(c, Q); free(d, Q); + free(e1, Q); + free(e2, Q); return 0; } diff --git a/sycl/test/extensions/annotated_ptr/annotated_ptr.cpp b/sycl/test/extensions/annotated_ptr/annotated_ptr.cpp index 7753ed298dcba..89bcef827f5be 100644 --- a/sycl/test/extensions/annotated_ptr/annotated_ptr.cpp +++ b/sycl/test/extensions/annotated_ptr/annotated_ptr.cpp @@ -157,6 +157,18 @@ void TestVectorAddWithAnnotatedMMHosts() { std::cout << raw[i] << std::endl; } + class test { + int n; + + public: + test(int n_) : n(n_) {} + test(const test &t) { n = t.n; } + }; + // expected-error-re@sycl/ext/oneapi/experimental/annotated_ptr/annotated_ptr.hpp:* {{static assertion failed due to requirement {{.+}}: annotated_ptr can only encapsulate either a trivially-copyable type or void!}} + annotated_ptr non_trivially_copyable; + + annotated_ptr void_type; + free(raw, q); }