Skip to content

Commit 95beeec

Browse files
[SYCL] Replace hardcoded namespaces with attribute
Namespaces were hardcoded and used in compiler to check for various SYCL types including accessors, spec_constants, etc. This patch implements an attribute to uniquely identify the types instead. Attribute argument is an Identifier which denotes each type. E.g. __attribute__((sycl_type(accessor)) is used to mark accessor class. The attribite has been implemented as with an accepted list of arguments via EnumArg. The attribute definition should be updated to support any new types. The attribute takes 1 argument. Signed-off-by: Elizabeth Andrews <[email protected]>
1 parent 5b2cfe2 commit 95beeec

20 files changed

+242
-290
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,6 +1281,23 @@ def SYCLSpecialClass: InheritableAttr {
12811281
let Documentation = [SYCLSpecialClassDocs];
12821282
}
12831283

1284+
def SYCLType: InheritableAttr {
1285+
let Spellings = [Clang<"sycl_type">];
1286+
let Subjects = SubjectList<[CXXRecord, Enum], ErrorDiag>;
1287+
let LangOpts = [SYCLIsDevice, SYCLIsHost];
1288+
let Args = [EnumArgument<"Type", "SYCLType",
1289+
["accessor", "local_accessor", "spec_constant",
1290+
"specialization_id", "kernel_handler", "buffer_location",
1291+
"no_alias", "accessor_property_list", "group",
1292+
"private_memory", "aspect"],
1293+
["accessor", "local_accessor", "spec_constant",
1294+
"specialization_id", "kernel_handler", "buffer_location",
1295+
"no_alias", "accessor_property_list", "group",
1296+
"private_memory", "aspect"]>];
1297+
// Only used internally by SYCL implementation
1298+
let Documentation = [Undocumented];
1299+
}
1300+
12841301
def SYCLDeviceHas : InheritableAttr {
12851302
let Spellings = [CXX11<"sycl", "device_has">];
12861303
let Subjects = SubjectList<[Function], ErrorDiag>;

clang/include/clang/Sema/Sema.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10855,6 +10855,9 @@ class Sema final {
1085510855
ReqdWorkGroupSizeAttr *
1085610856
MergeReqdWorkGroupSizeAttr(Decl *D, const ReqdWorkGroupSizeAttr &A);
1085710857

10858+
SYCLTypeAttr *MergeSYCLTypeAttr(Decl *D, const AttributeCommonInfo &CI,
10859+
SYCLTypeAttr::SYCLType TypeName);
10860+
1085810861
/// Only called on function definitions; if there is a MSVC #pragma optimize
1085910862
/// in scope, consider changing the function's attributes based on the
1086010863
/// optimization list passed to the pragma.
@@ -13543,12 +13546,16 @@ class Sema final {
1354313546
const CXXRecordDecl *RecTy = Ty->getAsCXXRecordDecl();
1354413547
if (!RecTy)
1354513548
return false;
13549+
13550+
if (RecTy->hasAttr<AttrTy>())
13551+
return true;
13552+
1354613553
if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RecTy)) {
1354713554
ClassTemplateDecl *Template = CTSD->getSpecializedTemplate();
1354813555
if (CXXRecordDecl *RD = Template->getTemplatedDecl())
1354913556
return RD->hasAttr<AttrTy>();
1355013557
}
13551-
return RecTy->hasAttr<AttrTy>();
13558+
return false;
1355213559
}
1355313560

1355413561
private:

clang/lib/Sema/SemaDecl.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2918,6 +2918,8 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
29182918
NewAttr = S.MergeSYCLDeviceHasAttr(D, *A);
29192919
else if (const auto *A = dyn_cast<SYCLUsesAspectsAttr>(Attr))
29202920
NewAttr = S.MergeSYCLUsesAspectsAttr(D, *A);
2921+
else if (const auto *A = dyn_cast<SYCLTypeAttr>(Attr))
2922+
NewAttr = S.MergeSYCLTypeAttr(D, *A, A->getType());
29212923
else if (const auto *A = dyn_cast<SYCLIntelPipeIOAttr>(Attr))
29222924
NewAttr = S.MergeSYCLIntelPipeIOAttr(D, *A);
29232925
else if (const auto *A = dyn_cast<SYCLIntelMaxWorkGroupSizeAttr>(Attr))

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 39 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10412,46 +10412,15 @@ static void handleFunctionReturnThunksAttr(Sema &S, Decl *D,
1041210412
D->addAttr(FunctionReturnThunksAttr::Create(S.Context, Kind, AL));
1041310413
}
1041410414

10415-
static constexpr std::pair<Decl::Kind, StringRef>
10416-
MakeDeclContextDesc(Decl::Kind K, StringRef SR) {
10417-
return std::pair<Decl::Kind, StringRef>{K, SR};
10418-
}
10419-
10420-
// FIXME: Refactor Util class in SemaSYCL.cpp to avoid following
10421-
// code duplication.
1042210415
bool isDeviceAspectType(const QualType Ty) {
1042310416
const EnumType *ET = Ty->getAs<EnumType>();
1042410417
if (!ET)
1042510418
return false;
1042610419

10427-
std::array<std::pair<Decl::Kind, StringRef>, 3> Scopes = {
10428-
MakeDeclContextDesc(Decl::Kind::Namespace, "sycl"),
10429-
MakeDeclContextDesc(Decl::Kind::Namespace, "_V1"),
10430-
MakeDeclContextDesc(Decl::Kind::Enum, "aspect")};
10431-
10432-
const auto *Ctx = cast<DeclContext>(ET->getDecl());
10433-
StringRef Name = "";
10434-
10435-
for (const auto &Scope : llvm::reverse(Scopes)) {
10436-
Decl::Kind DK = Ctx->getDeclKind();
10437-
if (DK != Scope.first)
10438-
return false;
10420+
if (const SYCLTypeAttr *Attr = ET->getDecl()->getAttr<SYCLTypeAttr>())
10421+
return Attr->getType() == SYCLTypeAttr::aspect;
1043910422

10440-
switch (DK) {
10441-
case Decl::Kind::Enum:
10442-
Name = cast<EnumDecl>(Ctx)->getName();
10443-
break;
10444-
case Decl::Kind::Namespace:
10445-
Name = cast<NamespaceDecl>(Ctx)->getName();
10446-
break;
10447-
default:
10448-
llvm_unreachable("isDeviceAspectType: decl kind not supported");
10449-
}
10450-
if (Name != Scope.second)
10451-
return false;
10452-
Ctx = Ctx->getParent();
10453-
}
10454-
return Ctx->isTranslationUnit();
10423+
return false;
1045510424
}
1045610425

1045710426
SYCLDeviceHasAttr *Sema::MergeSYCLDeviceHasAttr(Decl *D,
@@ -10576,6 +10545,39 @@ static void handleSYCLKernelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
1057610545
handleSimpleAttribute<SYCLKernelAttr>(S, D, AL);
1057710546
}
1057810547

10548+
SYCLTypeAttr *Sema::MergeSYCLTypeAttr(Decl *D, const AttributeCommonInfo &CI,
10549+
SYCLTypeAttr::SYCLType TypeName) {
10550+
if (const auto ExistingAttr = D->getAttr<SYCLTypeAttr>()) {
10551+
if (ExistingAttr->getType() != TypeName) {
10552+
Diag(ExistingAttr->getLoc(), diag::warn_duplicate_attribute)
10553+
<< ExistingAttr;
10554+
Diag(CI.getLoc(), diag::note_previous_attribute);
10555+
}
10556+
// Do not add duplicate attribute
10557+
return nullptr;
10558+
}
10559+
return ::new (Context) SYCLTypeAttr(Context, CI, TypeName);
10560+
}
10561+
10562+
static void handleSYCLTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
10563+
if (!AL.isArgIdent(0)) {
10564+
S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
10565+
<< AL << AANT_ArgumentIdentifier;
10566+
return;
10567+
}
10568+
10569+
IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
10570+
SYCLTypeAttr::SYCLType Type;
10571+
10572+
if (!SYCLTypeAttr::ConvertStrToSYCLType(II->getName(), Type)) {
10573+
S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
10574+
return;
10575+
}
10576+
10577+
if (SYCLTypeAttr *NewAttr = S.MergeSYCLTypeAttr(D, AL, Type))
10578+
D->addAttr(NewAttr);
10579+
}
10580+
1057910581
static void handleDestroyAttr(Sema &S, Decl *D, const ParsedAttr &A) {
1058010582
if (!cast<VarDecl>(D)->hasGlobalStorage()) {
1058110583
S.Diag(D->getLocation(), diag::err_destroy_attr_on_non_static_var)
@@ -11128,6 +11130,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
1112811130
case ParsedAttr::AT_SYCLSpecialClass:
1112911131
handleSimpleAttribute<SYCLSpecialClassAttr>(S, D, AL);
1113011132
break;
11133+
case ParsedAttr::AT_SYCLType:
11134+
handleSYCLTypeAttr(S, D, AL);
11135+
break;
1113111136
case ParsedAttr::AT_SYCLDevice:
1113211137
handleSYCLDeviceAttr(S, D, AL);
1113311138
break;

0 commit comments

Comments
 (0)