diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 4da65710d09bc..296703e931b7f 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4702,79 +4702,6 @@ class Sema final : public SemaBase { /// Essentially, this just moves them to the current pool. void redelayDiagnostics(sema::DelayedDiagnosticPool &pool); - SYCLWorkGroupSizeHintAttr * - MergeSYCLWorkGroupSizeHintAttr(Decl *D, const SYCLWorkGroupSizeHintAttr &A); - IntelReqdSubGroupSizeAttr * - MergeIntelReqdSubGroupSizeAttr(Decl *D, const IntelReqdSubGroupSizeAttr &A); - IntelNamedSubGroupSizeAttr * - MergeIntelNamedSubGroupSizeAttr(Decl *D, const IntelNamedSubGroupSizeAttr &A); - SYCLIntelNumSimdWorkItemsAttr * - MergeSYCLIntelNumSimdWorkItemsAttr(Decl *D, - const SYCLIntelNumSimdWorkItemsAttr &A); - SYCLIntelESimdVectorizeAttr * - MergeSYCLIntelESimdVectorizeAttr(Decl *D, - const SYCLIntelESimdVectorizeAttr &A); - SYCLIntelSchedulerTargetFmaxMhzAttr *MergeSYCLIntelSchedulerTargetFmaxMhzAttr( - Decl *D, const SYCLIntelSchedulerTargetFmaxMhzAttr &A); - SYCLIntelNoGlobalWorkOffsetAttr *MergeSYCLIntelNoGlobalWorkOffsetAttr( - Decl *D, const SYCLIntelNoGlobalWorkOffsetAttr &A); - SYCLIntelLoopFuseAttr * - MergeSYCLIntelLoopFuseAttr(Decl *D, const SYCLIntelLoopFuseAttr &A); - SYCLIntelMaxReplicatesAttr * - MergeSYCLIntelMaxReplicatesAttr(Decl *D, const SYCLIntelMaxReplicatesAttr &A); - SYCLIntelForcePow2DepthAttr * - MergeSYCLIntelForcePow2DepthAttr(Decl *D, - const SYCLIntelForcePow2DepthAttr &A); - SYCLIntelInitiationIntervalAttr *MergeSYCLIntelInitiationIntervalAttr( - Decl *D, const SYCLIntelInitiationIntervalAttr &A); - - SYCLIntelMaxConcurrencyAttr * - MergeSYCLIntelMaxConcurrencyAttr(Decl *D, - const SYCLIntelMaxConcurrencyAttr &A); - SYCLIntelMaxGlobalWorkDimAttr * - MergeSYCLIntelMaxGlobalWorkDimAttr(Decl *D, - const SYCLIntelMaxGlobalWorkDimAttr &A); - SYCLIntelMinWorkGroupsPerComputeUnitAttr * - MergeSYCLIntelMinWorkGroupsPerComputeUnitAttr( - Decl *D, const SYCLIntelMinWorkGroupsPerComputeUnitAttr &A); - SYCLIntelMaxWorkGroupsPerMultiprocessorAttr * - MergeSYCLIntelMaxWorkGroupsPerMultiprocessorAttr( - Decl *D, const SYCLIntelMaxWorkGroupsPerMultiprocessorAttr &A); - SYCLIntelBankWidthAttr * - MergeSYCLIntelBankWidthAttr(Decl *D, const SYCLIntelBankWidthAttr &A); - SYCLIntelNumBanksAttr * - MergeSYCLIntelNumBanksAttr(Decl *D, const SYCLIntelNumBanksAttr &A); - SYCLDeviceHasAttr *MergeSYCLDeviceHasAttr(Decl *D, - const SYCLDeviceHasAttr &A); - SYCLUsesAspectsAttr *MergeSYCLUsesAspectsAttr(Decl *D, - const SYCLUsesAspectsAttr &A); - bool CheckMaxAllowedWorkGroupSize(const Expr *RWGSXDim, const Expr *RWGSYDim, - const Expr *RWGSZDim, const Expr *MWGSXDim, - const Expr *MWGSYDim, const Expr *MWGSZDim); - SYCLIntelMaxWorkGroupSizeAttr * - MergeSYCLIntelMaxWorkGroupSizeAttr(Decl *D, - const SYCLIntelMaxWorkGroupSizeAttr &A); - void CheckSYCLAddIRAttributesFunctionAttrConflicts(Decl *D); - SYCLAddIRAttributesFunctionAttr *MergeSYCLAddIRAttributesFunctionAttr( - Decl *D, const SYCLAddIRAttributesFunctionAttr &A); - SYCLAddIRAttributesKernelParameterAttr * - MergeSYCLAddIRAttributesKernelParameterAttr( - Decl *D, const SYCLAddIRAttributesKernelParameterAttr &A); - SYCLAddIRAttributesGlobalVariableAttr * - MergeSYCLAddIRAttributesGlobalVariableAttr( - Decl *D, const SYCLAddIRAttributesGlobalVariableAttr &A); - SYCLAddIRAnnotationsMemberAttr * - MergeSYCLAddIRAnnotationsMemberAttr(Decl *D, - const SYCLAddIRAnnotationsMemberAttr &A); - SYCLReqdWorkGroupSizeAttr * - MergeSYCLReqdWorkGroupSizeAttr(Decl *D, const SYCLReqdWorkGroupSizeAttr &A); - - SYCLTypeAttr *MergeSYCLTypeAttr(Decl *D, const AttributeCommonInfo &CI, - SYCLTypeAttr::SYCLType TypeName); - - SYCLIntelPipeIOAttr *MergeSYCLIntelPipeIOAttr(Decl *D, - const SYCLIntelPipeIOAttr &A); - bool CheckCountedByAttr(Scope *Scope, const FieldDecl *FD); /// Check if IdxExpr is a valid parameter index for a function or /// instance method D. May output an error. diff --git a/clang/include/clang/Sema/SemaSYCL.h b/clang/include/clang/Sema/SemaSYCL.h index 55b2782dcabf6..9455a77bbb7dc 100644 --- a/clang/include/clang/Sema/SemaSYCL.h +++ b/clang/include/clang/Sema/SemaSYCL.h @@ -419,6 +419,124 @@ class SemaSYCL : public SemaBase { ParsedType ParsedTy); void handleKernelAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLTypeAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLDeviceAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLDeviceIndirectlyCallableAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLGlobalVarAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLRegisterNumAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelESimdVectorizeAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLDeviceHasAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLUsesAspectsAttr(Decl *D, const ParsedAttr &AL); + void handleLaunchBoundsAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLWorkGroupSizeHintAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLReqdWorkGroupSizeAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelMaxWorkGroupSizeAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelMinWorkGroupsPerComputeUnitAttr(Decl *D, + const ParsedAttr &AL); + void handleSYCLIntelMaxWorkGroupsPerMultiprocessorAttr(Decl *D, + const ParsedAttr &AL); + void handleIntelReqdSubGroupSizeAttr(Decl *D, const ParsedAttr &AL); + void handleIntelNamedSubGroupSizeAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelNumSimdWorkItemsAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelSchedulerTargetFmaxMhzAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelMaxGlobalWorkDimAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelNoGlobalWorkOffsetAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelUseStallEnableClustersAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelLoopFuseAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelInitiationIntervalAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelDoublePumpAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelSinglePumpAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelMemoryAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelRegisterAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelBankWidthAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelNumBanksAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelPrivateCopiesAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelMaxReplicatesAttr(Decl *D, const ParsedAttr &AL); + void handleIntelSimpleDualPortAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelMergeAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelBankBitsAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelForcePow2DepthAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelPipeIOAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelMaxConcurrencyAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLAddIRAttributesFunctionAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLAddIRAttributesKernelParameterAttr(Decl *D, + const ParsedAttr &AL); + void handleSYCLAddIRAttributesGlobalVariableAttr(Decl *D, + const ParsedAttr &AL); + void handleSYCLAddIRAnnotationsMemberAttr(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelMaxWorkGroupSize(Decl *D, const ParsedAttr &AL); + void handleSYCLIntelMinWorkGroupsPerComputeUnit(Decl *D, + const ParsedAttr &AL); + void handleSYCLIntelMaxWorkGroupsPerMultiprocessor(Decl *D, + const ParsedAttr &AL); + + void checkSYCLAddIRAttributesFunctionAttrConflicts(Decl *D); + + SYCLReqdWorkGroupSizeAttr * + mergeSYCLReqdWorkGroupSizeAttr(Decl *D, const SYCLReqdWorkGroupSizeAttr &A); + SYCLIntelNumSimdWorkItemsAttr * + mergeSYCLIntelNumSimdWorkItemsAttr(Decl *D, + const SYCLIntelNumSimdWorkItemsAttr &A); + SYCLIntelInitiationIntervalAttr *mergeSYCLIntelInitiationIntervalAttr( + Decl *D, const SYCLIntelInitiationIntervalAttr &A); + SYCLIntelSchedulerTargetFmaxMhzAttr *mergeSYCLIntelSchedulerTargetFmaxMhzAttr( + Decl *D, const SYCLIntelSchedulerTargetFmaxMhzAttr &A); + SYCLIntelMaxGlobalWorkDimAttr * + mergeSYCLIntelMaxGlobalWorkDimAttr(Decl *D, + const SYCLIntelMaxGlobalWorkDimAttr &A); + SYCLIntelMinWorkGroupsPerComputeUnitAttr * + mergeSYCLIntelMinWorkGroupsPerComputeUnitAttr( + Decl *D, const SYCLIntelMinWorkGroupsPerComputeUnitAttr &A); + SYCLIntelMaxWorkGroupsPerMultiprocessorAttr * + mergeSYCLIntelMaxWorkGroupsPerMultiprocessorAttr( + Decl *D, const SYCLIntelMaxWorkGroupsPerMultiprocessorAttr &A); + SYCLIntelLoopFuseAttr * + mergeSYCLIntelLoopFuseAttr(Decl *D, const SYCLIntelLoopFuseAttr &A); + SYCLIntelESimdVectorizeAttr * + mergeSYCLIntelESimdVectorizeAttr(Decl *D, + const SYCLIntelESimdVectorizeAttr &A); + SYCLIntelNoGlobalWorkOffsetAttr *mergeSYCLIntelNoGlobalWorkOffsetAttr( + Decl *D, const SYCLIntelNoGlobalWorkOffsetAttr &A); + SYCLIntelBankWidthAttr * + mergeSYCLIntelBankWidthAttr(Decl *D, const SYCLIntelBankWidthAttr &A); + SYCLIntelNumBanksAttr * + mergeSYCLIntelNumBanksAttr(Decl *D, const SYCLIntelNumBanksAttr &A); + SYCLIntelMaxReplicatesAttr * + mergeSYCLIntelMaxReplicatesAttr(Decl *D, const SYCLIntelMaxReplicatesAttr &A); + SYCLIntelForcePow2DepthAttr * + mergeSYCLIntelForcePow2DepthAttr(Decl *D, + const SYCLIntelForcePow2DepthAttr &A); + SYCLIntelPipeIOAttr *mergeSYCLIntelPipeIOAttr(Decl *D, + const SYCLIntelPipeIOAttr &A); + SYCLIntelMaxConcurrencyAttr * + mergeSYCLIntelMaxConcurrencyAttr(Decl *D, + const SYCLIntelMaxConcurrencyAttr &A); + SYCLAddIRAttributesFunctionAttr *mergeSYCLAddIRAttributesFunctionAttr( + Decl *D, const SYCLAddIRAttributesFunctionAttr &A); + SYCLAddIRAttributesKernelParameterAttr * + mergeSYCLAddIRAttributesKernelParameterAttr( + Decl *D, const SYCLAddIRAttributesKernelParameterAttr &A); + SYCLAddIRAttributesGlobalVariableAttr * + mergeSYCLAddIRAttributesGlobalVariableAttr( + Decl *D, const SYCLAddIRAttributesGlobalVariableAttr &A); + SYCLAddIRAnnotationsMemberAttr * + mergeSYCLAddIRAnnotationsMemberAttr(Decl *D, + const SYCLAddIRAnnotationsMemberAttr &A); + SYCLDeviceHasAttr *mergeSYCLDeviceHasAttr(Decl *D, + const SYCLDeviceHasAttr &A); + SYCLUsesAspectsAttr *mergeSYCLUsesAspectsAttr(Decl *D, + const SYCLUsesAspectsAttr &A); + SYCLTypeAttr *mergeSYCLTypeAttr(Decl *D, const AttributeCommonInfo &CI, + SYCLTypeAttr::SYCLType TypeName); + SYCLWorkGroupSizeHintAttr * + mergeSYCLWorkGroupSizeHintAttr(Decl *D, const SYCLWorkGroupSizeHintAttr &A); + SYCLIntelMaxWorkGroupSizeAttr * + mergeSYCLIntelMaxWorkGroupSizeAttr(Decl *D, + const SYCLIntelMaxWorkGroupSizeAttr &A); + IntelReqdSubGroupSizeAttr * + mergeIntelReqdSubGroupSizeAttr(Decl *D, const IntelReqdSubGroupSizeAttr &A); + IntelNamedSubGroupSizeAttr * + mergeIntelNamedSubGroupSizeAttr(Decl *D, const IntelNamedSubGroupSizeAttr &A); static OffloadArch getOffloadArch(const TargetInfo &TI); static bool hasDependentExpr(Expr **Exprs, const size_t ExprsSize); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index f43ffed826209..a315ad3373b48 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2855,69 +2855,69 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, else if (const auto *INA = dyn_cast(Attr)) NewAttr = S.Wasm().mergeImportNameAttr(D, *INA); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLIntelLoopFuseAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLIntelLoopFuseAttr(D, *A); else if (const auto *TCBA = dyn_cast(Attr)) NewAttr = S.mergeEnforceTCBAttr(D, *TCBA); else if (const auto *TCBLA = dyn_cast(Attr)) NewAttr = S.mergeEnforceTCBLeafAttr(D, *TCBLA); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeIntelReqdSubGroupSizeAttr(D, *A); + NewAttr = S.SYCL().mergeIntelReqdSubGroupSizeAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeIntelNamedSubGroupSizeAttr(D, *A); + NewAttr = S.SYCL().mergeIntelNamedSubGroupSizeAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLIntelNumSimdWorkItemsAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLIntelNumSimdWorkItemsAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLIntelESimdVectorizeAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLIntelESimdVectorizeAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLIntelSchedulerTargetFmaxMhzAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLIntelSchedulerTargetFmaxMhzAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLIntelNoGlobalWorkOffsetAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLIntelNoGlobalWorkOffsetAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLIntelMaxReplicatesAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLIntelMaxReplicatesAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLIntelMaxConcurrencyAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLIntelMaxConcurrencyAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLIntelForcePow2DepthAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLIntelForcePow2DepthAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLIntelInitiationIntervalAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLIntelInitiationIntervalAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLWorkGroupSizeHintAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLWorkGroupSizeHintAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLIntelMinWorkGroupsPerComputeUnitAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLIntelMinWorkGroupsPerComputeUnitAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLIntelMaxWorkGroupsPerMultiprocessorAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLIntelMaxWorkGroupsPerMultiprocessorAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLIntelMaxGlobalWorkDimAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLIntelMaxGlobalWorkDimAttr(D, *A); else if (const auto *BTFA = dyn_cast(Attr)) NewAttr = S.mergeBTFDeclTagAttr(D, *BTFA); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLIntelBankWidthAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLIntelBankWidthAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLIntelNumBanksAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLIntelNumBanksAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLDeviceHasAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLDeviceHasAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLUsesAspectsAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLUsesAspectsAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLTypeAttr(D, *A, A->getType()); + NewAttr = S.SYCL().mergeSYCLTypeAttr(D, *A, A->getType()); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLIntelPipeIOAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLIntelPipeIOAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLIntelMaxWorkGroupSizeAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLIntelMaxWorkGroupSizeAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLAddIRAttributesFunctionAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLAddIRAttributesFunctionAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLAddIRAttributesKernelParameterAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLAddIRAttributesKernelParameterAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLAddIRAttributesGlobalVariableAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLAddIRAttributesGlobalVariableAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLAddIRAnnotationsMemberAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLAddIRAnnotationsMemberAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLReqdWorkGroupSizeAttr(D, *A); + NewAttr = S.SYCL().mergeSYCLReqdWorkGroupSizeAttr(D, *A); else if (const auto *NT = dyn_cast(Attr)) NewAttr = S.HLSL().mergeNumThreadsAttr(D, *NT, NT->getX(), NT->getY(), NT->getZ()); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index adcd35f064e56..8e120b8c43510 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -2841,538 +2841,6 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { WorkGroupAttr(S.Context, AL, WGSize[0], WGSize[1], WGSize[2])); } -SYCLWorkGroupSizeHintAttr * -Sema::MergeSYCLWorkGroupSizeHintAttr(Decl *D, - const SYCLWorkGroupSizeHintAttr &A) { - // Check to see if there's a duplicate attribute already applied. - if (const auto *DeclAttr = D->getAttr()) { - // If any of the results are known to be different, we can diagnose at this - // point and drop the attribute. - if (SYCL().anyWorkGroupSizesDiffer(DeclAttr->getXDim(), DeclAttr->getYDim(), - DeclAttr->getZDim(), A.getXDim(), - A.getYDim(), A.getZDim())) { - Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; - Diag(A.getLoc(), diag::note_previous_attribute); - return nullptr; - } - // If all of the results are known to be the same, we can silently drop the - // attribute. Otherwise, we have to add the attribute and resolve its - // differences later. - if (SYCL().allWorkGroupSizesSame(DeclAttr->getXDim(), DeclAttr->getYDim(), - DeclAttr->getZDim(), A.getXDim(), - A.getYDim(), A.getZDim())) - return nullptr; - } - return ::new (Context) SYCLWorkGroupSizeHintAttr(Context, A, A.getXDim(), - A.getYDim(), A.getZDim()); -} - -// Handles SYCL work_group_size_hint. -static void handleSYCLWorkGroupSizeHint(Sema &S, Decl *D, - const ParsedAttr &AL) { - S.SYCL().checkDeprecatedSYCLAttributeSpelling(AL); - - // __attribute__((work_group_size_hint) requires exactly three arguments. - if (AL.getSyntax() == ParsedAttr::AS_GNU || !AL.hasScope() || - (AL.hasScope() && !AL.getScopeName()->isStr("sycl"))) { - if (!AL.checkExactlyNumArgs(S, 3)) - return; - } else if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 3)) - return; - - size_t NumArgs = AL.getNumArgs(); - Expr *XDimExpr = NumArgs > 0 ? AL.getArgAsExpr(0) : nullptr; - Expr *YDimExpr = NumArgs > 1 ? AL.getArgAsExpr(1) : nullptr; - Expr *ZDimExpr = NumArgs > 2 ? AL.getArgAsExpr(2) : nullptr; - S.SYCL().addSYCLWorkGroupSizeHintAttr(D, AL, XDimExpr, YDimExpr, ZDimExpr); -} - -static void handleWorkGroupSizeHint(Sema &S, Decl *D, const ParsedAttr &AL) { - // Handle the attribute based on whether we are targeting SYCL or not. - if (S.getLangOpts().SYCLIsDevice || S.getLangOpts().SYCLIsHost) - handleSYCLWorkGroupSizeHint(S, D, AL); - else - handleWorkGroupSize(S, D, AL); -} - -SYCLIntelMaxWorkGroupSizeAttr *Sema::MergeSYCLIntelMaxWorkGroupSizeAttr( - Decl *D, const SYCLIntelMaxWorkGroupSizeAttr &A) { - // Check to see if there's a duplicate attribute already applied. - if (const auto *DeclAttr = D->getAttr()) { - // If any of the results are known to be different, we can diagnose at this - // point and drop the attribute. - if (SYCL().anyWorkGroupSizesDiffer(DeclAttr->getXDim(), DeclAttr->getYDim(), - DeclAttr->getZDim(), A.getXDim(), - A.getYDim(), A.getZDim())) { - Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; - Diag(A.getLoc(), diag::note_previous_attribute); - return nullptr; - } - // If all of the results are known to be the same, we can silently drop the - // attribute. Otherwise, we have to add the attribute and resolve its - // differences later. - if (SYCL().allWorkGroupSizesSame(DeclAttr->getXDim(), DeclAttr->getYDim(), - DeclAttr->getZDim(), A.getXDim(), - A.getYDim(), A.getZDim())) - return nullptr; - } - - // If the 'max_work_group_size' attribute is specified on a declaration along - // with 'reqd_work_group_size' attribute, check to see if values of - // 'reqd_work_group_size' attribute arguments are equal to or less than values - // of 'max_work_group_size' attribute arguments. - // - // We emit diagnostic if values of 'reqd_work_group_size' attribute arguments - // are greater than values of 'max_work_group_size' attribute arguments. - if (const auto *DeclAttr = D->getAttr()) { - if (SYCL().checkMaxAllowedWorkGroupSize( - DeclAttr->getXDim(), DeclAttr->getYDim(), DeclAttr->getZDim(), - A.getXDim(), A.getYDim(), A.getZDim())) { - Diag(DeclAttr->getLoc(), diag::err_conflicting_sycl_function_attributes) - << DeclAttr << &A; - Diag(A.getLoc(), diag::note_conflicting_attribute); - return nullptr; - } - } - - // If the declaration has a SYCLIntelMaxWorkGroupSizeAttr, check to see if - // the attribute holds values equal to (1, 1, 1) in case the value of - // SYCLIntelMaxGlobalWorkDimAttr equals to 0. - if (const auto *DeclAttr = D->getAttr()) { - if (SYCL().areInvalidWorkGroupSizeAttrs(DeclAttr->getValue(), A.getXDim(), - A.getYDim(), A.getZDim())) { - Diag(A.getLoc(), diag::err_sycl_x_y_z_arguments_must_be_one) - << &A << DeclAttr; - return nullptr; - } - } - - return ::new (Context) SYCLIntelMaxWorkGroupSizeAttr( - Context, A, A.getXDim(), A.getYDim(), A.getZDim()); -} - -// Handles max_work_group_size attribute. -static void handleSYCLIntelMaxWorkGroupSize(Sema &S, Decl *D, - const ParsedAttr &AL) { - S.SYCL().addSYCLIntelMaxWorkGroupSizeAttr( - D, AL, AL.getArgAsExpr(0), AL.getArgAsExpr(1), AL.getArgAsExpr(2)); -} - -// Handles min_work_groups_per_cu attribute. -static void handleSYCLIntelMinWorkGroupsPerComputeUnit(Sema &S, Decl *D, - const ParsedAttr &AL) { - S.SYCL().addSYCLIntelMinWorkGroupsPerComputeUnitAttr(D, AL, - AL.getArgAsExpr(0)); -} - -// Handles max_work_groups_per_mp attribute. -static void -handleSYCLIntelMaxWorkGroupsPerMultiprocessor(Sema &S, Decl *D, - const ParsedAttr &AL) { - S.SYCL().addSYCLIntelMaxWorkGroupsPerMultiprocessorAttr(D, AL, - AL.getArgAsExpr(0)); -} - -SYCLReqdWorkGroupSizeAttr * -Sema::MergeSYCLReqdWorkGroupSizeAttr(Decl *D, - const SYCLReqdWorkGroupSizeAttr &A) { - // If the declaration has a SYCLReqdWorkGroupSizeAttr, check to see if the - // attribute holds values equal to (1, 1, 1) in case the value of - // SYCLIntelMaxGlobalWorkDimAttr equals to 0. - if (const auto *DeclAttr = D->getAttr()) { - if (SYCL().areInvalidWorkGroupSizeAttrs(DeclAttr->getValue(), A.getXDim(), - A.getYDim(), A.getZDim())) { - Diag(A.getLoc(), diag::err_sycl_x_y_z_arguments_must_be_one) - << &A << DeclAttr; - return nullptr; - } - } - - // If the 'max_work_group_size' attribute is specified on a declaration along - // with 'reqd_work_group_size' attribute, check to see if values of - // 'reqd_work_group_size' attribute arguments are equal or less than values - // of 'max_work_group_size' attribute arguments. - // - // We emit diagnostic if values of 'reqd_work_group_size' attribute arguments - // are greater than values of 'max_work_group_size' attribute arguments. - if (const auto *DeclAttr = D->getAttr()) { - if (SYCL().checkMaxAllowedWorkGroupSize( - A.getXDim(), A.getYDim(), A.getZDim(), DeclAttr->getXDim(), - DeclAttr->getYDim(), DeclAttr->getZDim())) { - Diag(DeclAttr->getLoc(), diag::err_conflicting_sycl_function_attributes) - << DeclAttr << &A; - Diag(A.getLoc(), diag::note_conflicting_attribute); - return nullptr; - } - } - - // If the 'reqd_work_group_size' attribute is specified on a declaration - // along with 'num_simd_work_items' attribute, the required work group size - // specified by 'num_simd_work_items' attribute must evenly divide the index - // that increments fastest in the 'reqd_work_group_size' attribute. - if (const auto *DeclAttr = D->getAttr()) { - if (SYCL().checkWorkGroupSize(DeclAttr->getValue(), A.getXDim(), - A.getYDim(), A.getZDim())) { - Diag(DeclAttr->getLoc(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) - << DeclAttr << &A; - Diag(A.getLoc(), diag::note_conflicting_attribute); - return nullptr; - } - } - - // Check to see if there's a duplicate attribute already applied. - if (const auto *DeclAttr = D->getAttr()) { - // If any of the results are known to be different, we can diagnose at this - // point and drop the attribute. - if (SYCL().anyWorkGroupSizesDiffer(DeclAttr->getXDim(), DeclAttr->getYDim(), - DeclAttr->getZDim(), A.getXDim(), - A.getYDim(), A.getZDim())) { - Diag(DeclAttr->getLoc(), diag::err_duplicate_attribute) << &A; - Diag(A.getLoc(), diag::note_previous_attribute); - return nullptr; - } - - // If all of the results are known to be the same, we can silently drop the - // attribute. Otherwise, we have to add the attribute and resolve its - // differences later. - if (SYCL().allWorkGroupSizesSame(DeclAttr->getXDim(), DeclAttr->getYDim(), - DeclAttr->getZDim(), A.getXDim(), - A.getYDim(), A.getZDim())) - return nullptr; - } - - return ::new (Context) SYCLReqdWorkGroupSizeAttr(Context, A, A.getXDim(), - A.getYDim(), A.getZDim()); -} - -static void handleSYCLReqdWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL){ - S.SYCL().checkDeprecatedSYCLAttributeSpelling(AL); - - // __attribute__((reqd_work_group_size)) and [[cl::reqd_work_group_size]] - // all require exactly three arguments. - if ((AL.getKind() == ParsedAttr::AT_ReqdWorkGroupSize && - AL.getAttributeSpellingListIndex() == - SYCLReqdWorkGroupSizeAttr::CXX11_cl_reqd_work_group_size) || - AL.getSyntax() == ParsedAttr::AS_GNU) { - if (!AL.checkExactlyNumArgs(S, 3)) - return; - } else if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 3)) - return; - - size_t NumArgs = AL.getNumArgs(); - Expr *XDimExpr = NumArgs > 0 ? AL.getArgAsExpr(0) : nullptr; - Expr *YDimExpr = NumArgs > 1 ? AL.getArgAsExpr(1) : nullptr; - Expr *ZDimExpr = NumArgs > 2 ? AL.getArgAsExpr(2) : nullptr; - S.SYCL().addSYCLReqdWorkGroupSizeAttr(D, AL, XDimExpr, YDimExpr, ZDimExpr); -} - -static void handleReqdWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { - // Handle the attribute based on whether we are targeting SYCL or not. - if (S.getLangOpts().SYCLIsDevice || S.getLangOpts().SYCLIsHost) - handleSYCLReqdWorkGroupSize(S, D, AL); - else - handleWorkGroupSize(S, D, AL); -} - -IntelReqdSubGroupSizeAttr * -Sema::MergeIntelReqdSubGroupSizeAttr(Decl *D, - const IntelReqdSubGroupSizeAttr &A) { - // Check to see if there's a duplicate attribute with different values - // already applied to the declaration. - if (const auto *DeclAttr = D->getAttr()) { - if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { - if (const auto *MergeExpr = dyn_cast(A.getValue())) { - if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { - Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; - Diag(A.getLoc(), diag::note_previous_attribute); - return nullptr; - } - // Do not add a duplicate attribute. - return nullptr; - } - } - } - return ::new (Context) IntelReqdSubGroupSizeAttr(Context, A, A.getValue()); -} - -static void handleIntelReqdSubGroupSize(Sema &S, Decl *D, - const ParsedAttr &AL) { - S.SYCL().checkDeprecatedSYCLAttributeSpelling(AL); - - Expr *E = AL.getArgAsExpr(0); - S.SYCL().addIntelReqdSubGroupSizeAttr(D, AL, E); -} - -IntelNamedSubGroupSizeAttr * -Sema::MergeIntelNamedSubGroupSizeAttr(Decl *D, - const IntelNamedSubGroupSizeAttr &A) { - // Check to see if there's a duplicate attribute with different values - // already applied to the declaration. - if (const auto *DeclAttr = D->getAttr()) { - if (DeclAttr->getType() != A.getType()) { - Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; - Diag(A.getLoc(), diag::note_previous_attribute); - } - return nullptr; - } - - return IntelNamedSubGroupSizeAttr::Create(Context, A.getType(), A); -} - -static void handleIntelNamedSubGroupSize(Sema &S, Decl *D, - const ParsedAttr &AL) { - StringRef SizeStr; - SourceLocation Loc; - if (AL.isArgIdent(0)) { - IdentifierLoc *IL = AL.getArgAsIdent(0); - SizeStr = IL->Ident->getName(); - Loc = IL->Loc; - } else if (!S.checkStringLiteralArgumentAttr(AL, 0, SizeStr, &Loc)) { - return; - } - - IntelNamedSubGroupSizeAttr::SubGroupSizeType SizeType; - if (!IntelNamedSubGroupSizeAttr::ConvertStrToSubGroupSizeType(SizeStr, - SizeType)) { - S.Diag(Loc, diag::warn_attribute_type_not_supported) << AL << SizeStr; - return; - } - D->addAttr(IntelNamedSubGroupSizeAttr::Create(S.Context, SizeType, AL)); -} - -SYCLIntelNumSimdWorkItemsAttr *Sema::MergeSYCLIntelNumSimdWorkItemsAttr( - Decl *D, const SYCLIntelNumSimdWorkItemsAttr &A) { - // Check to see if there's a duplicate attribute with different values - // already applied to the declaration. - if (const auto *DeclAttr = D->getAttr()) { - if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { - if (const auto *MergeExpr = dyn_cast(A.getValue())) { - if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { - Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; - Diag(A.getLoc(), diag::note_previous_attribute); - } - // Do not add a duplicate attribute. - return nullptr; - } - } - } - - // If the 'reqd_work_group_size' attribute is specified on a declaration - // along with 'num_simd_work_items' attribute, the required work group size - // specified by 'num_simd_work_items' attribute must evenly divide the index - // that increments fastest in the 'reqd_work_group_size' attribute. - if (const auto *DeclAttr = D->getAttr()) { - if (SYCL().checkWorkGroupSize(A.getValue(), DeclAttr->getXDim(), - DeclAttr->getYDim(), DeclAttr->getZDim())) { - Diag(A.getLoc(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) - << &A << DeclAttr; - Diag(DeclAttr->getLoc(), diag::note_conflicting_attribute); - return nullptr; - } - } - - return ::new (Context) - SYCLIntelNumSimdWorkItemsAttr(Context, A, A.getValue()); -} - -static void handleSYCLIntelNumSimdWorkItemsAttr(Sema &S, Decl *D, - const ParsedAttr &A) { - Expr *E = A.getArgAsExpr(0); - S.SYCL().addSYCLIntelNumSimdWorkItemsAttr(D, A, E); -} - -// Handles use_stall_enable_clusters -static void handleSYCLIntelUseStallEnableClustersAttr(Sema &S, Decl *D, - const ParsedAttr &A) { - D->addAttr(::new (S.Context) - SYCLIntelUseStallEnableClustersAttr(S.Context, A)); -} - -SYCLIntelInitiationIntervalAttr * -Sema::MergeSYCLIntelInitiationIntervalAttr( - Decl *D, const SYCLIntelInitiationIntervalAttr &A) { - // Check to see if there's a duplicate attribute with different values - // already applied to the declaration. - if (const auto *DeclAttr = - D->getAttr()) { - if (const auto *DeclExpr = dyn_cast(DeclAttr->getNExpr())) { - if (const auto *MergeExpr = dyn_cast(A.getNExpr())) { - if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { - Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; - Diag(A.getLoc(), diag::note_previous_attribute); - } - // Do not add a duplicate attribute. - return nullptr; - } - } - } - - return ::new (Context) - SYCLIntelInitiationIntervalAttr(Context, A, A.getNExpr()); -} - -static void handleSYCLIntelInitiationIntervalAttr(Sema &S, Decl *D, - const ParsedAttr &A) { - S.SYCL().checkDeprecatedSYCLAttributeSpelling(A); - - S.SYCL().addSYCLIntelInitiationIntervalAttr(D, A, A.getArgAsExpr(0)); -} - -SYCLIntelSchedulerTargetFmaxMhzAttr * -Sema::MergeSYCLIntelSchedulerTargetFmaxMhzAttr( - Decl *D, const SYCLIntelSchedulerTargetFmaxMhzAttr &A) { - // Check to see if there's a duplicate attribute with different values - // already applied to the declaration. - if (const auto *DeclAttr = - D->getAttr()) { - if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { - if (const auto *MergeExpr = dyn_cast(A.getValue())) { - if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { - Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; - Diag(A.getLoc(), diag::note_previous_attribute); - return nullptr; - } - // Do not add a duplicate attribute. - return nullptr; - } - } - } - return ::new (Context) - SYCLIntelSchedulerTargetFmaxMhzAttr(Context, A, A.getValue()); -} - -static void handleSYCLIntelSchedulerTargetFmaxMhzAttr(Sema &S, Decl *D, - const ParsedAttr &AL) { - Expr *E = AL.getArgAsExpr(0); - S.SYCL().addSYCLIntelSchedulerTargetFmaxMhzAttr(D, AL, E); -} - -SYCLIntelMaxGlobalWorkDimAttr *Sema::MergeSYCLIntelMaxGlobalWorkDimAttr( - Decl *D, const SYCLIntelMaxGlobalWorkDimAttr &A) { - // Check to see if there's a duplicate attribute with different values - // already applied to the declaration. - if (const auto *DeclAttr = D->getAttr()) { - if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { - if (const auto *MergeExpr = dyn_cast(A.getValue())) { - if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { - Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; - Diag(A.getLoc(), diag::note_previous_attribute); - } - // Do not add a duplicate attribute. - return nullptr; - } - } - } - - // If the declaration has a SYCLIntelMaxWorkGroupSizeAttr or - // SYCLReqdWorkGroupSizeAttr, check to see if the attribute holds values equal - // to (1, 1, 1) in case the value of SYCLIntelMaxGlobalWorkDimAttr equals to - // 0. - const auto *MergeExpr = dyn_cast(A.getValue()); - if (MergeExpr && MergeExpr->getResultAsAPSInt() == 0) { - if (SYCL().checkWorkGroupSizeAttrExpr(D, - A) || - SYCL().checkWorkGroupSizeAttrExpr(D, A)) - return nullptr; - } - - return ::new (Context) - SYCLIntelMaxGlobalWorkDimAttr(Context, A, A.getValue()); -} - -static void handleSYCLIntelMaxGlobalWorkDimAttr(Sema &S, Decl *D, - const ParsedAttr &AL) { - Expr *E = AL.getArgAsExpr(0); - S.SYCL().addSYCLIntelMaxGlobalWorkDimAttr(D, AL, E); -} - -SYCLIntelMinWorkGroupsPerComputeUnitAttr * -Sema::MergeSYCLIntelMinWorkGroupsPerComputeUnitAttr( - Decl *D, const SYCLIntelMinWorkGroupsPerComputeUnitAttr &A) { - // Check to see if there's a duplicate attribute with different values - // already applied to the declaration. - if (const auto *DeclAttr = - D->getAttr()) { - if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { - if (const auto *MergeExpr = dyn_cast(A.getValue())) { - if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { - Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; - Diag(A.getLoc(), diag::note_previous_attribute); - } - // Do not add a duplicate attribute. - return nullptr; - } - } - } - - return ::new (Context) - SYCLIntelMinWorkGroupsPerComputeUnitAttr(Context, A, A.getValue()); -} - -SYCLIntelMaxWorkGroupsPerMultiprocessorAttr * -Sema::MergeSYCLIntelMaxWorkGroupsPerMultiprocessorAttr( - Decl *D, const SYCLIntelMaxWorkGroupsPerMultiprocessorAttr &A) { - // Check to see if there's a duplicate attribute with different values - // already applied to the declaration. - if (const auto *DeclAttr = - D->getAttr()) { - if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { - if (const auto *MergeExpr = dyn_cast(A.getValue())) { - if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { - Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; - Diag(A.getLoc(), diag::note_previous_attribute); - } - // Do not add a duplicate attribute. - return nullptr; - } - } - } - - return ::new (Context) - SYCLIntelMaxWorkGroupsPerMultiprocessorAttr(Context, A, A.getValue()); -} - -SYCLIntelLoopFuseAttr * -Sema::MergeSYCLIntelLoopFuseAttr(Decl *D, const SYCLIntelLoopFuseAttr &A) { - // Check to see if there's a duplicate attribute with different values - // already applied to the declaration. - if (const auto *DeclAttr = D->getAttr()) { - // [[intel::loop_fuse]] and [[intel::loop_fuse_independent]] are - // incompatible. - // FIXME: If additional spellings are provided for this attribute, - // this code will do the wrong thing. - if (DeclAttr->getAttributeSpellingListIndex() != - A.getAttributeSpellingListIndex()) { - Diag(A.getLoc(), diag::err_attributes_are_not_compatible) - << &A << DeclAttr << A.isRegularKeywordAttribute(); - Diag(DeclAttr->getLoc(), diag::note_conflicting_attribute); - return nullptr; - } - if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { - if (const auto *MergeExpr = dyn_cast(A.getValue())) { - if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { - Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; - Diag(A.getLoc(), diag::note_previous_attribute); - } - // Do not add a duplicate attribute. - return nullptr; - } - } - } - - return ::new (Context) SYCLIntelLoopFuseAttr(Context, A, A.getValue()); -} - -static void handleSYCLIntelLoopFuseAttr(Sema &S, Decl *D, const ParsedAttr &A) { - // If no attribute argument is specified, set to default value '1'. - Expr *E = A.isArgExpr(0) - ? A.getArgAsExpr(0) - : IntegerLiteral::Create(S.Context, llvm::APInt(32, 1), - S.Context.IntTy, A.getLoc()); - - S.SYCL().addSYCLIntelLoopFuseAttr(D, A, E); -} - static void handleVecTypeHint(Sema &S, Decl *D, const ParsedAttr &AL) { // Given attribute is deprecated without replacement in SYCL 2020 mode. // Ignore the attribute in SYCL 2020. @@ -5147,89 +4615,6 @@ static void handleOptimizeNoneAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(Optnone); } -static void handleSYCLDeviceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - auto *ND = cast(D); - if (!ND->isExternallyVisible()) { - S.Diag(AL.getLoc(), diag::err_sycl_attribute_internal_decl) - << AL << !isa(ND); - return; - } - - if (auto *VD = dyn_cast(D)) { - QualType VarType = VD->getType(); - // Diagnose only for non-dependent types since dependent type don't have - // attributes applied on them ATM. - if (!VarType->isDependentType() && - !S.SYCL().isTypeDecoratedWithDeclAttribute( - VD->getType())) { - S.Diag(AL.getLoc(), diag::err_sycl_attribute_not_device_global) << AL; - return; - } - } - - handleSimpleAttribute(S, D, AL); -} - -static void handleSYCLDeviceIndirectlyCallableAttr(Sema &S, Decl *D, - const ParsedAttr &AL) { - auto *FD = cast(D); - if (!FD->isExternallyVisible()) { - S.Diag(AL.getLoc(), diag::err_sycl_attribute_internal_decl) - << AL << /*function*/ 0; - return; - } - - D->addAttr(SYCLDeviceAttr::CreateImplicit(S.Context)); - handleSimpleAttribute(S, D, AL); -} - -static void handleSYCLGlobalVarAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (!S.Context.getSourceManager().isInSystemHeader(D->getLocation())) { - S.Diag(AL.getLoc(), diag::err_attribute_only_system_header) << AL; - return; - } - - handleSimpleAttribute(S, D, AL); -} - -static void handleSYCLRegisterNumAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (!AL.checkExactlyNumArgs(S, 1)) - return; - uint32_t RegNo = 0; - const Expr *E = AL.getArgAsExpr(0); - if (!S.checkUInt32Argument(AL, E, RegNo, 0, /*StrictlyUnsigned=*/true)) - return; - D->addAttr(::new (S.Context) SYCLRegisterNumAttr(S.Context, AL, RegNo)); -} - -SYCLIntelESimdVectorizeAttr * -Sema::MergeSYCLIntelESimdVectorizeAttr(Decl *D, - const SYCLIntelESimdVectorizeAttr &A) { - // Check to see if there's a duplicate attribute with different values - // already applied to the declaration. - if (const auto *DeclAttr = D->getAttr()) { - if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { - if (const auto *MergeExpr = dyn_cast(A.getValue())) { - if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { - Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; - Diag(A.getLoc(), diag::note_previous_attribute); - } - // Do not add a duplicate attribute. - return nullptr; - } - } - } - return ::new (Context) SYCLIntelESimdVectorizeAttr(Context, A, A.getValue()); -} - -static void handleSYCLIntelESimdVectorizeAttr(Sema &S, Decl *D, - const ParsedAttr &A) { - S.SYCL().checkDeprecatedSYCLAttributeSpelling(A); - - Expr *E = A.getArgAsExpr(0); - S.SYCL().addSYCLIntelESimdVectorizeAttr(D, A, E); -} - static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) { const auto *VD = cast(D); if (VD->hasLocalStorage()) { @@ -5900,395 +5285,6 @@ static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D, AL.getMustBeNull())); } -/// Give a warning for duplicate attributes, return true if duplicate. -template -static bool checkForDuplicateAttribute(Sema &S, Decl *D, - const ParsedAttr &Attr) { - // Give a warning for duplicates but not if it's one we've implicitly added. - auto *A = D->getAttr(); - if (A && !A->isImplicit()) { - S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute_exact) << A; - return true; - } - return false; -} - -SYCLIntelNoGlobalWorkOffsetAttr *Sema::MergeSYCLIntelNoGlobalWorkOffsetAttr( - Decl *D, const SYCLIntelNoGlobalWorkOffsetAttr &A) { - // Check to see if there's a duplicate attribute with different values - // already applied to the declaration. - if (const auto *DeclAttr = D->getAttr()) { - if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { - if (const auto *MergeExpr = dyn_cast(A.getValue())) { - if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { - Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; - Diag(A.getLoc(), diag::note_previous_attribute); - } - // Do not add a duplicate attribute. - return nullptr; - } - } - } - return ::new (Context) - SYCLIntelNoGlobalWorkOffsetAttr(Context, A, A.getValue()); -} - -static void handleSYCLIntelNoGlobalWorkOffsetAttr(Sema &S, Decl *D, - const ParsedAttr &A) { - // If no attribute argument is specified, set to default value '1'. - Expr *E = A.isArgExpr(0) - ? A.getArgAsExpr(0) - : IntegerLiteral::Create(S.Context, llvm::APInt(32, 1), - S.Context.IntTy, A.getLoc()); - - S.SYCL().addSYCLIntelNoGlobalWorkOffsetAttr(D, A, E); -} - -/// Handle the [[intel::singlepump]] attribute. -static void handleSYCLIntelSinglePumpAttr(Sema &S, Decl *D, - const ParsedAttr &AL) { - // 'singlepump' Attribute does not take any argument. Give a warning for - // duplicate attributes but not if it's one we've implicitly added and drop - // any duplicates. - if (const auto *ExistingAttr = D->getAttr()) { - if (ExistingAttr && !ExistingAttr->isImplicit()) { - S.Diag(AL.getLoc(), diag::warn_duplicate_attribute_exact) << &AL; - S.Diag(ExistingAttr->getLoc(), diag::note_previous_attribute); - return; - } - } - - // Check attribute applies to field, constant variables, local variables, - // static variables, non-static data members, and device_global variables - // for the device compilation. - if ((D->getKind() == Decl::ParmVar) || - S.SYCL().checkValidFPGAMemoryAttributesVar(D)) { - S.Diag(AL.getLoc(), diag::err_fpga_attribute_incorrect_variable) - << AL << /*agent memory arguments*/ 0; - return; - } - - // If the declaration does not have an [[intel::fpga_memory]] - // attribute, this creates one as an implicit attribute. - if (!D->hasAttr()) - D->addAttr(SYCLIntelMemoryAttr::CreateImplicit( - S.Context, SYCLIntelMemoryAttr::Default)); - - D->addAttr(::new (S.Context) SYCLIntelSinglePumpAttr(S.Context, AL)); -} - -/// Handle the [[intel::doublepump]] attribute. -static void handleSYCLIntelDoublePumpAttr(Sema &S, Decl *D, - const ParsedAttr &AL) { - // 'doublepump' Attribute does not take any argument. Give a warning for - // duplicate attributes but not if it's one we've implicitly added and drop - // any duplicates. - if (const auto *ExistingAttr = D->getAttr()) { - if (ExistingAttr && !ExistingAttr->isImplicit()) { - S.Diag(AL.getLoc(), diag::warn_duplicate_attribute_exact) << &AL; - S.Diag(ExistingAttr->getLoc(), diag::note_previous_attribute); - return; - } - } - - // Check attribute applies to field, constant variables, local variables, - // static variables, non-static data members, and device_global variables - // for the device compilation. - if ((D->getKind() == Decl::ParmVar) || - S.SYCL().checkValidFPGAMemoryAttributesVar(D)) { - S.Diag(AL.getLoc(), diag::err_fpga_attribute_incorrect_variable) - << AL << /*agent memory arguments*/ 0; - return; - } - - // If the declaration does not have an [[intel::fpga_memory]] - // attribute, this creates one as an implicit attribute. - if (!D->hasAttr()) - D->addAttr(SYCLIntelMemoryAttr::CreateImplicit( - S.Context, SYCLIntelMemoryAttr::Default)); - - D->addAttr(::new (S.Context) SYCLIntelDoublePumpAttr(S.Context, AL)); -} - -/// Handle the [[intel::fpga_memory]] attribute. -/// This is incompatible with the [[intel::fpga_register]] attribute. -static void handleSYCLIntelMemoryAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - SYCLIntelMemoryAttr::MemoryKind Kind; - if (AL.getNumArgs() == 0) - Kind = SYCLIntelMemoryAttr::Default; - else { - StringRef Str; - if (!S.checkStringLiteralArgumentAttr(AL, 0, Str)) - return; - if (Str.empty() || - !SYCLIntelMemoryAttr::ConvertStrToMemoryKind(Str, Kind)) { - SmallString<256> ValidStrings; - SYCLIntelMemoryAttr::generateValidStrings(ValidStrings); - S.Diag(AL.getLoc(), diag::err_intel_fpga_memory_arg_invalid) - << AL << ValidStrings; - return; - } - } - - if (auto *MA = D->getAttr()) { - // Check to see if there's a duplicate memory attribute with different - // values already applied to the declaration. - if (!MA->isImplicit()) { - if (MA->getKind() != Kind) { - S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << &AL; - S.Diag(MA->getLocation(), diag::note_previous_attribute); - } - // Drop the duplicate attribute. - return; - } - // We are adding a user memory attribute, drop any implicit default. - D->dropAttr(); - } - - // Check attribute applies to field, constant variables, local variables, - // static variables, agent memory arguments, non-static data members, - // and device_global variables for the device compilation. - if (S.SYCL().checkValidFPGAMemoryAttributesVar(D)) { - S.Diag(AL.getLoc(), diag::err_fpga_attribute_incorrect_variable) - << AL << /*agent memory arguments*/ 1; - return; - } - - D->addAttr(::new (S.Context) SYCLIntelMemoryAttr(S.Context, AL, Kind)); -} - -/// Handle the [[intel::fpga_register]] attribute. -/// This is incompatible with most of the other memory attributes. -static void handleSYCLIntelRegisterAttr(Sema &S, Decl *D, - const ParsedAttr &A) { - - // 'fpga_register' Attribute does not take any argument. Give a warning for - // duplicate attributes but not if it's one we've implicitly added and drop - // any duplicates. - if (const auto *ExistingAttr = D->getAttr()) { - if (ExistingAttr && !ExistingAttr->isImplicit()) { - S.Diag(A.getLoc(), diag::warn_duplicate_attribute_exact) << &A; - S.Diag(ExistingAttr->getLoc(), diag::note_previous_attribute); - return; - } - } - - // Check attribute applies to field, constant variables, local variables, - // static variables, non-static data members, and device_global variables - // for the device compilation. - if ((D->getKind() == Decl::ParmVar) || - S.SYCL().checkValidFPGAMemoryAttributesVar(D)) { - S.Diag(A.getLoc(), diag::err_fpga_attribute_incorrect_variable) - << A << /*agent memory arguments*/ 0; - return; - } - - D->addAttr(::new (S.Context) SYCLIntelRegisterAttr(S.Context, A)); -} - -SYCLIntelBankWidthAttr * -Sema::MergeSYCLIntelBankWidthAttr(Decl *D, const SYCLIntelBankWidthAttr &A) { - // Check to see if there's a duplicate attribute with different values - // already applied to the declaration. - if (const auto *DeclAttr = D->getAttr()) { - const auto *DeclExpr = dyn_cast(DeclAttr->getValue()); - const auto *MergeExpr = dyn_cast(A.getValue()); - if (DeclExpr && MergeExpr && - DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { - Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; - Diag(A.getLoc(), diag::note_previous_attribute); - return nullptr; - } - } - - return ::new (Context) SYCLIntelBankWidthAttr(Context, A, A.getValue()); -} - -static void handleSYCLIntelBankWidthAttr(Sema &S, Decl *D, - const ParsedAttr &A) { - S.SYCL().addSYCLIntelBankWidthAttr(D, A, A.getArgAsExpr(0)); -} - -SYCLIntelNumBanksAttr * -Sema::MergeSYCLIntelNumBanksAttr(Decl *D, const SYCLIntelNumBanksAttr &A) { - // Check to see if there's a duplicate attribute with different values - // already applied to the declaration. - if (const auto *DeclAttr = D->getAttr()) { - const auto *DeclExpr = dyn_cast(DeclAttr->getValue()); - const auto *MergeExpr = dyn_cast(A.getValue()); - if (DeclExpr && MergeExpr && - DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { - Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; - Diag(A.getLoc(), diag::note_previous_attribute); - return nullptr; - } - } - - return ::new (Context) SYCLIntelNumBanksAttr(Context, A, A.getValue()); -} - -static void handleSYCLIntelNumBanksAttr(Sema &S, Decl *D, const ParsedAttr &A) { - S.SYCL().addSYCLIntelNumBanksAttr(D, A, A.getArgAsExpr(0)); -} - -static void handleIntelSimpleDualPortAttr(Sema &S, Decl *D, - const ParsedAttr &AL) { - // 'simple_dual_port' Attribute does not take any argument. Give a warning for - // duplicate attributes but not if it's one we've implicitly added and drop - // any duplicates. - if (const auto *ExistingAttr = D->getAttr()) { - if (ExistingAttr && !ExistingAttr->isImplicit()) { - S.Diag(AL.getLoc(), diag::warn_duplicate_attribute_exact) << &AL; - S.Diag(ExistingAttr->getLoc(), diag::note_previous_attribute); - return; - } - } - - // Check attribute applies to field, constant variables, local variables, - // static variables, agent memory arguments, non-static data members, - // and device_global variables for the device compilation. - if (S.SYCL().checkValidFPGAMemoryAttributesVar(D)) { - S.Diag(AL.getLoc(), diag::err_fpga_attribute_incorrect_variable) - << AL << /*agent memory arguments*/ 1; - return; - } - - if (!D->hasAttr()) - D->addAttr(SYCLIntelMemoryAttr::CreateImplicit( - S.Context, SYCLIntelMemoryAttr::Default)); - - D->addAttr(::new (S.Context) - SYCLIntelSimpleDualPortAttr(S.Context, AL)); -} - -SYCLIntelMaxReplicatesAttr * -Sema::MergeSYCLIntelMaxReplicatesAttr(Decl *D, - const SYCLIntelMaxReplicatesAttr &A) { - // Check to see if there's a duplicate attribute with different values - // already applied to the declaration. - if (const auto *DeclAttr = D->getAttr()) { - if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { - if (const auto *MergeExpr = dyn_cast(A.getValue())) { - if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { - Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; - Diag(A.getLoc(), diag::note_previous_attribute); - } - // Do not add a duplicate attribute. - return nullptr; - } - } - } - - return ::new (Context) SYCLIntelMaxReplicatesAttr(Context, A, A.getValue()); -} - -static void handleSYCLIntelMaxReplicatesAttr(Sema &S, Decl *D, - const ParsedAttr &A) { - S.SYCL().addSYCLIntelMaxReplicatesAttr(D, A, A.getArgAsExpr(0)); -} - -/// Handle the merge attribute. -/// This requires two string arguments. The first argument is a name, the -/// second is a direction. The direction must be "depth" or "width". -/// This is incompatible with the register attribute. -static void handleSYCLIntelMergeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - SmallVector Results; - for (int I = 0; I < 2; I++) { - StringRef Str; - if (!S.checkStringLiteralArgumentAttr(AL, I, Str)) - return; - - if (I == 1 && Str != "depth" && Str != "width") { - S.Diag(AL.getLoc(), diag::err_intel_fpga_merge_dir_invalid) << AL; - return; - } - Results.push_back(Str); - } - - // Warn about duplicate attributes if they have different arguments, no - // diagnostic is emitted if the arguments match, and drop any duplicate - // attributes. - if (const auto *Existing = D->getAttr()) { - if (Existing && !(Existing->getName() == Results[0] && - Existing->getDirection() == Results[1])) { - S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; - S.Diag(Existing->getLoc(), diag::note_previous_attribute); - } - // If there is no mismatch, drop any duplicate attributes. - return; - } - - // Check attribute applies to field, constant variables, local variables, - // static variables, non-static data members, and device_global variables - // for the device compilation. - if ((D->getKind() == Decl::ParmVar) || - S.SYCL().checkValidFPGAMemoryAttributesVar(D)) { - S.Diag(AL.getLoc(), diag::err_fpga_attribute_incorrect_variable) - << AL << /*agent memory arguments*/ 0; - return; - } - - if (!D->hasAttr()) - D->addAttr(SYCLIntelMemoryAttr::CreateImplicit( - S.Context, SYCLIntelMemoryAttr::Default)); - - D->addAttr(::new (S.Context) - SYCLIntelMergeAttr(S.Context, AL, Results[0], Results[1])); -} - -/// Handle the bank_bits attribute. -/// This attribute accepts a list of values greater than zero. -/// This is incompatible with the register attribute. -/// The numbanks and bank_bits attributes are related. If numbanks exists -/// when handling bank_bits they are checked for consistency. If numbanks -/// hasn't been added yet an implicit one is added with the correct value. -/// If the user later adds a numbanks attribute the implicit one is removed. -/// The values must be consecutive values (i.e. 3,4,5 or 2,1). -static void handleSYCLIntelBankBitsAttr(Sema &S, Decl *D, const ParsedAttr &A) { - checkForDuplicateAttribute(S, D, A); - - if (!A.checkAtLeastNumArgs(S, 1)) - return; - - SmallVector Args; - for (unsigned I = 0; I < A.getNumArgs(); ++I) { - Args.push_back(A.getArgAsExpr(I)); - } - - S.SYCL().addSYCLIntelBankBitsAttr(D, A, Args.data(), Args.size()); -} - -static void handleSYCLIntelPrivateCopiesAttr(Sema &S, Decl *D, - const ParsedAttr &A) { - S.SYCL().addSYCLIntelPrivateCopiesAttr(D, A, A.getArgAsExpr(0)); -} - -SYCLIntelForcePow2DepthAttr * -Sema::MergeSYCLIntelForcePow2DepthAttr(Decl *D, - const SYCLIntelForcePow2DepthAttr &A) { - // Check to see if there's a duplicate attribute with different values - // already applied to the declaration. - if (const auto *DeclAttr = D->getAttr()) { - if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { - if (const auto *MergeExpr = dyn_cast(A.getValue())) { - if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { - Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; - Diag(A.getLoc(), diag::note_previous_attribute); - } - // If there is no mismatch, drop any duplicate attributes. - return nullptr; - } - } - } - - return ::new (Context) SYCLIntelForcePow2DepthAttr(Context, A, A.getValue()); -} - -static void handleSYCLIntelForcePow2DepthAttr(Sema &S, Decl *D, - const ParsedAttr &A) { - S.SYCL().addSYCLIntelForcePow2DepthAttr(D, A, A.getArgAsExpr(0)); -} - static void handleXRayLogArgsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { ParamIdx ArgCount; @@ -6321,216 +5317,6 @@ static void handlePatchableFunctionEntryAttr(Sema &S, Decl *D, PatchableFunctionEntryAttr(S.Context, AL, Count, Offset)); } -SYCLIntelPipeIOAttr * -Sema::MergeSYCLIntelPipeIOAttr(Decl *D, const SYCLIntelPipeIOAttr &A) { - // Check to see if there's a duplicate attribute with different values - // already applied to the declaration. - if (const auto *DeclAttr = D->getAttr()) { - if (const auto *DeclExpr = dyn_cast(DeclAttr->getID())) { - if (const auto *MergeExpr = dyn_cast(A.getID())) { - if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { - Diag(DeclAttr->getLoc(), diag::err_disallowed_duplicate_attribute) - << &A; - Diag(A.getLoc(), diag::note_conflicting_attribute); - } - // Do not add a duplicate attribute. - return nullptr; - } - } - } - - return ::new (Context) SYCLIntelPipeIOAttr(Context, A, A.getID()); -} - -static void handleSYCLIntelPipeIOAttr(Sema &S, Decl *D, const ParsedAttr &A) { - Expr *E = A.getArgAsExpr(0); - S.SYCL().addSYCLIntelPipeIOAttr(D, A, E); -} - -SYCLIntelMaxConcurrencyAttr *Sema::MergeSYCLIntelMaxConcurrencyAttr( - Decl *D, const SYCLIntelMaxConcurrencyAttr &A) { - // Check to see if there's a duplicate attribute with different values - // already applied to the declaration. - if (const auto *DeclAttr = D->getAttr()) { - if (const auto *DeclExpr = dyn_cast(DeclAttr->getNExpr())) { - if (const auto *MergeExpr = dyn_cast(A.getNExpr())) { - if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { - Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; - Diag(A.getLoc(), diag::note_previous_attribute); - } - // Do not add a duplicate attribute. - return nullptr; - } - } - } - - return ::new (Context) SYCLIntelMaxConcurrencyAttr(Context, A, A.getNExpr()); -} - -static void handleSYCLIntelMaxConcurrencyAttr(Sema &S, Decl *D, - const ParsedAttr &A) { - Expr *E = A.getArgAsExpr(0); - S.SYCL().addSYCLIntelMaxConcurrencyAttr(D, A, E); -} - -static bool hasSameSYCLAddIRAttributes( - const SmallVector, 4> &LAttrs, - const SmallVector, 4> &RAttrs) { - std::set> LNameValSet{LAttrs.begin(), - LAttrs.end()}; - std::set> RNameValSet{RAttrs.begin(), - RAttrs.end()}; - return LNameValSet == RNameValSet; -} - -template -static bool checkSYCLAddIRAttributesMergeability(const AddIRAttrT &NewAttr, - const AddIRAttrT &ExistingAttr, - Sema &S) { - ASTContext &Context = S.getASTContext(); - // If there are no dependent argument expressions and the filters or the - // attributes are different, then fail due to differing duplicates. - if (!S.SYCL().hasDependentExpr(NewAttr.args_begin(), NewAttr.args_size()) && - !S.SYCL().hasDependentExpr(ExistingAttr.args_begin(), - ExistingAttr.args_size()) && - (NewAttr.getAttributeFilter() != ExistingAttr.getAttributeFilter() || - !hasSameSYCLAddIRAttributes( - NewAttr.getAttributeNameValuePairs(Context), - ExistingAttr.getAttributeNameValuePairs(Context)))) { - S.Diag(ExistingAttr.getLoc(), diag::err_duplicate_attribute) << &NewAttr; - S.Diag(NewAttr.getLoc(), diag::note_conflicting_attribute); - return true; - } - return false; -} - -void Sema::CheckSYCLAddIRAttributesFunctionAttrConflicts(Decl *D) { - const auto *AddIRFuncAttr = D->getAttr(); - - // If there is no such attribute there is nothing to check. If there are - // dependent arguments we cannot know the actual number of arguments so we - // defer the check. - if (!AddIRFuncAttr || SYCL().hasDependentExpr(AddIRFuncAttr->args_begin(), - AddIRFuncAttr->args_size())) - return; - - // If there are no name-value pairs in the attribute it will not have an - // effect and we can skip the check. The filter is ignored. - size_t NumArgsWithoutFilter = - AddIRFuncAttr->args_size() - (AddIRFuncAttr->hasFilterList() ? 1 : 0); - if (NumArgsWithoutFilter == 0) - return; - - // "sycl-single-task" is present on all single_task invocations, implicitly - // added by the SYCL headers. It can only conflict with max_global_work_dim, - // but the value will be the same so there is no need for a warning. - if (NumArgsWithoutFilter == 2) { - auto NameValuePairs = AddIRFuncAttr->getAttributeNameValuePairs(Context); - if (NameValuePairs.size() > 0 && - NameValuePairs[0].first == "sycl-single-task") - return; - } - - // If there are potentially conflicting attributes, we issue a warning. - for (const auto *Attr : std::vector{ - D->getAttr(), - D->getAttr(), - D->getAttr(), - D->getAttr()}) - if (Attr) - Diag(Attr->getLoc(), diag::warn_sycl_old_and_new_kernel_attributes) - << Attr; -} - -SYCLAddIRAttributesFunctionAttr *Sema::MergeSYCLAddIRAttributesFunctionAttr( - Decl *D, const SYCLAddIRAttributesFunctionAttr &A) { - if (const auto *ExistingAttr = - D->getAttr()) { - checkSYCLAddIRAttributesMergeability(A, *ExistingAttr, *this); - return nullptr; - } - return A.clone(Context); -} - -static void handleSYCLAddIRAttributesFunctionAttr(Sema &S, Decl *D, - const ParsedAttr &A) { - llvm::SmallVector Args; - Args.reserve(A.getNumArgs() - 1); - for (unsigned I = 0; I < A.getNumArgs(); I++) { - assert(A.isArgExpr(I)); - Args.push_back(A.getArgAsExpr(I)); - } - - S.SYCL().addSYCLAddIRAttributesFunctionAttr(D, A, Args); -} - -SYCLAddIRAttributesKernelParameterAttr * -Sema::MergeSYCLAddIRAttributesKernelParameterAttr( - Decl *D, const SYCLAddIRAttributesKernelParameterAttr &A) { - if (const auto *ExistingAttr = - D->getAttr()) { - checkSYCLAddIRAttributesMergeability(A, *ExistingAttr, *this); - return nullptr; - } - return A.clone(Context); -} - -static void handleSYCLAddIRAttributesKernelParameterAttr(Sema &S, Decl *D, - const ParsedAttr &A) { - llvm::SmallVector Args; - Args.reserve(A.getNumArgs() - 1); - for (unsigned I = 0; I < A.getNumArgs(); I++) { - assert(A.getArgAsExpr(I)); - Args.push_back(A.getArgAsExpr(I)); - } - - S.SYCL().addSYCLAddIRAttributesKernelParameterAttr(D, A, Args); -} - -SYCLAddIRAttributesGlobalVariableAttr * -Sema::MergeSYCLAddIRAttributesGlobalVariableAttr( - Decl *D, const SYCLAddIRAttributesGlobalVariableAttr &A) { - if (const auto *ExistingAttr = - D->getAttr()) { - checkSYCLAddIRAttributesMergeability(A, *ExistingAttr, *this); - return nullptr; - } - return A.clone(Context); -} - -static void handleSYCLAddIRAttributesGlobalVariableAttr(Sema &S, Decl *D, - const ParsedAttr &A) { - llvm::SmallVector Args; - Args.reserve(A.getNumArgs() - 1); - for (unsigned I = 0; I < A.getNumArgs(); I++) { - assert(A.getArgAsExpr(I)); - Args.push_back(A.getArgAsExpr(I)); - } - - S.SYCL().addSYCLAddIRAttributesGlobalVariableAttr(D, A, Args); -} - -SYCLAddIRAnnotationsMemberAttr *Sema::MergeSYCLAddIRAnnotationsMemberAttr( - Decl *D, const SYCLAddIRAnnotationsMemberAttr &A) { - if (const auto *ExistingAttr = D->getAttr()) { - checkSYCLAddIRAttributesMergeability(A, *ExistingAttr, *this); - return nullptr; - } - return A.clone(Context); -} - -static void handleSYCLAddIRAnnotationsMemberAttr(Sema &S, Decl *D, - const ParsedAttr &A) { - llvm::SmallVector Args; - Args.reserve(A.getNumArgs()); - for (unsigned I = 0; I < A.getNumArgs(); I++) { - assert(A.getArgAsExpr(I)); - Args.push_back(A.getArgAsExpr(I)); - } - - S.SYCL().addSYCLAddIRAnnotationsMemberAttr(D, A, Args); -} - static bool SYCLAliasValid(ASTContext &Context, unsigned BuiltinID) { constexpr llvm::StringLiteral Prefix = "__builtin_intel_sycl"; return Context.BuiltinInfo.getName(BuiltinID).starts_with(Prefix); @@ -7362,62 +6148,6 @@ static void handleFunctionReturnThunksAttr(Sema &S, Decl *D, D->addAttr(FunctionReturnThunksAttr::Create(S.Context, Kind, AL)); } -SYCLDeviceHasAttr *Sema::MergeSYCLDeviceHasAttr(Decl *D, - const SYCLDeviceHasAttr &A) { - if (const auto *ExistingAttr = D->getAttr()) { - Diag(ExistingAttr->getLoc(), diag::warn_duplicate_attribute_exact) << &A; - Diag(A.getLoc(), diag::note_previous_attribute); - return nullptr; - } - - SmallVector Args; - for (auto *E : A.aspects()) - Args.push_back(E); - return ::new (Context) - SYCLDeviceHasAttr(Context, A, Args.data(), Args.size()); -} - -static void handleSYCLDeviceHasAttr(Sema &S, Decl *D, const ParsedAttr &A) { - // Ignore the attribute if compiling for the host side because aspects may not - // be marked properly for such compilation - if (!S.Context.getLangOpts().SYCLIsDevice) - return; - - SmallVector Args; - for (unsigned I = 0; I < A.getNumArgs(); ++I) - Args.push_back(A.getArgAsExpr(I)); - - S.SYCL().addSYCLDeviceHasAttr(D, A, Args.data(), Args.size()); -} - -SYCLUsesAspectsAttr * -Sema::MergeSYCLUsesAspectsAttr(Decl *D, const SYCLUsesAspectsAttr &A) { - if (const auto *ExistingAttr = D->getAttr()) { - Diag(ExistingAttr->getLoc(), diag::warn_duplicate_attribute_exact) << &A; - Diag(A.getLoc(), diag::note_previous_attribute); - return nullptr; - } - - SmallVector Args; - for (auto *E : A.aspects()) - Args.push_back(E); - return ::new (Context) - SYCLUsesAspectsAttr(Context, A, Args.data(), Args.size()); -} - -static void handleSYCLUsesAspectsAttr(Sema &S, Decl *D, const ParsedAttr &A) { - // Ignore the attribute if compiling for the host because aspects may not be - // marked properly for such compilation - if (!S.Context.getLangOpts().SYCLIsDevice) - return; - - SmallVector Args; - for (unsigned I = 0; I < A.getNumArgs(); ++I) - Args.push_back(A.getArgAsExpr(I)); - - S.SYCL().addSYCLUsesAspectsAttr(D, A, Args.data(), Args.size()); -} - static void handleAvailableOnlyInDefaultEvalMethod(Sema &S, Decl *D, const ParsedAttr &AL) { assert(isa(D) && "This attribute only applies to a typedef"); @@ -7438,39 +6168,6 @@ static void handleNoUniqueAddressAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(NoUniqueAddressAttr::Create(S.Context, AL)); } -SYCLTypeAttr *Sema::MergeSYCLTypeAttr(Decl *D, const AttributeCommonInfo &CI, - SYCLTypeAttr::SYCLType TypeName) { - if (const auto *ExistingAttr = D->getAttr()) { - if (ExistingAttr->getType() != TypeName) { - Diag(ExistingAttr->getLoc(), diag::err_duplicate_attribute) - << ExistingAttr; - Diag(CI.getLoc(), diag::note_previous_attribute); - } - // Do not add duplicate attribute - return nullptr; - } - return ::new (Context) SYCLTypeAttr(Context, CI, TypeName); -} - -static void handleSYCLTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (!AL.isArgIdent(0)) { - S.Diag(AL.getLoc(), diag::err_attribute_argument_type) - << AL << AANT_ArgumentIdentifier; - return; - } - - IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; - SYCLTypeAttr::SYCLType Type; - - if (!SYCLTypeAttr::ConvertStrToSYCLType(II->getName(), Type)) { - S.Diag(AL.getLoc(), diag::err_attribute_argument_not_supported) << AL << II; - return; - } - - if (SYCLTypeAttr *NewAttr = S.MergeSYCLTypeAttr(D, AL, Type)) - D->addAttr(NewAttr); -} - 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) @@ -8071,28 +6768,28 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, handleSimpleAttribute(S, D, AL); break; case ParsedAttr::AT_SYCLType: - handleSYCLTypeAttr(S, D, AL); + S.SYCL().handleSYCLTypeAttr(D, AL); break; case ParsedAttr::AT_SYCLDevice: - handleSYCLDeviceAttr(S, D, AL); + S.SYCL().handleSYCLDeviceAttr(D, AL); break; case ParsedAttr::AT_SYCLDeviceIndirectlyCallable: - handleSYCLDeviceIndirectlyCallableAttr(S, D, AL); + S.SYCL().handleSYCLDeviceIndirectlyCallableAttr(D, AL); break; case ParsedAttr::AT_SYCLGlobalVar: - handleSYCLGlobalVarAttr(S, D, AL); + S.SYCL().handleSYCLGlobalVarAttr(D, AL); break; case ParsedAttr::AT_SYCLRegisterNum: - handleSYCLRegisterNumAttr(S, D, AL); + S.SYCL().handleSYCLRegisterNumAttr(D, AL); break; case ParsedAttr::AT_SYCLIntelESimdVectorize: - handleSYCLIntelESimdVectorizeAttr(S, D, AL); + S.SYCL().handleSYCLIntelESimdVectorizeAttr(D, AL); break; case ParsedAttr::AT_SYCLDeviceHas: - handleSYCLDeviceHasAttr(S, D, AL); + S.SYCL().handleSYCLDeviceHasAttr(D, AL); break; case ParsedAttr::AT_SYCLUsesAspects: - handleSYCLUsesAspectsAttr(S, D, AL); + S.SYCL().handleSYCLUsesAspectsAttr(D, AL); break; case ParsedAttr::AT_Format: handleFormatAttr(S, D, AL); @@ -8236,46 +6933,53 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, S.ObjC().handleXReturnsXRetainedAttr(D, AL); break; case ParsedAttr::AT_WorkGroupSizeHint: - handleWorkGroupSizeHint(S, D, AL); + // Handle the attribute based on whether we are targeting SYCL or not. + if (S.getLangOpts().SYCLIsDevice || S.getLangOpts().SYCLIsHost) + S.SYCL().handleSYCLWorkGroupSizeHintAttr(D, AL); + else + handleWorkGroupSize(S, D, AL); break; case ParsedAttr::AT_ReqdWorkGroupSize: - handleReqdWorkGroupSize(S, D, AL); + if (S.getLangOpts().SYCLIsDevice || S.getLangOpts().SYCLIsHost) + S.SYCL().handleSYCLReqdWorkGroupSizeAttr(D, AL); + else + handleWorkGroupSize(S, D, AL); break; case ParsedAttr::AT_SYCLIntelMaxWorkGroupSize: - handleSYCLIntelMaxWorkGroupSize(S, D, AL); + S.SYCL().handleSYCLIntelMaxWorkGroupSize(D, AL); break; case ParsedAttr::AT_SYCLIntelMinWorkGroupsPerComputeUnit: - handleSYCLIntelMinWorkGroupsPerComputeUnit(S, D, AL); + S.SYCL().handleSYCLIntelMinWorkGroupsPerComputeUnit(D, AL); break; case ParsedAttr::AT_SYCLIntelMaxWorkGroupsPerMultiprocessor: - handleSYCLIntelMaxWorkGroupsPerMultiprocessor(S, D, AL); + S.SYCL().handleSYCLIntelMaxWorkGroupsPerMultiprocessor(D, AL); break; case ParsedAttr::AT_IntelReqdSubGroupSize: - handleIntelReqdSubGroupSize(S, D, AL); + S.SYCL().handleIntelReqdSubGroupSizeAttr(D, AL); break; case ParsedAttr::AT_IntelNamedSubGroupSize: - handleIntelNamedSubGroupSize(S, D, AL); + S.SYCL().handleIntelNamedSubGroupSizeAttr(D, AL); break; case ParsedAttr::AT_SYCLIntelNumSimdWorkItems: - handleSYCLIntelNumSimdWorkItemsAttr(S, D, AL); + S.SYCL().handleSYCLIntelNumSimdWorkItemsAttr(D, AL); break; case ParsedAttr::AT_SYCLIntelSchedulerTargetFmaxMhz: - handleSYCLIntelSchedulerTargetFmaxMhzAttr(S, D, AL); + S.SYCL().handleSYCLIntelSchedulerTargetFmaxMhzAttr(D, AL); break; case ParsedAttr::AT_SYCLIntelMaxGlobalWorkDim: - handleSYCLIntelMaxGlobalWorkDimAttr(S, D, AL); + S.SYCL().handleSYCLIntelMaxGlobalWorkDimAttr(D, AL); break; case ParsedAttr::AT_SYCLIntelNoGlobalWorkOffset: - handleSYCLIntelNoGlobalWorkOffsetAttr(S, D, AL); + S.SYCL().handleSYCLIntelNoGlobalWorkOffsetAttr(D, AL); break; case ParsedAttr::AT_SYCLIntelUseStallEnableClusters: - handleSYCLIntelUseStallEnableClustersAttr(S, D, AL); + S.SYCL().handleSYCLIntelUseStallEnableClustersAttr(D, AL); break; case ParsedAttr::AT_SYCLIntelLoopFuse: - handleSYCLIntelLoopFuseAttr(S, D, AL); + S.SYCL().handleSYCLIntelLoopFuseAttr(D, AL); break; case ParsedAttr::AT_SYCLIntelInitiationInterval: - handleSYCLIntelInitiationIntervalAttr(S, D, AL); + S.SYCL().handleSYCLIntelInitiationIntervalAttr(D, AL); break; case ParsedAttr::AT_VecTypeHint: handleVecTypeHint(S, D, AL); @@ -8595,58 +7299,58 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, // Intel FPGA specific attributes case ParsedAttr::AT_SYCLIntelDoublePump: - handleSYCLIntelDoublePumpAttr(S, D, AL); + S.SYCL().handleSYCLIntelDoublePumpAttr(D, AL); break; case ParsedAttr::AT_SYCLIntelSinglePump: - handleSYCLIntelSinglePumpAttr(S, D, AL); + S.SYCL().handleSYCLIntelSinglePumpAttr(D, AL); break; case ParsedAttr::AT_SYCLIntelMemory: - handleSYCLIntelMemoryAttr(S, D, AL); + S.SYCL().handleSYCLIntelMemoryAttr(D, AL); break; case ParsedAttr::AT_SYCLIntelRegister: - handleSYCLIntelRegisterAttr(S, D, AL); + S.SYCL().handleSYCLIntelRegisterAttr(D, AL); break; case ParsedAttr::AT_SYCLIntelBankWidth: - handleSYCLIntelBankWidthAttr(S, D, AL); + S.SYCL().handleSYCLIntelBankWidthAttr(D, AL); break; case ParsedAttr::AT_SYCLIntelNumBanks: - handleSYCLIntelNumBanksAttr(S, D, AL); + S.SYCL().handleSYCLIntelNumBanksAttr(D, AL); break; case ParsedAttr::AT_SYCLIntelPrivateCopies: - handleSYCLIntelPrivateCopiesAttr(S, D, AL); + S.SYCL().handleSYCLIntelPrivateCopiesAttr(D, AL); break; case ParsedAttr::AT_SYCLIntelMaxReplicates: - handleSYCLIntelMaxReplicatesAttr(S, D, AL); + S.SYCL().handleSYCLIntelMaxReplicatesAttr(D, AL); break; case ParsedAttr::AT_SYCLIntelSimpleDualPort: - handleIntelSimpleDualPortAttr(S, D, AL); + S.SYCL().handleIntelSimpleDualPortAttr(D, AL); break; case ParsedAttr::AT_SYCLIntelMerge: - handleSYCLIntelMergeAttr(S, D, AL); + S.SYCL().handleSYCLIntelMergeAttr(D, AL); break; case ParsedAttr::AT_SYCLIntelBankBits: - handleSYCLIntelBankBitsAttr(S, D, AL); + S.SYCL().handleSYCLIntelBankBitsAttr(D, AL); break; case ParsedAttr::AT_SYCLIntelForcePow2Depth: - handleSYCLIntelForcePow2DepthAttr(S, D, AL); + S.SYCL().handleSYCLIntelForcePow2DepthAttr(D, AL); break; case ParsedAttr::AT_SYCLIntelPipeIO: - handleSYCLIntelPipeIOAttr(S, D, AL); + S.SYCL().handleSYCLIntelPipeIOAttr(D, AL); break; case ParsedAttr::AT_SYCLIntelMaxConcurrency: - handleSYCLIntelMaxConcurrencyAttr(S, D, AL); + S.SYCL().handleSYCLIntelMaxConcurrencyAttr(D, AL); break; case ParsedAttr::AT_SYCLAddIRAttributesFunction: - handleSYCLAddIRAttributesFunctionAttr(S, D, AL); + S.SYCL().handleSYCLAddIRAttributesFunctionAttr(D, AL); break; case ParsedAttr::AT_SYCLAddIRAttributesKernelParameter: - handleSYCLAddIRAttributesKernelParameterAttr(S, D, AL); + S.SYCL().handleSYCLAddIRAttributesKernelParameterAttr(D, AL); break; case ParsedAttr::AT_SYCLAddIRAttributesGlobalVariable: - handleSYCLAddIRAttributesGlobalVariableAttr(S, D, AL); + S.SYCL().handleSYCLAddIRAttributesGlobalVariableAttr(D, AL); break; case ParsedAttr::AT_SYCLAddIRAnnotationsMember: - handleSYCLAddIRAnnotationsMemberAttr(S, D, AL); + S.SYCL().handleSYCLAddIRAnnotationsMemberAttr(D, AL); break; // Swift attributes. diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index 223fd7a145bb9..bcd138ceb6657 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -5428,7 +5428,7 @@ void SemaSYCL::MarkDevices() { for (auto *A : T.GetCollectedAttributes()) PropagateAndDiagnoseDeviceAttr(*this, T, A, T.GetSYCLKernel(), T.GetKernelBody()); - SemaRef.CheckSYCLAddIRAttributesFunctionAttrConflicts(T.GetSYCLKernel()); + checkSYCLAddIRAttributesFunctionAttrConflicts(T.GetSYCLKernel()); } } diff --git a/clang/lib/Sema/SemaSYCLDeclAttr.cpp b/clang/lib/Sema/SemaSYCLDeclAttr.cpp index d8b616ea7b48d..0e23934b4597f 100644 --- a/clang/lib/Sema/SemaSYCLDeclAttr.cpp +++ b/clang/lib/Sema/SemaSYCLDeclAttr.cpp @@ -8,6 +8,7 @@ // This implements Semantic Analysis for SYCL attributes. //===----------------------------------------------------------------------===// +#include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/Attr.h" #include "clang/Sema/Initialization.h" @@ -1839,3 +1840,1303 @@ void SemaSYCL::addSYCLReqdWorkGroupSizeAttr(Decl *D, D->addAttr(::new (Context) SYCLReqdWorkGroupSizeAttr(Context, CI, XDim, YDim, ZDim)); } + +// Handles SYCL work_group_size_hint. +void SemaSYCL::handleSYCLWorkGroupSizeHintAttr(Decl *D, const ParsedAttr &AL) { + checkDeprecatedSYCLAttributeSpelling(AL); + + // __attribute__((work_group_size_hint) requires exactly three arguments. + if (AL.getSyntax() == ParsedAttr::AS_GNU || !AL.hasScope() || + (AL.hasScope() && !AL.getScopeName()->isStr("sycl"))) { + if (!AL.checkExactlyNumArgs(SemaRef, 3)) + return; + } else if (!AL.checkAtLeastNumArgs(SemaRef, 1) || + !AL.checkAtMostNumArgs(SemaRef, 3)) + return; + + size_t NumArgs = AL.getNumArgs(); + Expr *XDimExpr = NumArgs > 0 ? AL.getArgAsExpr(0) : nullptr; + Expr *YDimExpr = NumArgs > 1 ? AL.getArgAsExpr(1) : nullptr; + Expr *ZDimExpr = NumArgs > 2 ? AL.getArgAsExpr(2) : nullptr; + addSYCLWorkGroupSizeHintAttr(D, AL, XDimExpr, YDimExpr, ZDimExpr); +} + +SYCLWorkGroupSizeHintAttr * +SemaSYCL::mergeSYCLWorkGroupSizeHintAttr(Decl *D, + const SYCLWorkGroupSizeHintAttr &A) { + // Check to see if there's a duplicate attribute already applied. + if (const auto *DeclAttr = D->getAttr()) { + // If any of the results are known to be different, we can diagnose at this + // point and drop the attribute. + if (anyWorkGroupSizesDiffer(DeclAttr->getXDim(), DeclAttr->getYDim(), + DeclAttr->getZDim(), A.getXDim(), A.getYDim(), + A.getZDim())) { + Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + return nullptr; + } + // If all of the results are known to be the same, we can silently drop the + // attribute. Otherwise, we have to add the attribute and resolve its + // differences later. + if (allWorkGroupSizesSame(DeclAttr->getXDim(), DeclAttr->getYDim(), + DeclAttr->getZDim(), A.getXDim(), A.getYDim(), + A.getZDim())) + return nullptr; + } + ASTContext &Context = getASTContext(); + return ::new (Context) SYCLWorkGroupSizeHintAttr(Context, A, A.getXDim(), + A.getYDim(), A.getZDim()); +} + +SYCLIntelMaxWorkGroupSizeAttr *SemaSYCL::mergeSYCLIntelMaxWorkGroupSizeAttr( + Decl *D, const SYCLIntelMaxWorkGroupSizeAttr &A) { + // Check to see if there's a duplicate attribute already applied. + if (const auto *DeclAttr = D->getAttr()) { + // If any of the results are known to be different, we can diagnose at this + // point and drop the attribute. + if (anyWorkGroupSizesDiffer(DeclAttr->getXDim(), DeclAttr->getYDim(), + DeclAttr->getZDim(), A.getXDim(), A.getYDim(), + A.getZDim())) { + Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + return nullptr; + } + // If all of the results are known to be the same, we can silently drop the + // attribute. Otherwise, we have to add the attribute and resolve its + // differences later. + if (allWorkGroupSizesSame(DeclAttr->getXDim(), DeclAttr->getYDim(), + DeclAttr->getZDim(), A.getXDim(), A.getYDim(), + A.getZDim())) + return nullptr; + } + + // If the 'max_work_group_size' attribute is specified on a declaration along + // with 'reqd_work_group_size' attribute, check to see if values of + // 'reqd_work_group_size' attribute arguments are equal to or less than values + // of 'max_work_group_size' attribute arguments. + // + // We emit diagnostic if values of 'reqd_work_group_size' attribute arguments + // are greater than values of 'max_work_group_size' attribute arguments. + if (const auto *DeclAttr = D->getAttr()) { + if (checkMaxAllowedWorkGroupSize(DeclAttr->getXDim(), DeclAttr->getYDim(), + DeclAttr->getZDim(), A.getXDim(), + A.getYDim(), A.getZDim())) { + Diag(DeclAttr->getLoc(), diag::err_conflicting_sycl_function_attributes) + << DeclAttr << &A; + Diag(A.getLoc(), diag::note_conflicting_attribute); + return nullptr; + } + } + + // If the declaration has a SYCLIntelMaxWorkGroupSizeAttr, check to see if + // the attribute holds values equal to (1, 1, 1) in case the value of + // SYCLIntelMaxGlobalWorkDimAttr equals to 0. + if (const auto *DeclAttr = D->getAttr()) { + if (areInvalidWorkGroupSizeAttrs(DeclAttr->getValue(), A.getXDim(), + A.getYDim(), A.getZDim())) { + Diag(A.getLoc(), diag::err_sycl_x_y_z_arguments_must_be_one) + << &A << DeclAttr; + return nullptr; + } + } + + ASTContext &Context = getASTContext(); + return ::new (Context) SYCLIntelMaxWorkGroupSizeAttr( + Context, A, A.getXDim(), A.getYDim(), A.getZDim()); +} + +void SemaSYCL::handleSYCLReqdWorkGroupSizeAttr(Decl *D, const ParsedAttr &AL) { + checkDeprecatedSYCLAttributeSpelling(AL); + + // __attribute__((reqd_work_group_size)) and [[cl::reqd_work_group_size]] + // all require exactly three arguments. + if ((AL.getKind() == ParsedAttr::AT_ReqdWorkGroupSize && + AL.getAttributeSpellingListIndex() == + SYCLReqdWorkGroupSizeAttr::CXX11_cl_reqd_work_group_size) || + AL.getSyntax() == ParsedAttr::AS_GNU) { + if (!AL.checkExactlyNumArgs(SemaRef, 3)) + return; + } else if (!AL.checkAtLeastNumArgs(SemaRef, 1) || + !AL.checkAtMostNumArgs(SemaRef, 3)) + return; + + size_t NumArgs = AL.getNumArgs(); + Expr *XDimExpr = NumArgs > 0 ? AL.getArgAsExpr(0) : nullptr; + Expr *YDimExpr = NumArgs > 1 ? AL.getArgAsExpr(1) : nullptr; + Expr *ZDimExpr = NumArgs > 2 ? AL.getArgAsExpr(2) : nullptr; + addSYCLReqdWorkGroupSizeAttr(D, AL, XDimExpr, YDimExpr, ZDimExpr); +} + +SYCLReqdWorkGroupSizeAttr * +SemaSYCL::mergeSYCLReqdWorkGroupSizeAttr(Decl *D, + const SYCLReqdWorkGroupSizeAttr &A) { + // If the declaration has a SYCLReqdWorkGroupSizeAttr, check to see if the + // attribute holds values equal to (1, 1, 1) in case the value of + // SYCLIntelMaxGlobalWorkDimAttr equals to 0. + if (const auto *DeclAttr = D->getAttr()) { + if (areInvalidWorkGroupSizeAttrs(DeclAttr->getValue(), A.getXDim(), + A.getYDim(), A.getZDim())) { + Diag(A.getLoc(), diag::err_sycl_x_y_z_arguments_must_be_one) + << &A << DeclAttr; + return nullptr; + } + } + + // If the 'max_work_group_size' attribute is specified on a declaration along + // with 'reqd_work_group_size' attribute, check to see if values of + // 'reqd_work_group_size' attribute arguments are equal or less than values + // of 'max_work_group_size' attribute arguments. + // + // We emit diagnostic if values of 'reqd_work_group_size' attribute arguments + // are greater than values of 'max_work_group_size' attribute arguments. + if (const auto *DeclAttr = D->getAttr()) { + if (checkMaxAllowedWorkGroupSize(A.getXDim(), A.getYDim(), A.getZDim(), + DeclAttr->getXDim(), DeclAttr->getYDim(), + DeclAttr->getZDim())) { + Diag(DeclAttr->getLoc(), diag::err_conflicting_sycl_function_attributes) + << DeclAttr << &A; + Diag(A.getLoc(), diag::note_conflicting_attribute); + return nullptr; + } + } + + // If the 'reqd_work_group_size' attribute is specified on a declaration + // along with 'num_simd_work_items' attribute, the required work group size + // specified by 'num_simd_work_items' attribute must evenly divide the index + // that increments fastest in the 'reqd_work_group_size' attribute. + if (const auto *DeclAttr = D->getAttr()) { + if (checkWorkGroupSize(DeclAttr->getValue(), A.getXDim(), A.getYDim(), + A.getZDim())) { + Diag(DeclAttr->getLoc(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) + << DeclAttr << &A; + Diag(A.getLoc(), diag::note_conflicting_attribute); + return nullptr; + } + } + + // Check to see if there's a duplicate attribute already applied. + if (const auto *DeclAttr = D->getAttr()) { + // If any of the results are known to be different, we can diagnose at this + // point and drop the attribute. + if (anyWorkGroupSizesDiffer(DeclAttr->getXDim(), DeclAttr->getYDim(), + DeclAttr->getZDim(), A.getXDim(), A.getYDim(), + A.getZDim())) { + Diag(DeclAttr->getLoc(), diag::err_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + return nullptr; + } + + // If all of the results are known to be the same, we can silently drop the + // attribute. Otherwise, we have to add the attribute and resolve its + // differences later. + if (allWorkGroupSizesSame(DeclAttr->getXDim(), DeclAttr->getYDim(), + DeclAttr->getZDim(), A.getXDim(), A.getYDim(), + A.getZDim())) + return nullptr; + } + + ASTContext &Context = getASTContext(); + return ::new (Context) SYCLReqdWorkGroupSizeAttr(Context, A, A.getXDim(), + A.getYDim(), A.getZDim()); +} + +IntelReqdSubGroupSizeAttr * +SemaSYCL::mergeIntelReqdSubGroupSizeAttr(Decl *D, + const IntelReqdSubGroupSizeAttr &A) { + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = D->getAttr()) { + if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { + if (const auto *MergeExpr = dyn_cast(A.getValue())) { + if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { + Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + return nullptr; + } + // Do not add a duplicate attribute. + return nullptr; + } + } + } + ASTContext &Context = getASTContext(); + return ::new (Context) IntelReqdSubGroupSizeAttr(Context, A, A.getValue()); +} + +void SemaSYCL::handleIntelReqdSubGroupSizeAttr(Decl *D, const ParsedAttr &AL) { + checkDeprecatedSYCLAttributeSpelling(AL); + + Expr *E = AL.getArgAsExpr(0); + addIntelReqdSubGroupSizeAttr(D, AL, E); +} + +IntelNamedSubGroupSizeAttr * +SemaSYCL::mergeIntelNamedSubGroupSizeAttr(Decl *D, + const IntelNamedSubGroupSizeAttr &A) { + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = D->getAttr()) { + if (DeclAttr->getType() != A.getType()) { + Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + } + return nullptr; + } + + ASTContext &Context = getASTContext(); + return IntelNamedSubGroupSizeAttr::Create(Context, A.getType(), A); +} + +void SemaSYCL::handleIntelNamedSubGroupSizeAttr(Decl *D, const ParsedAttr &AL) { + StringRef SizeStr; + SourceLocation Loc; + if (AL.isArgIdent(0)) { + IdentifierLoc *IL = AL.getArgAsIdent(0); + SizeStr = IL->Ident->getName(); + Loc = IL->Loc; + } else if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, SizeStr, &Loc)) { + return; + } + + IntelNamedSubGroupSizeAttr::SubGroupSizeType SizeType; + if (!IntelNamedSubGroupSizeAttr::ConvertStrToSubGroupSizeType(SizeStr, + SizeType)) { + Diag(Loc, diag::warn_attribute_type_not_supported) << AL << SizeStr; + return; + } + D->addAttr(IntelNamedSubGroupSizeAttr::Create(getASTContext(), SizeType, AL)); +} + +SYCLIntelNumSimdWorkItemsAttr *SemaSYCL::mergeSYCLIntelNumSimdWorkItemsAttr( + Decl *D, const SYCLIntelNumSimdWorkItemsAttr &A) { + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = D->getAttr()) { + if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { + if (const auto *MergeExpr = dyn_cast(A.getValue())) { + if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { + Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + } + // Do not add a duplicate attribute. + return nullptr; + } + } + } + + // If the 'reqd_work_group_size' attribute is specified on a declaration + // along with 'num_simd_work_items' attribute, the required work group size + // specified by 'num_simd_work_items' attribute must evenly divide the index + // that increments fastest in the 'reqd_work_group_size' attribute. + if (const auto *DeclAttr = D->getAttr()) { + if (checkWorkGroupSize(A.getValue(), DeclAttr->getXDim(), + DeclAttr->getYDim(), DeclAttr->getZDim())) { + Diag(A.getLoc(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) + << &A << DeclAttr; + Diag(DeclAttr->getLoc(), diag::note_conflicting_attribute); + return nullptr; + } + } + + ASTContext &Context = getASTContext(); + return ::new (Context) + SYCLIntelNumSimdWorkItemsAttr(Context, A, A.getValue()); +} + +void SemaSYCL::handleSYCLIntelInitiationIntervalAttr(Decl *D, + const ParsedAttr &A) { + checkDeprecatedSYCLAttributeSpelling(A); + + addSYCLIntelInitiationIntervalAttr(D, A, A.getArgAsExpr(0)); +} + +SYCLIntelInitiationIntervalAttr *SemaSYCL::mergeSYCLIntelInitiationIntervalAttr( + Decl *D, const SYCLIntelInitiationIntervalAttr &A) { + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = D->getAttr()) { + if (const auto *DeclExpr = dyn_cast(DeclAttr->getNExpr())) { + if (const auto *MergeExpr = dyn_cast(A.getNExpr())) { + if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { + Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + } + // Do not add a duplicate attribute. + return nullptr; + } + } + } + + ASTContext &Context = getASTContext(); + return ::new (Context) + SYCLIntelInitiationIntervalAttr(Context, A, A.getNExpr()); +} + +void SemaSYCL::handleSYCLIntelSchedulerTargetFmaxMhzAttr(Decl *D, + const ParsedAttr &AL) { + Expr *E = AL.getArgAsExpr(0); + addSYCLIntelSchedulerTargetFmaxMhzAttr(D, AL, E); +} + +SYCLIntelSchedulerTargetFmaxMhzAttr * +SemaSYCL::mergeSYCLIntelSchedulerTargetFmaxMhzAttr( + Decl *D, const SYCLIntelSchedulerTargetFmaxMhzAttr &A) { + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = + D->getAttr()) { + if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { + if (const auto *MergeExpr = dyn_cast(A.getValue())) { + if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { + Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + return nullptr; + } + // Do not add a duplicate attribute. + return nullptr; + } + } + } + ASTContext &Context = getASTContext(); + return ::new (Context) + SYCLIntelSchedulerTargetFmaxMhzAttr(Context, A, A.getValue()); +} + +void SemaSYCL::handleSYCLIntelMaxGlobalWorkDimAttr(Decl *D, + const ParsedAttr &AL) { + Expr *E = AL.getArgAsExpr(0); + addSYCLIntelMaxGlobalWorkDimAttr(D, AL, E); +} + +SYCLIntelMaxGlobalWorkDimAttr *SemaSYCL::mergeSYCLIntelMaxGlobalWorkDimAttr( + Decl *D, const SYCLIntelMaxGlobalWorkDimAttr &A) { + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = D->getAttr()) { + if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { + if (const auto *MergeExpr = dyn_cast(A.getValue())) { + if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { + Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + } + // Do not add a duplicate attribute. + return nullptr; + } + } + } + + // If the declaration has a SYCLIntelMaxWorkGroupSizeAttr or + // SYCLReqdWorkGroupSizeAttr, check to see if the attribute holds values equal + // to (1, 1, 1) in case the value of SYCLIntelMaxGlobalWorkDimAttr equals to + // 0. + const auto *MergeExpr = dyn_cast(A.getValue()); + if (MergeExpr && MergeExpr->getResultAsAPSInt() == 0) { + if (checkWorkGroupSizeAttrExpr(D, A) || + checkWorkGroupSizeAttrExpr(D, A)) + return nullptr; + } + + ASTContext &Context = getASTContext(); + return ::new (Context) + SYCLIntelMaxGlobalWorkDimAttr(Context, A, A.getValue()); +} + +SYCLIntelMinWorkGroupsPerComputeUnitAttr * +SemaSYCL::mergeSYCLIntelMinWorkGroupsPerComputeUnitAttr( + Decl *D, const SYCLIntelMinWorkGroupsPerComputeUnitAttr &A) { + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = + D->getAttr()) { + if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { + if (const auto *MergeExpr = dyn_cast(A.getValue())) { + if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { + Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + } + // Do not add a duplicate attribute. + return nullptr; + } + } + } + + ASTContext &Context = getASTContext(); + return ::new (Context) + SYCLIntelMinWorkGroupsPerComputeUnitAttr(Context, A, A.getValue()); +} + +SYCLIntelMaxWorkGroupsPerMultiprocessorAttr * +SemaSYCL::mergeSYCLIntelMaxWorkGroupsPerMultiprocessorAttr( + Decl *D, const SYCLIntelMaxWorkGroupsPerMultiprocessorAttr &A) { + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = + D->getAttr()) { + if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { + if (const auto *MergeExpr = dyn_cast(A.getValue())) { + if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { + Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + } + // Do not add a duplicate attribute. + return nullptr; + } + } + } + + ASTContext &Context = getASTContext(); + return ::new (Context) + SYCLIntelMaxWorkGroupsPerMultiprocessorAttr(Context, A, A.getValue()); +} + +void SemaSYCL::handleSYCLIntelLoopFuseAttr(Decl *D, const ParsedAttr &A) { + // If no attribute argument is specified, set to default value '1'. + ASTContext &Context = getASTContext(); + Expr *E = A.isArgExpr(0) ? A.getArgAsExpr(0) + : IntegerLiteral::Create(Context, llvm::APInt(32, 1), + Context.IntTy, A.getLoc()); + + addSYCLIntelLoopFuseAttr(D, A, E); +} + +SYCLIntelLoopFuseAttr * +SemaSYCL::mergeSYCLIntelLoopFuseAttr(Decl *D, const SYCLIntelLoopFuseAttr &A) { + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = D->getAttr()) { + // [[intel::loop_fuse]] and [[intel::loop_fuse_independent]] are + // incompatible. + // FIXME: If additional spellings are provided for this attribute, + // this code will do the wrong thing. + if (DeclAttr->getAttributeSpellingListIndex() != + A.getAttributeSpellingListIndex()) { + Diag(A.getLoc(), diag::err_attributes_are_not_compatible) + << &A << DeclAttr << A.isRegularKeywordAttribute(); + Diag(DeclAttr->getLoc(), diag::note_conflicting_attribute); + return nullptr; + } + if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { + if (const auto *MergeExpr = dyn_cast(A.getValue())) { + if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { + Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + } + // Do not add a duplicate attribute. + return nullptr; + } + } + } + + ASTContext &Context = getASTContext(); + return ::new (Context) SYCLIntelLoopFuseAttr(Context, A, A.getValue()); +} + +void SemaSYCL::handleSYCLIntelESimdVectorizeAttr(Decl *D, const ParsedAttr &A) { + checkDeprecatedSYCLAttributeSpelling(A); + + Expr *E = A.getArgAsExpr(0); + addSYCLIntelESimdVectorizeAttr(D, A, E); +} + +SYCLIntelESimdVectorizeAttr *SemaSYCL::mergeSYCLIntelESimdVectorizeAttr( + Decl *D, const SYCLIntelESimdVectorizeAttr &A) { + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = D->getAttr()) { + if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { + if (const auto *MergeExpr = dyn_cast(A.getValue())) { + if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { + Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + } + // Do not add a duplicate attribute. + return nullptr; + } + } + } + ASTContext &Context = getASTContext(); + return ::new (Context) SYCLIntelESimdVectorizeAttr(Context, A, A.getValue()); +} + +void SemaSYCL::handleSYCLIntelNoGlobalWorkOffsetAttr(Decl *D, + const ParsedAttr &A) { + // If no attribute argument is specified, set to default value '1'. + ASTContext &Context = getASTContext(); + Expr *E = A.isArgExpr(0) ? A.getArgAsExpr(0) + : IntegerLiteral::Create(Context, llvm::APInt(32, 1), + Context.IntTy, A.getLoc()); + + addSYCLIntelNoGlobalWorkOffsetAttr(D, A, E); +} + +SYCLIntelNoGlobalWorkOffsetAttr *SemaSYCL::mergeSYCLIntelNoGlobalWorkOffsetAttr( + Decl *D, const SYCLIntelNoGlobalWorkOffsetAttr &A) { + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = D->getAttr()) { + if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { + if (const auto *MergeExpr = dyn_cast(A.getValue())) { + if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { + Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + } + // Do not add a duplicate attribute. + return nullptr; + } + } + } + ASTContext &Context = getASTContext(); + return ::new (Context) + SYCLIntelNoGlobalWorkOffsetAttr(Context, A, A.getValue()); +} + +void SemaSYCL::handleSYCLIntelBankWidthAttr(Decl *D, const ParsedAttr &A) { + addSYCLIntelBankWidthAttr(D, A, A.getArgAsExpr(0)); +} + +SYCLIntelBankWidthAttr * +SemaSYCL::mergeSYCLIntelBankWidthAttr(Decl *D, + const SYCLIntelBankWidthAttr &A) { + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = D->getAttr()) { + const auto *DeclExpr = dyn_cast(DeclAttr->getValue()); + const auto *MergeExpr = dyn_cast(A.getValue()); + if (DeclExpr && MergeExpr && + DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { + Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + return nullptr; + } + } + + ASTContext &Context = getASTContext(); + return ::new (Context) SYCLIntelBankWidthAttr(Context, A, A.getValue()); +} + +void SemaSYCL::handleSYCLIntelNumBanksAttr(Decl *D, const ParsedAttr &A) { + addSYCLIntelNumBanksAttr(D, A, A.getArgAsExpr(0)); +} + +SYCLIntelNumBanksAttr * +SemaSYCL::mergeSYCLIntelNumBanksAttr(Decl *D, const SYCLIntelNumBanksAttr &A) { + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = D->getAttr()) { + const auto *DeclExpr = dyn_cast(DeclAttr->getValue()); + const auto *MergeExpr = dyn_cast(A.getValue()); + if (DeclExpr && MergeExpr && + DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { + Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + return nullptr; + } + } + + ASTContext &Context = getASTContext(); + return ::new (Context) SYCLIntelNumBanksAttr(Context, A, A.getValue()); +} + +void SemaSYCL::handleSYCLIntelMaxReplicatesAttr(Decl *D, const ParsedAttr &A) { + addSYCLIntelMaxReplicatesAttr(D, A, A.getArgAsExpr(0)); +} + +SYCLIntelMaxReplicatesAttr * +SemaSYCL::mergeSYCLIntelMaxReplicatesAttr(Decl *D, + const SYCLIntelMaxReplicatesAttr &A) { + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = D->getAttr()) { + if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { + if (const auto *MergeExpr = dyn_cast(A.getValue())) { + if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { + Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + } + // Do not add a duplicate attribute. + return nullptr; + } + } + } + + ASTContext &Context = getASTContext(); + return ::new (Context) SYCLIntelMaxReplicatesAttr(Context, A, A.getValue()); +} + +void SemaSYCL::handleSYCLIntelForcePow2DepthAttr(Decl *D, const ParsedAttr &A) { + addSYCLIntelForcePow2DepthAttr(D, A, A.getArgAsExpr(0)); +} + +SYCLIntelForcePow2DepthAttr *SemaSYCL::mergeSYCLIntelForcePow2DepthAttr( + Decl *D, const SYCLIntelForcePow2DepthAttr &A) { + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = D->getAttr()) { + if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { + if (const auto *MergeExpr = dyn_cast(A.getValue())) { + if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { + Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + } + // If there is no mismatch, drop any duplicate attributes. + return nullptr; + } + } + } + + ASTContext &Context = getASTContext(); + return ::new (Context) SYCLIntelForcePow2DepthAttr(Context, A, A.getValue()); +} + +void SemaSYCL::handleSYCLIntelPipeIOAttr(Decl *D, const ParsedAttr &A) { + Expr *E = A.getArgAsExpr(0); + addSYCLIntelPipeIOAttr(D, A, E); +} + +SYCLIntelPipeIOAttr * +SemaSYCL::mergeSYCLIntelPipeIOAttr(Decl *D, const SYCLIntelPipeIOAttr &A) { + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = D->getAttr()) { + if (const auto *DeclExpr = dyn_cast(DeclAttr->getID())) { + if (const auto *MergeExpr = dyn_cast(A.getID())) { + if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { + Diag(DeclAttr->getLoc(), diag::err_disallowed_duplicate_attribute) + << &A; + Diag(A.getLoc(), diag::note_conflicting_attribute); + } + // Do not add a duplicate attribute. + return nullptr; + } + } + } + + ASTContext &Context = getASTContext(); + return ::new (Context) SYCLIntelPipeIOAttr(Context, A, A.getID()); +} + +void SemaSYCL::handleSYCLIntelMaxConcurrencyAttr(Decl *D, const ParsedAttr &A) { + Expr *E = A.getArgAsExpr(0); + addSYCLIntelMaxConcurrencyAttr(D, A, E); +} + +SYCLIntelMaxConcurrencyAttr *SemaSYCL::mergeSYCLIntelMaxConcurrencyAttr( + Decl *D, const SYCLIntelMaxConcurrencyAttr &A) { + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = D->getAttr()) { + if (const auto *DeclExpr = dyn_cast(DeclAttr->getNExpr())) { + if (const auto *MergeExpr = dyn_cast(A.getNExpr())) { + if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { + Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + } + // Do not add a duplicate attribute. + return nullptr; + } + } + } + + ASTContext &Context = getASTContext(); + return ::new (Context) SYCLIntelMaxConcurrencyAttr(Context, A, A.getNExpr()); +} + +void SemaSYCL::handleSYCLAddIRAttributesFunctionAttr(Decl *D, + const ParsedAttr &A) { + llvm::SmallVector Args; + Args.reserve(A.getNumArgs() - 1); + for (unsigned I = 0; I < A.getNumArgs(); I++) { + assert(A.isArgExpr(I)); + Args.push_back(A.getArgAsExpr(I)); + } + + addSYCLAddIRAttributesFunctionAttr(D, A, Args); +} + +static bool hasSameSYCLAddIRAttributes( + const SmallVector, 4> &LAttrs, + const SmallVector, 4> &RAttrs) { + std::set> LNameValSet{LAttrs.begin(), + LAttrs.end()}; + std::set> RNameValSet{RAttrs.begin(), + RAttrs.end()}; + return LNameValSet == RNameValSet; +} + +template +static bool checkSYCLAddIRAttributesMergeability(const AddIRAttrT &NewAttr, + const AddIRAttrT &ExistingAttr, + SemaSYCL &S) { + ASTContext &Context = S.getASTContext(); + // If there are no dependent argument expressions and the filters or the + // attributes are different, then fail due to differing duplicates. + if (!S.hasDependentExpr(NewAttr.args_begin(), NewAttr.args_size()) && + !S.hasDependentExpr(ExistingAttr.args_begin(), + ExistingAttr.args_size()) && + (NewAttr.getAttributeFilter() != ExistingAttr.getAttributeFilter() || + !hasSameSYCLAddIRAttributes( + NewAttr.getAttributeNameValuePairs(Context), + ExistingAttr.getAttributeNameValuePairs(Context)))) { + S.Diag(ExistingAttr.getLoc(), diag::err_duplicate_attribute) << &NewAttr; + S.Diag(NewAttr.getLoc(), diag::note_conflicting_attribute); + return true; + } + return false; +} + +SYCLAddIRAttributesFunctionAttr *SemaSYCL::mergeSYCLAddIRAttributesFunctionAttr( + Decl *D, const SYCLAddIRAttributesFunctionAttr &A) { + if (const auto *ExistingAttr = + D->getAttr()) { + checkSYCLAddIRAttributesMergeability(A, *ExistingAttr, *this); + return nullptr; + } + ASTContext &Context = getASTContext(); + return A.clone(Context); +} + +void SemaSYCL::handleSYCLAddIRAttributesKernelParameterAttr( + Decl *D, const ParsedAttr &A) { + llvm::SmallVector Args; + Args.reserve(A.getNumArgs() - 1); + for (unsigned I = 0; I < A.getNumArgs(); I++) { + assert(A.getArgAsExpr(I)); + Args.push_back(A.getArgAsExpr(I)); + } + + addSYCLAddIRAttributesKernelParameterAttr(D, A, Args); +} + +SYCLAddIRAttributesKernelParameterAttr * +SemaSYCL::mergeSYCLAddIRAttributesKernelParameterAttr( + Decl *D, const SYCLAddIRAttributesKernelParameterAttr &A) { + if (const auto *ExistingAttr = + D->getAttr()) { + checkSYCLAddIRAttributesMergeability(A, *ExistingAttr, *this); + return nullptr; + } + ASTContext &Context = getASTContext(); + return A.clone(Context); +} + +void SemaSYCL::handleSYCLAddIRAttributesGlobalVariableAttr( + Decl *D, const ParsedAttr &A) { + llvm::SmallVector Args; + Args.reserve(A.getNumArgs() - 1); + for (unsigned I = 0; I < A.getNumArgs(); I++) { + assert(A.getArgAsExpr(I)); + Args.push_back(A.getArgAsExpr(I)); + } + + addSYCLAddIRAttributesGlobalVariableAttr(D, A, Args); +} + +SYCLAddIRAttributesGlobalVariableAttr * +SemaSYCL::mergeSYCLAddIRAttributesGlobalVariableAttr( + Decl *D, const SYCLAddIRAttributesGlobalVariableAttr &A) { + if (const auto *ExistingAttr = + D->getAttr()) { + checkSYCLAddIRAttributesMergeability(A, *ExistingAttr, *this); + return nullptr; + } + ASTContext &Context = getASTContext(); + return A.clone(Context); +} + +void SemaSYCL::handleSYCLAddIRAnnotationsMemberAttr(Decl *D, + const ParsedAttr &A) { + llvm::SmallVector Args; + Args.reserve(A.getNumArgs()); + for (unsigned I = 0; I < A.getNumArgs(); I++) { + assert(A.getArgAsExpr(I)); + Args.push_back(A.getArgAsExpr(I)); + } + + addSYCLAddIRAnnotationsMemberAttr(D, A, Args); +} + +SYCLAddIRAnnotationsMemberAttr *SemaSYCL::mergeSYCLAddIRAnnotationsMemberAttr( + Decl *D, const SYCLAddIRAnnotationsMemberAttr &A) { + if (const auto *ExistingAttr = D->getAttr()) { + checkSYCLAddIRAttributesMergeability(A, *ExistingAttr, *this); + return nullptr; + } + ASTContext &Context = getASTContext(); + return A.clone(Context); +} + +void SemaSYCL::handleSYCLDeviceHasAttr(Decl *D, const ParsedAttr &A) { + // Ignore the attribute if compiling for the host side because aspects may not + // be marked properly for such compilation + if (!getLangOpts().SYCLIsDevice) + return; + + SmallVector Args; + for (unsigned I = 0; I < A.getNumArgs(); ++I) + Args.push_back(A.getArgAsExpr(I)); + + addSYCLDeviceHasAttr(D, A, Args.data(), Args.size()); +} + +SYCLDeviceHasAttr * +SemaSYCL::mergeSYCLDeviceHasAttr(Decl *D, const SYCLDeviceHasAttr &A) { + if (const auto *ExistingAttr = D->getAttr()) { + Diag(ExistingAttr->getLoc(), diag::warn_duplicate_attribute_exact) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + return nullptr; + } + + SmallVector Args; + for (auto *E : A.aspects()) + Args.push_back(E); + ASTContext &Context = getASTContext(); + return ::new (Context) + SYCLDeviceHasAttr(Context, A, Args.data(), Args.size()); +} + +void SemaSYCL::handleSYCLUsesAspectsAttr(Decl *D, const ParsedAttr &A) { + // Ignore the attribute if compiling for the host because aspects may not be + // marked properly for such compilation + if (!getLangOpts().SYCLIsDevice) + return; + + SmallVector Args; + for (unsigned I = 0; I < A.getNumArgs(); ++I) + Args.push_back(A.getArgAsExpr(I)); + + addSYCLUsesAspectsAttr(D, A, Args.data(), Args.size()); +} + +SYCLUsesAspectsAttr * +SemaSYCL::mergeSYCLUsesAspectsAttr(Decl *D, const SYCLUsesAspectsAttr &A) { + if (const auto *ExistingAttr = D->getAttr()) { + Diag(ExistingAttr->getLoc(), diag::warn_duplicate_attribute_exact) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + return nullptr; + } + + SmallVector Args; + for (auto *E : A.aspects()) + Args.push_back(E); + ASTContext &Context = getASTContext(); + return ::new (Context) + SYCLUsesAspectsAttr(Context, A, Args.data(), Args.size()); +} + +void SemaSYCL::handleSYCLTypeAttr(Decl *D, const ParsedAttr &AL) { + if (!AL.isArgIdent(0)) { + Diag(AL.getLoc(), diag::err_attribute_argument_type) + << AL << AANT_ArgumentIdentifier; + return; + } + + IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; + SYCLTypeAttr::SYCLType Type; + + if (!SYCLTypeAttr::ConvertStrToSYCLType(II->getName(), Type)) { + Diag(AL.getLoc(), diag::err_attribute_argument_not_supported) << AL << II; + return; + } + + if (SYCLTypeAttr *NewAttr = mergeSYCLTypeAttr(D, AL, Type)) + D->addAttr(NewAttr); +} + +SYCLTypeAttr *SemaSYCL::mergeSYCLTypeAttr(Decl *D, + const AttributeCommonInfo &CI, + SYCLTypeAttr::SYCLType TypeName) { + if (const auto *ExistingAttr = D->getAttr()) { + if (ExistingAttr->getType() != TypeName) { + Diag(ExistingAttr->getLoc(), diag::err_duplicate_attribute) + << ExistingAttr; + Diag(CI.getLoc(), diag::note_previous_attribute); + } + // Do not add duplicate attribute + return nullptr; + } + ASTContext &Context = getASTContext(); + return ::new (Context) SYCLTypeAttr(Context, CI, TypeName); +} + +/// Handle the [[intel::doublepump]] attribute. +void SemaSYCL::handleSYCLIntelDoublePumpAttr(Decl *D, const ParsedAttr &AL) { + // 'doublepump' Attribute does not take any argument. Give a warning for + // duplicate attributes but not if it's one we've implicitly added and drop + // any duplicates. + if (const auto *ExistingAttr = D->getAttr()) { + if (ExistingAttr && !ExistingAttr->isImplicit()) { + Diag(AL.getLoc(), diag::warn_duplicate_attribute_exact) << &AL; + Diag(ExistingAttr->getLoc(), diag::note_previous_attribute); + return; + } + } + + // Check attribute applies to field, constant variables, local variables, + // static variables, non-static data members, and device_global variables + // for the device compilation. + if ((D->getKind() == Decl::ParmVar) || checkValidFPGAMemoryAttributesVar(D)) { + Diag(AL.getLoc(), diag::err_fpga_attribute_incorrect_variable) + << AL << /*agent memory arguments*/ 0; + return; + } + + ASTContext &Context = getASTContext(); + // If the declaration does not have an [[intel::fpga_memory]] + // attribute, this creates one as an implicit attribute. + if (!D->hasAttr()) + D->addAttr(SYCLIntelMemoryAttr::CreateImplicit( + Context, SYCLIntelMemoryAttr::Default)); + + D->addAttr(::new (Context) SYCLIntelDoublePumpAttr(Context, AL)); +} + +/// Handle the [[intel::singlepump]] attribute. +void SemaSYCL::handleSYCLIntelSinglePumpAttr(Decl *D, const ParsedAttr &AL) { + // 'singlepump' Attribute does not take any argument. Give a warning for + // duplicate attributes but not if it's one we've implicitly added and drop + // any duplicates. + if (const auto *ExistingAttr = D->getAttr()) { + if (ExistingAttr && !ExistingAttr->isImplicit()) { + Diag(AL.getLoc(), diag::warn_duplicate_attribute_exact) << &AL; + Diag(ExistingAttr->getLoc(), diag::note_previous_attribute); + return; + } + } + + // Check attribute applies to field, constant variables, local variables, + // static variables, non-static data members, and device_global variables + // for the device compilation. + if (D->getKind() == Decl::ParmVar || checkValidFPGAMemoryAttributesVar(D)) { + Diag(AL.getLoc(), diag::err_fpga_attribute_incorrect_variable) + << AL << /*agent memory arguments*/ 0; + return; + } + + // If the declaration does not have an [[intel::fpga_memory]] + // attribute, this creates one as an implicit attribute. + ASTContext &Context = getASTContext(); + if (!D->hasAttr()) + D->addAttr(SYCLIntelMemoryAttr::CreateImplicit( + Context, SYCLIntelMemoryAttr::Default)); + + D->addAttr(::new (Context) SYCLIntelSinglePumpAttr(Context, AL)); +} + +/// Handle the [[intel::fpga_memory]] attribute. +/// This is incompatible with the [[intel::fpga_register]] attribute. +void SemaSYCL::handleSYCLIntelMemoryAttr(Decl *D, const ParsedAttr &AL) { + SYCLIntelMemoryAttr::MemoryKind Kind; + if (AL.getNumArgs() == 0) + Kind = SYCLIntelMemoryAttr::Default; + else { + StringRef Str; + if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str)) + return; + if (Str.empty() || + !SYCLIntelMemoryAttr::ConvertStrToMemoryKind(Str, Kind)) { + SmallString<256> ValidStrings; + SYCLIntelMemoryAttr::generateValidStrings(ValidStrings); + Diag(AL.getLoc(), diag::err_intel_fpga_memory_arg_invalid) + << AL << ValidStrings; + return; + } + } + + if (auto *MA = D->getAttr()) { + // Check to see if there's a duplicate memory attribute with different + // values already applied to the declaration. + if (!MA->isImplicit()) { + if (MA->getKind() != Kind) { + Diag(AL.getLoc(), diag::warn_duplicate_attribute) << &AL; + Diag(MA->getLocation(), diag::note_previous_attribute); + } + // Drop the duplicate attribute. + return; + } + // We are adding a user memory attribute, drop any implicit default. + D->dropAttr(); + } + + // Check attribute applies to field, constant variables, local variables, + // static variables, agent memory arguments, non-static data members, + // and device_global variables for the device compilation. + if (checkValidFPGAMemoryAttributesVar(D)) { + Diag(AL.getLoc(), diag::err_fpga_attribute_incorrect_variable) + << AL << /*agent memory arguments*/ 1; + return; + } + + ASTContext &Context = getASTContext(); + D->addAttr(::new (Context) SYCLIntelMemoryAttr(Context, AL, Kind)); +} + +/// Handle the [[intel::fpga_register]] attribute. +/// This is incompatible with most of the other memory attributes. +void SemaSYCL::handleSYCLIntelRegisterAttr(Decl *D, const ParsedAttr &A) { + // 'fpga_register' Attribute does not take any argument. Give a warning for + // duplicate attributes but not if it's one we've implicitly added and drop + // any duplicates. + if (const auto *ExistingAttr = D->getAttr()) { + if (ExistingAttr && !ExistingAttr->isImplicit()) { + Diag(A.getLoc(), diag::warn_duplicate_attribute_exact) << &A; + Diag(ExistingAttr->getLoc(), diag::note_previous_attribute); + return; + } + } + + // Check attribute applies to field, constant variables, local variables, + // static variables, non-static data members, and device_global variables + // for the device compilation. + if (D->getKind() == Decl::ParmVar || checkValidFPGAMemoryAttributesVar(D)) { + Diag(A.getLoc(), diag::err_fpga_attribute_incorrect_variable) + << A << /*agent memory arguments*/ 0; + return; + } + + ASTContext &Context = getASTContext(); + D->addAttr(::new (Context) SYCLIntelRegisterAttr(Context, A)); +} + +void SemaSYCL::handleIntelSimpleDualPortAttr(Decl *D, const ParsedAttr &AL) { + // 'simple_dual_port' Attribute does not take any argument. Give a warning for + // duplicate attributes but not if it's one we've implicitly added and drop + // any duplicates. + if (const auto *ExistingAttr = D->getAttr()) { + if (ExistingAttr && !ExistingAttr->isImplicit()) { + Diag(AL.getLoc(), diag::warn_duplicate_attribute_exact) << &AL; + Diag(ExistingAttr->getLoc(), diag::note_previous_attribute); + return; + } + } + + // Check attribute applies to field, constant variables, local variables, + // static variables, agent memory arguments, non-static data members, + // and device_global variables for the device compilation. + if (checkValidFPGAMemoryAttributesVar(D)) { + Diag(AL.getLoc(), diag::err_fpga_attribute_incorrect_variable) + << AL << /*agent memory arguments*/ 1; + return; + } + + ASTContext &Context = getASTContext(); + if (!D->hasAttr()) + D->addAttr(SYCLIntelMemoryAttr::CreateImplicit( + Context, SYCLIntelMemoryAttr::Default)); + + D->addAttr(::new (Context) SYCLIntelSimpleDualPortAttr(Context, AL)); +} + +/// Handle the merge attribute. +/// This requires two string arguments. The first argument is a name, the +/// second is a direction. The direction must be "depth" or "width". +/// This is incompatible with the register attribute. +void SemaSYCL::handleSYCLIntelMergeAttr(Decl *D, const ParsedAttr &AL) { + SmallVector Results; + for (int I = 0; I < 2; I++) { + StringRef Str; + if (!SemaRef.checkStringLiteralArgumentAttr(AL, I, Str)) + return; + + if (I == 1 && Str != "depth" && Str != "width") { + Diag(AL.getLoc(), diag::err_intel_fpga_merge_dir_invalid) << AL; + return; + } + Results.push_back(Str); + } + + // Warn about duplicate attributes if they have different arguments, no + // diagnostic is emitted if the arguments match, and drop any duplicate + // attributes. + if (const auto *Existing = D->getAttr()) { + if (Existing && !(Existing->getName() == Results[0] && + Existing->getDirection() == Results[1])) { + Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; + Diag(Existing->getLoc(), diag::note_previous_attribute); + } + // If there is no mismatch, drop any duplicate attributes. + return; + } + + // Check attribute applies to field, constant variables, local variables, + // static variables, non-static data members, and device_global variables + // for the device compilation. + if (D->getKind() == Decl::ParmVar || checkValidFPGAMemoryAttributesVar(D)) { + Diag(AL.getLoc(), diag::err_fpga_attribute_incorrect_variable) + << AL << /*agent memory arguments*/ 0; + return; + } + + ASTContext &Context = getASTContext(); + if (!D->hasAttr()) + D->addAttr(SYCLIntelMemoryAttr::CreateImplicit( + Context, SYCLIntelMemoryAttr::Default)); + + D->addAttr(::new (Context) + SYCLIntelMergeAttr(Context, AL, Results[0], Results[1])); +} + +/// Give a warning for duplicate attributes, return true if duplicate. +template +static bool checkForDuplicateAttribute(SemaSYCL &S, Decl *D, + const ParsedAttr &Attr) { + // Give a warning for duplicates but not if it's one we've implicitly added. + auto *A = D->getAttr(); + if (A && !A->isImplicit()) { + S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute_exact) << A; + return true; + } + return false; +} + +/// Handle the bank_bits attribute. +/// This attribute accepts a list of values greater than zero. +/// This is incompatible with the register attribute. +/// The numbanks and bank_bits attributes are related. If numbanks exists +/// when handling bank_bits they are checked for consistency. If numbanks +/// hasn't been added yet an implicit one is added with the correct value. +/// If the user later adds a numbanks attribute the implicit one is removed. +/// The values must be consecutive values (i.e. 3,4,5 or 2,1). +void SemaSYCL::handleSYCLIntelBankBitsAttr(Decl *D, const ParsedAttr &A) { + checkForDuplicateAttribute(*this, D, A); + + if (!A.checkAtLeastNumArgs(SemaRef, 1)) + return; + + SmallVector Args; + for (unsigned I = 0; I < A.getNumArgs(); ++I) { + Args.push_back(A.getArgAsExpr(I)); + } + + addSYCLIntelBankBitsAttr(D, A, Args.data(), Args.size()); +} + +void SemaSYCL::handleSYCLIntelPrivateCopiesAttr(Decl *D, const ParsedAttr &A) { + addSYCLIntelPrivateCopiesAttr(D, A, A.getArgAsExpr(0)); +} + +void SemaSYCL::handleSYCLIntelNumSimdWorkItemsAttr(Decl *D, + const ParsedAttr &A) { + Expr *E = A.getArgAsExpr(0); + addSYCLIntelNumSimdWorkItemsAttr(D, A, E); +} + +// Handles use_stall_enable_clusters +void SemaSYCL::handleSYCLIntelUseStallEnableClustersAttr(Decl *D, + const ParsedAttr &A) { + ASTContext &Context = getASTContext(); + D->addAttr(::new (Context) SYCLIntelUseStallEnableClustersAttr(Context, A)); +} + +// Handles max_work_group_size attribute. +void SemaSYCL::handleSYCLIntelMaxWorkGroupSize(Decl *D, const ParsedAttr &AL) { + addSYCLIntelMaxWorkGroupSizeAttr(D, AL, AL.getArgAsExpr(0), + AL.getArgAsExpr(1), AL.getArgAsExpr(2)); +} + +// Handles min_work_groups_per_cu attribute. +void SemaSYCL::handleSYCLIntelMinWorkGroupsPerComputeUnit( + Decl *D, const ParsedAttr &AL) { + addSYCLIntelMinWorkGroupsPerComputeUnitAttr(D, AL, AL.getArgAsExpr(0)); +} + +// Handles max_work_groups_per_mp attribute. +void SemaSYCL::handleSYCLIntelMaxWorkGroupsPerMultiprocessor( + Decl *D, const ParsedAttr &AL) { + addSYCLIntelMaxWorkGroupsPerMultiprocessorAttr(D, AL, AL.getArgAsExpr(0)); +} + +void SemaSYCL::handleSYCLDeviceAttr(Decl *D, const ParsedAttr &AL) { + auto *ND = cast(D); + if (!ND->isExternallyVisible()) { + Diag(AL.getLoc(), diag::err_sycl_attribute_internal_decl) + << AL << !isa(ND); + return; + } + + if (auto *VD = dyn_cast(D)) { + QualType VarType = VD->getType(); + // Diagnose only for non-dependent types since dependent type don't have + // attributes applied on them ATM. + if (!VarType->isDependentType() && + !isTypeDecoratedWithDeclAttribute( + VD->getType())) { + Diag(AL.getLoc(), diag::err_sycl_attribute_not_device_global) << AL; + return; + } + } + + handleSimpleAttribute(*this, D, AL); +} + +void SemaSYCL::handleSYCLDeviceIndirectlyCallableAttr(Decl *D, + const ParsedAttr &AL) { + auto *FD = cast(D); + if (!FD->isExternallyVisible()) { + Diag(AL.getLoc(), diag::err_sycl_attribute_internal_decl) + << AL << /*function*/ 0; + return; + } + + ASTContext &Context = getASTContext(); + D->addAttr(SYCLDeviceAttr::CreateImplicit(Context)); + handleSimpleAttribute(*this, D, AL); +} + +void SemaSYCL::handleSYCLGlobalVarAttr(Decl *D, const ParsedAttr &AL) { + ASTContext &Context = getASTContext(); + if (!Context.getSourceManager().isInSystemHeader(D->getLocation())) { + Diag(AL.getLoc(), diag::err_attribute_only_system_header) << AL; + return; + } + + handleSimpleAttribute(*this, D, AL); +} + +void SemaSYCL::handleSYCLRegisterNumAttr(Decl *D, const ParsedAttr &AL) { + if (!AL.checkExactlyNumArgs(SemaRef, 1)) + return; + uint32_t RegNo = 0; + const Expr *E = AL.getArgAsExpr(0); + if (!SemaRef.checkUInt32Argument(AL, E, RegNo, 0, /*StrictlyUnsigned=*/true)) + return; + ASTContext &Context = getASTContext(); + D->addAttr(::new (Context) SYCLRegisterNumAttr(Context, AL, RegNo)); +} + +void SemaSYCL::checkSYCLAddIRAttributesFunctionAttrConflicts(Decl *D) { + const auto *AddIRFuncAttr = D->getAttr(); + + // If there is no such attribute there is nothing to check. If there are + // dependent arguments we cannot know the actual number of arguments so we + // defer the check. + if (!AddIRFuncAttr || + hasDependentExpr(AddIRFuncAttr->args_begin(), AddIRFuncAttr->args_size())) + return; + + // If there are no name-value pairs in the attribute it will not have an + // effect and we can skip the check. The filter is ignored. + size_t NumArgsWithoutFilter = + AddIRFuncAttr->args_size() - (AddIRFuncAttr->hasFilterList() ? 1 : 0); + if (NumArgsWithoutFilter == 0) + return; + + // "sycl-single-task" is present on all single_task invocations, implicitly + // added by the SYCL headers. It can only conflict with max_global_work_dim, + // but the value will be the same so there is no need for a warning. + ASTContext &Context = getASTContext(); + if (NumArgsWithoutFilter == 2) { + auto NameValuePairs = AddIRFuncAttr->getAttributeNameValuePairs(Context); + if (NameValuePairs.size() > 0 && + NameValuePairs[0].first == "sycl-single-task") + return; + } + + // If there are potentially conflicting attributes, we issue a warning. + for (const auto *Attr : std::vector{ + D->getAttr(), + D->getAttr(), + D->getAttr(), + D->getAttr()}) + if (Attr) + Diag(Attr->getLoc(), diag::warn_sycl_old_and_new_kernel_attributes) + << Attr; +}