Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -1309,30 +1309,34 @@ def AMDGPUFlatWorkGroupSize : InheritableAttr { let Spellings = [GNU<"amdgpu_flat_work_group_size">]; - let Args = [UnsignedArgument<"Min">, UnsignedArgument<"Max">]; + let Args = [ExprArgument<"Min">, ExprArgument<"Max", 1>]; let Documentation = [AMDGPUFlatWorkGroupSizeDocs]; let Subjects = SubjectList<[Function], ErrorDiag, "ExpectedKernelFunction">; + let TemplateDependent = 1; } def AMDGPUWavesPerEU : InheritableAttr { let Spellings = [GNU<"amdgpu_waves_per_eu">]; - let Args = [UnsignedArgument<"Min">, UnsignedArgument<"Max", 1>]; + let Args = [ExprArgument<"Min">, ExprArgument<"Max", 1>]; let Documentation = [AMDGPUWavesPerEUDocs]; let Subjects = SubjectList<[Function], ErrorDiag, "ExpectedKernelFunction">; + let TemplateDependent = 1; } def AMDGPUNumSGPR : InheritableAttr { let Spellings = [GNU<"amdgpu_num_sgpr">]; - let Args = [UnsignedArgument<"NumSGPR">]; + let Args = [ExprArgument<"NumSGPR">]; let Documentation = [AMDGPUNumSGPRNumVGPRDocs]; let Subjects = SubjectList<[Function], ErrorDiag, "ExpectedKernelFunction">; + let TemplateDependent = 1; } def AMDGPUNumVGPR : InheritableAttr { let Spellings = [GNU<"amdgpu_num_vgpr">]; - let Args = [UnsignedArgument<"NumVGPR">]; + let Args = [ExprArgument<"NumVGPR">]; let Documentation = [AMDGPUNumSGPRNumVGPRDocs]; let Subjects = SubjectList<[Function], ErrorDiag, "ExpectedKernelFunction">; + let TemplateDependent = 1; } def NoSplitStack : InheritableAttr { Index: lib/CodeGen/TargetInfo.cpp =================================================================== --- lib/CodeGen/TargetInfo.cpp +++ lib/CodeGen/TargetInfo.cpp @@ -7661,6 +7661,18 @@ }; } +namespace +{ + inline + llvm::APSInt getConstexprInt(const Expr *E, const ASTContext& Ctx) + { + llvm::APSInt r{32, 0}; + if (E) E->EvaluateAsInt(r, Ctx); + + return r; + } +} + void AMDGPUTargetCodeGenInfo::setTargetAttributes( const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M, ForDefinition_t IsForDefinition) const { @@ -7676,8 +7688,11 @@ FD->getAttr() : nullptr; const auto *FlatWGS = FD->getAttr(); if (ReqdWGS || FlatWGS) { - unsigned Min = FlatWGS ? FlatWGS->getMin() : 0; - unsigned Max = FlatWGS ? FlatWGS->getMax() : 0; + llvm::APSInt min = getConstexprInt(FlatWGS->getMin(), FD->getASTContext()); + llvm::APSInt max = getConstexprInt(FlatWGS->getMax(), FD->getASTContext()); + + unsigned Min = min.getZExtValue(); + unsigned Max = std::max(min, max).getZExtValue(); if (ReqdWGS && Min == 0 && Max == 0) Min = Max = ReqdWGS->getXDim() * ReqdWGS->getYDim() * ReqdWGS->getZDim(); @@ -7691,8 +7706,13 @@ } if (const auto *Attr = FD->getAttr()) { - unsigned Min = Attr->getMin(); - unsigned Max = Attr->getMax(); + llvm::APSInt min = getConstexprInt(Attr->getMin(), FD->getASTContext()); + llvm::APSInt max = getConstexprInt(Attr->getMax(), FD->getASTContext()); + + Attr->getMin()->dump(); + Attr->getMax()->dump(); + unsigned Min = min.getZExtValue(); + unsigned Max = std::max(min, max).getZExtValue(); if (Min != 0) { assert((Max == 0 || Min <= Max) && "Min must be less than or equal Max"); @@ -7706,14 +7726,18 @@ } if (const auto *Attr = FD->getAttr()) { - unsigned NumSGPR = Attr->getNumSGPR(); + llvm::APSInt sgprs = + getConstexprInt(Attr->getNumSGPR(), FD->getASTContext()); + unsigned NumSGPR = sgprs.getZExtValue(); if (NumSGPR != 0) F->addFnAttr("amdgpu-num-sgpr", llvm::utostr(NumSGPR)); } if (const auto *Attr = FD->getAttr()) { - uint32_t NumVGPR = Attr->getNumVGPR(); + llvm::APSInt vgprs = + getConstexprInt(Attr->getNumVGPR(), FD->getASTContext()); + unsigned NumVGPR = vgprs.getZExtValue(); if (NumVGPR != 0) F->addFnAttr("amdgpu-num-vgpr", llvm::utostr(NumVGPR)); Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -5469,16 +5469,36 @@ } } +namespace +{ + bool checkAllAreIntegral(const AttributeList &Attr, Sema &S) { + for (auto i = 0u; i != Attr.getNumArgs(); ++i) { + auto e = Attr.getArgAsExpr(i); + if (e && !e->getType()->isIntegralOrEnumerationType()) { + S.Diag(getAttrLoc(Attr), diag::err_attribute_argument_n_type) + << getAttrName(Attr) << i << AANT_ArgumentIntegerConstant + << e->getSourceRange(); + + return false; + } + } + + return true; + } +} + static void handleAMDGPUFlatWorkGroupSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { uint32_t Min = 0; Expr *MinExpr = Attr.getArgAsExpr(0); - if (!checkUInt32Argument(S, Attr, MinExpr, Min)) + if (MinExpr->isEvaluatable(S.Context) && + !checkUInt32Argument(S, Attr, MinExpr, Min)) return; uint32_t Max = 0; Expr *MaxExpr = Attr.getArgAsExpr(1); - if (!checkUInt32Argument(S, Attr, MaxExpr, Max)) + if (MaxExpr->isEvaluatable(S.Context) && + !checkUInt32Argument(S, Attr, MaxExpr, Max)) return; if (Min == 0 && Max != 0) { @@ -5493,21 +5513,28 @@ } D->addAttr(::new (S.Context) - AMDGPUFlatWorkGroupSizeAttr(Attr.getLoc(), S.Context, Min, Max, - Attr.getAttributeSpellingListIndex())); + AMDGPUFlatWorkGroupSizeAttr( + Attr.getLoc(), S.Context, MinExpr, MaxExpr, + Attr.getAttributeSpellingListIndex())); } static void handleAMDGPUWavesPerEUAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (!checkAllAreIntegral(Attr, S)) + return; + uint32_t Min = 0; Expr *MinExpr = Attr.getArgAsExpr(0); - if (!checkUInt32Argument(S, Attr, MinExpr, Min)) + if (MinExpr->isEvaluatable(S.Context) && + !checkUInt32Argument(S, Attr, MinExpr, Min)) return; uint32_t Max = 0; + Expr *MaxExpr = MinExpr; if (Attr.getNumArgs() == 2) { - Expr *MaxExpr = Attr.getArgAsExpr(1); - if (!checkUInt32Argument(S, Attr, MaxExpr, Max)) + MaxExpr = Attr.getArgAsExpr(1); + if (MaxExpr->isEvaluatable(S.Context) && + !checkUInt32Argument(S, Attr, MaxExpr, Max)) return; } @@ -5523,31 +5550,39 @@ } D->addAttr(::new (S.Context) - AMDGPUWavesPerEUAttr(Attr.getLoc(), S.Context, Min, Max, + AMDGPUWavesPerEUAttr(Attr.getLoc(), S.Context, MinExpr, MaxExpr, Attr.getAttributeSpellingListIndex())); } static void handleAMDGPUNumSGPRAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (!checkAllAreIntegral(Attr, S)) + return; + uint32_t NumSGPR = 0; Expr *NumSGPRExpr = Attr.getArgAsExpr(0); - if (!checkUInt32Argument(S, Attr, NumSGPRExpr, NumSGPR)) + if (NumSGPRExpr->isEvaluatable(S.Context) && + !checkUInt32Argument(S, Attr, NumSGPRExpr, NumSGPR)) return; D->addAttr(::new (S.Context) - AMDGPUNumSGPRAttr(Attr.getLoc(), S.Context, NumSGPR, + AMDGPUNumSGPRAttr(Attr.getLoc(), S.Context, NumSGPRExpr, Attr.getAttributeSpellingListIndex())); } static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (!checkAllAreIntegral(Attr, S)) + return; + uint32_t NumVGPR = 0; Expr *NumVGPRExpr = Attr.getArgAsExpr(0); - if (!checkUInt32Argument(S, Attr, NumVGPRExpr, NumVGPR)) + if (NumVGPRExpr->isEvaluatable(S.Context) && + !checkUInt32Argument(S, Attr, NumVGPRExpr, NumVGPR)) return; D->addAttr(::new (S.Context) - AMDGPUNumVGPRAttr(Attr.getLoc(), S.Context, NumVGPR, + AMDGPUNumVGPRAttr(Attr.getLoc(), S.Context, NumVGPRExpr, Attr.getAttributeSpellingListIndex())); }