diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 5a607dbc2396d..4f13e02ec1f95 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1135,6 +1135,20 @@ def SYCLKernel : InheritableAttr { let Documentation = [SYCLKernelDocs]; } +def SYCLSpecialClass: InheritableAttr { + let Spellings = [Clang<"sycl_special_class">]; + let Subjects = SubjectList<[CXXRecord]>; + let LangOpts = [SYCLIsDevice, SYCLIsHost]; + // TODO: Add doc + let Documentation = [Undocumented]; + let Args = [ + EnumArgument<"SpecialClassKind", "SpecialClassKind", + [ "accessor", "sampler", "stream", "" ], + [ "Accessor", "Sampler", "Stream", "Generic" ], 1> + ]; + let PragmaAttributeSupport = 0; +} + // Marks functions which must not be vectorized via horizontal SIMT widening, // e.g. because the function is already vectorized. Used to mark SYCL // explicit SIMD kernels and functions. diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index b5170932ae739..5a6e2a6775513 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -7219,6 +7219,31 @@ static void handleSYCLKernelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { handleSimpleAttribute(S, D, AL); } +static void handleSYCLSpecialClassAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + if (S.LangOpts.SYCLIsHost) + return; + + SYCLSpecialClassAttr::SpecialClassKind Kind; + if (AL.getNumArgs() == 0) + Kind = SYCLSpecialClassAttr::Generic; + else { + // Check the attribute arguments. + if (!AL.isArgIdent(0)) { + S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) + << AL << 0 << AANT_ArgumentIdentifier; + return; + } + + IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; + if (!SYCLSpecialClassAttr::ConvertStrToSpecialClassKind(II->getName(), + Kind)) { + S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II; + return; + } + } + D->addAttr(::new (S.Context) SYCLSpecialClassAttr(S.Context, AL, Kind)); +} + static void handleDestroyAttr(Sema &S, Decl *D, const ParsedAttr &A) { if (!cast(D)->hasGlobalStorage()) { S.Diag(D->getLocation(), diag::err_destroy_attr_on_non_static_var) @@ -7600,6 +7625,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_SYCLSimd: handleSimpleAttribute(S, D, AL); break; + case ParsedAttr::AT_SYCLSpecialClass: + handleSYCLSpecialClassAttr(S, D, AL); + break; case ParsedAttr::AT_SYCLDevice: handleSYCLDeviceAttr(S, D, AL); break; diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index 443ed62c30edd..ae8f3aa091c4c 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -2692,17 +2692,33 @@ SYCLIntegrationHeader::SYCLIntegrationHeader(DiagnosticsEngine &_Diag, // ----------------------------------------------------------------------------- bool Util::isSyclAccessorType(const QualType &Ty) { - return isSyclType(Ty, "accessor", true /*Tmpl*/); + const CXXRecordDecl *RecTy = Ty->getAsCXXRecordDecl(); + if (!RecTy) + return false; // only classes/structs supported + if (const auto *A = RecTy->getAttr()) + return A->getSpecialClassKind() == SYCLSpecialClassAttr::Accessor; + return false; } bool Util::isSyclSamplerType(const QualType &Ty) { - return isSyclType(Ty, "sampler"); + const CXXRecordDecl *RecTy = Ty->getAsCXXRecordDecl(); + if (!RecTy) + return false; // only classes/structs supported + if (const auto *A = RecTy->getAttr()) + return A->getSpecialClassKind() == SYCLSpecialClassAttr::Sampler; + return false; } bool Util::isSyclStreamType(const QualType &Ty) { - return isSyclType(Ty, "stream"); + const CXXRecordDecl *RecTy = Ty->getAsCXXRecordDecl(); + if (!RecTy) + return false; // only classes/structs supported + if (const auto *A = RecTy->getAttr()) + return A->getSpecialClassKind() == SYCLSpecialClassAttr::Stream; + return false; } +// TODO: Remove this once structs decomposing is optimized bool Util::isSyclHalfType(const QualType &Ty) { const StringRef &Name = "half"; std::array Scopes = { @@ -2714,6 +2730,7 @@ bool Util::isSyclHalfType(const QualType &Ty) { return matchQualifiedTypeName(Ty, Scopes); } +// TODO: Do we need an attribute for this one as well? bool Util::isSyclSpecConstantType(const QualType &Ty) { const StringRef &Name = "spec_constant"; std::array Scopes = { diff --git a/clang/test/CodeGenSYCL/Inputs/sycl.hpp b/clang/test/CodeGenSYCL/Inputs/sycl.hpp index 3184c58edcbfc..04302bb4ff971 100644 --- a/clang/test/CodeGenSYCL/Inputs/sycl.hpp +++ b/clang/test/CodeGenSYCL/Inputs/sycl.hpp @@ -11,7 +11,7 @@ struct sampler_impl { #endif }; -class sampler { +class __attribute__((sycl_special_class(sampler))) sampler { struct sampler_impl impl; #ifdef __SYCL_DEVICE_ONLY__ void __init(__ocl_sampler_t Sampler) { impl.m_Sampler = Sampler; } @@ -128,7 +128,7 @@ struct _ImplT { template -class accessor { +class __attribute__((sycl_special_class(accessor))) accessor { public: void use(void) const {} @@ -189,7 +189,7 @@ struct _ImageImplT { }; template -class accessor { +class __attribute__((sycl_special_class(accessor))) accessor { public: void use(void) const {} template @@ -310,7 +310,7 @@ class handler { } }; -class stream { +class __attribute__((sycl_special_class(stream))) stream { public: stream(unsigned long BufferSize, unsigned long MaxStatementSize, handler &CGH) {} diff --git a/clang/test/SemaSYCL/Inputs/sycl.hpp b/clang/test/SemaSYCL/Inputs/sycl.hpp index 9e3efc6321096..01329e2e12838 100644 --- a/clang/test/SemaSYCL/Inputs/sycl.hpp +++ b/clang/test/SemaSYCL/Inputs/sycl.hpp @@ -87,7 +87,7 @@ struct DeviceValueType { template -class accessor { +class __attribute__((sycl_special_class(accessor))) accessor { public: void use(void) const {} @@ -146,7 +146,7 @@ struct _ImageImplT { }; template -class accessor { +class __attribute__((sycl_special_class(accessor))) accessor { public: void use(void) const {} template @@ -165,7 +165,7 @@ struct sampler_impl { #endif }; -class sampler { +class __attribute__((sycl_special_class(sampler))) sampler { struct sampler_impl impl; #ifdef __SYCL_DEVICE_ONLY__ void __init(__ocl_sampler_t Sampler) { impl.m_Sampler = Sampler; } diff --git a/sycl/include/CL/sycl/accessor.hpp b/sycl/include/CL/sycl/accessor.hpp index 0b39a2c090c76..b1a6a89f8b90f 100644 --- a/sycl/include/CL/sycl/accessor.hpp +++ b/sycl/include/CL/sycl/accessor.hpp @@ -730,7 +730,7 @@ class __image_array_slice__ { /// \ingroup sycl_api_acc template -class accessor : +class __SYCL_SPECIAL_CLASS(accessor) accessor : #ifndef __SYCL_DEVICE_ONLY__ public detail::AccessorBaseHost, #endif @@ -1350,8 +1350,8 @@ accessor(buffer, handler, Type1, Type2, Type3, /// \ingroup sycl_api_acc template -class accessor : +class __SYCL_SPECIAL_CLASS(accessor) accessor< + DataT, Dimensions, AccessMode, access::target::local, IsPlaceholder> : #ifndef __SYCL_DEVICE_ONLY__ public detail::LocalAccessorBaseHost, #endif @@ -1516,8 +1516,8 @@ class accessor -class accessor +class __SYCL_SPECIAL_CLASS(accessor) accessor< + DataT, Dimensions, AccessMode, access::target::image, IsPlaceholder> : public detail::image_accessor { public: @@ -1580,8 +1580,8 @@ class accessor -class accessor +class __SYCL_SPECIAL_CLASS(accessor) accessor< + DataT, Dimensions, AccessMode, access::target::image_array, IsPlaceholder> : public detail::image_accessor { #ifdef __SYCL_DEVICE_ONLY__ diff --git a/sycl/include/CL/sycl/detail/defines.hpp b/sycl/include/CL/sycl/detail/defines.hpp index c26b2e18d2b9b..e36066ad55fdf 100644 --- a/sycl/include/CL/sycl/detail/defines.hpp +++ b/sycl/include/CL/sycl/detail/defines.hpp @@ -59,3 +59,9 @@ #else #define __SYCL_INLINE_CONSTEXPR static constexpr #endif + +#if __has_attribute(sycl_special_class) +#define __SYCL_SPECIAL_CLASS(kind) __attribute__((sycl_special_class(kind))) +#else +#define __SYCL_SPECIAL_CLASS(kind) +#endif diff --git a/sycl/include/CL/sycl/sampler.hpp b/sycl/include/CL/sycl/sampler.hpp index 5843b0a47bc33..b7ab4ff970296 100644 --- a/sycl/include/CL/sycl/sampler.hpp +++ b/sycl/include/CL/sycl/sampler.hpp @@ -45,7 +45,7 @@ class image_accessor; /// \sa sycl_api_acc /// /// \ingroup sycl_api -class __SYCL_EXPORT sampler { +class __SYCL_EXPORT __SYCL_SPECIAL_CLASS(sampler) sampler { public: sampler(coordinate_normalization_mode normalizationMode, addressing_mode addressingMode, filtering_mode filteringMode); diff --git a/sycl/include/CL/sycl/stream.hpp b/sycl/include/CL/sycl/stream.hpp index 58f038980545d..544cd38cdd88d 100644 --- a/sycl/include/CL/sycl/stream.hpp +++ b/sycl/include/CL/sycl/stream.hpp @@ -94,7 +94,7 @@ inline __width_manipulator__ setw(int Width) { /// vector and SYCL types to the console. /// /// \ingroup sycl_api -class __SYCL_EXPORT stream { +class __SYCL_EXPORT __SYCL_SPECIAL_CLASS(stream) stream { public: stream(size_t BufferSize, size_t MaxStatementSize, handler &CGH);