https://github.com/schittir created https://github.com/llvm/llvm-project/pull/140282
None >From abdbf8905d324f9b935b34bbc97c508ede5ac028 Mon Sep 17 00:00:00 2001 From: "Chittireddy, Sindhu" <sindhu.chittire...@intel.com> Date: Fri, 16 May 2025 08:51:06 -0700 Subject: [PATCH] Add sycl_external attribute --- clang/include/clang/Basic/Attr.td | 20 ++++++- clang/include/clang/Basic/AttrDocs.td | 11 ++++ .../clang/Basic/DiagnosticSemaKinds.td | 5 ++ clang/include/clang/Sema/SemaSYCL.h | 1 + clang/lib/AST/ASTContext.cpp | 7 +++ clang/lib/Sema/SemaDeclAttr.cpp | 3 ++ clang/lib/Sema/SemaSYCL.cpp | 11 ++++ .../test/SemaSYCL/sycl-external-attribute.cpp | 52 +++++++++++++++++++ 8 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 clang/test/SemaSYCL/sycl-external-attribute.cpp diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index ccd13a4cca4dd..1c13d0eb23f3b 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -143,6 +143,7 @@ def SharedVar : SubsetSubject<Var, def GlobalVar : SubsetSubject<Var, [{S->hasGlobalStorage()}], "global variables">; + def ExternalGlobalVar : SubsetSubject<Var, [{S->hasGlobalStorage() && S->getStorageClass()!=StorageClass::SC_Static && @@ -408,10 +409,14 @@ class SubjectList<list<AttrSubject> subjects, SubjectDiag diag = WarnDiag, string CustomDiag = customDiag; } -class LangOpt<string name, code customCode = [{}]> { +class LangOpt<string name, code customCode = [{}], bit silentlyIgnore = 0> { // The language option to test; ignored when custom code is supplied. string Name = name; + // If set to 1, the attribute is accepted but is silently ignored. This is + // useful in multi-compilation situations like SYCL. + bit SilentlyIgnore = silentlyIgnore; + // A custom predicate, written as an expression evaluated in a context with // "LangOpts" bound. code CustomCode = customCode; @@ -422,6 +427,7 @@ def CUDA : LangOpt<"CUDA">; def HIP : LangOpt<"HIP">; def SYCLHost : LangOpt<"SYCLIsHost">; def SYCLDevice : LangOpt<"SYCLIsDevice">; +def SilentlyIgnoreSYCLHost : LangOpt<"SYCLIsHost", "", 1>; def COnly : LangOpt<"", "!LangOpts.CPlusPlus">; def CPlusPlus : LangOpt<"CPlusPlus">; def OpenCL : LangOpt<"OpenCL">; @@ -1545,6 +1551,18 @@ def SYCLKernel : InheritableAttr { let Documentation = [SYCLKernelDocs]; } +def GlobalStorageNonLocalVar : SubsetSubject<Var, + [{S->hasGlobalStorage() && + !S->isLocalVarDeclOrParm()}], + "global variables">; + +def SYCLExternal : InheritableAttr { + let Spellings = [GNU<"sycl_external">]; + let Subjects = SubjectList<[Function, GlobalStorageNonLocalVar]>; + let LangOpts = [SYCLDevice, SilentlyIgnoreSYCLHost]; + let Documentation = [SYCLExternalDocs]; +} + def SYCLKernelEntryPoint : InheritableAttr { let Spellings = [Clang<"sycl_kernel_entry_point">]; let Args = [ diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 5fb5f16680b41..2eef46a1348f3 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -472,6 +472,17 @@ The SYCL kernel in the previous code sample meets these expectations. }]; } +def SYCLExternalDocs : Documentation { + let Category = DocCatFunction; + let Heading = "sycl_external"; + let Content = [{ +The ``sycl_external`` attribute (or the ``SYCL_EXTERNAL`` macro) can only be applied to +functions, and indicates that the function must be treated as a device function and +must be emitted even if it has no direct uses from other device functions. +All ``sycl_external`` function callees implicitly inherit this attribute. + }]; +} + def SYCLKernelEntryPointDocs : Documentation { let Category = DocCatFunction; let Content = [{ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 3efe9593b8633..9228d388bc10b 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -12746,6 +12746,11 @@ def err_sycl_special_type_num_init_method : Error< "types with 'sycl_special_class' attribute must have one and only one '__init' " "method defined">; +//SYCL external attribute diagnostics +def err_sycl_attribute_internal_decl + : Error<"%0 attribute cannot be applied to a %select{function|variable}1" + " without external linkage">; + // SYCL kernel entry point diagnostics def err_sycl_entry_point_invalid : Error< "'sycl_kernel_entry_point' attribute cannot be applied to a" diff --git a/clang/include/clang/Sema/SemaSYCL.h b/clang/include/clang/Sema/SemaSYCL.h index b47b2f155ef93..099cc56b0ef92 100644 --- a/clang/include/clang/Sema/SemaSYCL.h +++ b/clang/include/clang/Sema/SemaSYCL.h @@ -62,6 +62,7 @@ class SemaSYCL : public SemaBase { ParsedType ParsedTy); void handleKernelAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLExternalAttr(Decl *D, const ParsedAttr &AL); void handleKernelEntryPointAttr(Decl *D, const ParsedAttr &AL); void CheckSYCLEntryPointFunctionDecl(FunctionDecl *FD); diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index c58cd2c93fb60..e767b79d0b25f 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -12909,6 +12909,9 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { if (D->hasAttr<WeakRefAttr>()) return false; + if (LangOpts.SYCLIsDevice && !D->hasAttr<SYCLKernelEntryPointAttr>()) + return false; + // Aliases and used decls are required. if (D->hasAttr<AliasAttr>() || D->hasAttr<UsedAttr>()) return true; @@ -12926,6 +12929,10 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { // FIXME: Functions declared with SYCL_EXTERNAL are required during // device compilation. + // Functions definitions with sycl_external attribute are required during + // device compilation. + if (LangOpts.SYCLIsDevice && FD->hasAttr<SYCLExternalAttr>()) + return true; // Constructors and destructors are required. if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>()) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 377595639bef1..271cf417a12f3 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -7113,6 +7113,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_SYCLKernel: S.SYCL().handleKernelAttr(D, AL); break; + case ParsedAttr::AT_SYCLExternal: + S.SYCL().handleSYCLExternalAttr(D, AL); + break; case ParsedAttr::AT_SYCLKernelEntryPoint: S.SYCL().handleKernelEntryPointAttr(D, AL); break; diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index 1969d7b0ba837..a08e2f076fb12 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -202,6 +202,17 @@ void SemaSYCL::handleKernelAttr(Decl *D, const ParsedAttr &AL) { handleSimpleAttribute<SYCLKernelAttr>(*this, D, AL); } +void SemaSYCL::handleSYCLExternalAttr(Decl *D, const ParsedAttr &AL) { + auto *ND = cast<NamedDecl>(D); + if (!ND->isExternallyVisible()) { + Diag(AL.getLoc(), diag::err_sycl_attribute_internal_decl) + << AL << !isa<FunctionDecl>(ND); + return; + } + + handleSimpleAttribute<SYCLExternalAttr>(*this, D, AL); +} + void SemaSYCL::handleKernelEntryPointAttr(Decl *D, const ParsedAttr &AL) { ParsedType PT = AL.getTypeArg(); TypeSourceInfo *TSI = nullptr; diff --git a/clang/test/SemaSYCL/sycl-external-attribute.cpp b/clang/test/SemaSYCL/sycl-external-attribute.cpp new file mode 100644 index 0000000000000..2260dba386a73 --- /dev/null +++ b/clang/test/SemaSYCL/sycl-external-attribute.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -verify -DSYCL %s +// RUN: %clang_cc1 -fsycl-is-host -fsyntax-only -verify -DHOST %s +// RUN: %clang_cc1 -verify %s + +// Semantic tests for sycl_external attribute + +#ifdef SYCL + +__attribute__((sycl_external(3))) // expected-error {{'sycl_external' attribute takes no arguments}} +void bar() {} + +__attribute__((sycl_external)) // expected-error {{'sycl_external' attribute cannot be applied to a function without external linkage}} +static void func1() {} + +namespace { + __attribute__((sycl_external)) // expected-error {{'sycl_external' attribute cannot be applied to a function without external linkage}} + void func2() {} + + struct UnnX {}; +} + +__attribute__((sycl_external)) // expected-error {{'sycl_external' attribute cannot be applied to a function without external linkage}} + void func4(UnnX) {} + +class A { + __attribute__((sycl_external)) + A() {} + + __attribute__((sycl_external)) void func3() {} +}; + +class B { +public: + __attribute__((sycl_external)) virtual void foo() {} + + __attribute__((sycl_external)) virtual void bar() = 0; +}; + +__attribute__((sycl_external)) int *func0() { return nullptr; } + +__attribute__((sycl_external)) void func2(int *) {} + +#elif defined(HOST) + +// expected-no-diagnostics +__attribute__((sycl_external)) void func3() {} + +#else +__attribute__((sycl_external)) // expected-warning {{'sycl_external' attribute ignored}} +void baz() {} + +#endif _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits