1ed35a92cSVlad Serebrennikov //===------ SemaAMDGPU.cpp ------- AMDGPU target-specific routines --------===// 2ed35a92cSVlad Serebrennikov // 3ed35a92cSVlad Serebrennikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4ed35a92cSVlad Serebrennikov // See https://llvm.org/LICENSE.txt for license information. 5ed35a92cSVlad Serebrennikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6ed35a92cSVlad Serebrennikov // 7ed35a92cSVlad Serebrennikov //===----------------------------------------------------------------------===// 8ed35a92cSVlad Serebrennikov // 9ed35a92cSVlad Serebrennikov // This file implements semantic analysis functions specific to AMDGPU. 10ed35a92cSVlad Serebrennikov // 11ed35a92cSVlad Serebrennikov //===----------------------------------------------------------------------===// 12ed35a92cSVlad Serebrennikov 13ed35a92cSVlad Serebrennikov #include "clang/Sema/SemaAMDGPU.h" 14ed35a92cSVlad Serebrennikov #include "clang/Basic/DiagnosticSema.h" 15ed35a92cSVlad Serebrennikov #include "clang/Basic/TargetBuiltins.h" 16ed35a92cSVlad Serebrennikov #include "clang/Sema/Ownership.h" 17ed35a92cSVlad Serebrennikov #include "clang/Sema/Sema.h" 18ed35a92cSVlad Serebrennikov #include "llvm/Support/AtomicOrdering.h" 19ed35a92cSVlad Serebrennikov #include <cstdint> 20ed35a92cSVlad Serebrennikov 21ed35a92cSVlad Serebrennikov namespace clang { 22ed35a92cSVlad Serebrennikov 23ed35a92cSVlad Serebrennikov SemaAMDGPU::SemaAMDGPU(Sema &S) : SemaBase(S) {} 24ed35a92cSVlad Serebrennikov 25ed35a92cSVlad Serebrennikov bool SemaAMDGPU::CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID, 26ed35a92cSVlad Serebrennikov CallExpr *TheCall) { 27ed35a92cSVlad Serebrennikov // position of memory order and scope arguments in the builtin 28ed35a92cSVlad Serebrennikov unsigned OrderIndex, ScopeIndex; 29*a2c3e0c4SMatt Arsenault 30*a2c3e0c4SMatt Arsenault const auto *FD = SemaRef.getCurFunctionDecl(); 31*a2c3e0c4SMatt Arsenault assert(FD && "AMDGPU builtins should not be used outside of a function"); 32*a2c3e0c4SMatt Arsenault llvm::StringMap<bool> CallerFeatureMap; 33*a2c3e0c4SMatt Arsenault getASTContext().getFunctionFeatureMap(CallerFeatureMap, FD); 34*a2c3e0c4SMatt Arsenault bool HasGFX950Insts = 35*a2c3e0c4SMatt Arsenault Builtin::evaluateRequiredTargetFeatures("gfx950-insts", CallerFeatureMap); 36*a2c3e0c4SMatt Arsenault 37ed35a92cSVlad Serebrennikov switch (BuiltinID) { 38ed35a92cSVlad Serebrennikov case AMDGPU::BI__builtin_amdgcn_global_load_lds: { 39ed35a92cSVlad Serebrennikov constexpr const int SizeIdx = 2; 40ed35a92cSVlad Serebrennikov llvm::APSInt Size; 41ed35a92cSVlad Serebrennikov Expr *ArgExpr = TheCall->getArg(SizeIdx); 4279393124SHaojian Wu [[maybe_unused]] ExprResult R = 4379393124SHaojian Wu SemaRef.VerifyIntegerConstantExpression(ArgExpr, &Size); 44170d45c0SShilei Tian assert(!R.isInvalid()); 45ed35a92cSVlad Serebrennikov switch (Size.getSExtValue()) { 46ed35a92cSVlad Serebrennikov case 1: 47ed35a92cSVlad Serebrennikov case 2: 48ed35a92cSVlad Serebrennikov case 4: 49ed35a92cSVlad Serebrennikov return false; 50*a2c3e0c4SMatt Arsenault case 12: 51*a2c3e0c4SMatt Arsenault case 16: { 52*a2c3e0c4SMatt Arsenault if (HasGFX950Insts) 53*a2c3e0c4SMatt Arsenault return false; 54*a2c3e0c4SMatt Arsenault [[fallthrough]]; 55*a2c3e0c4SMatt Arsenault } 56ed35a92cSVlad Serebrennikov default: 57ed35a92cSVlad Serebrennikov Diag(ArgExpr->getExprLoc(), 58ed35a92cSVlad Serebrennikov diag::err_amdgcn_global_load_lds_size_invalid_value) 59ed35a92cSVlad Serebrennikov << ArgExpr->getSourceRange(); 60ed35a92cSVlad Serebrennikov Diag(ArgExpr->getExprLoc(), 61ed35a92cSVlad Serebrennikov diag::note_amdgcn_global_load_lds_size_valid_value) 62*a2c3e0c4SMatt Arsenault << HasGFX950Insts << ArgExpr->getSourceRange(); 63ed35a92cSVlad Serebrennikov return true; 64ed35a92cSVlad Serebrennikov } 65ed35a92cSVlad Serebrennikov } 66ed35a92cSVlad Serebrennikov case AMDGPU::BI__builtin_amdgcn_get_fpenv: 67ed35a92cSVlad Serebrennikov case AMDGPU::BI__builtin_amdgcn_set_fpenv: 68ed35a92cSVlad Serebrennikov return false; 69ed35a92cSVlad Serebrennikov case AMDGPU::BI__builtin_amdgcn_atomic_inc32: 70ed35a92cSVlad Serebrennikov case AMDGPU::BI__builtin_amdgcn_atomic_inc64: 71ed35a92cSVlad Serebrennikov case AMDGPU::BI__builtin_amdgcn_atomic_dec32: 72ed35a92cSVlad Serebrennikov case AMDGPU::BI__builtin_amdgcn_atomic_dec64: 73ed35a92cSVlad Serebrennikov OrderIndex = 2; 74ed35a92cSVlad Serebrennikov ScopeIndex = 3; 75ed35a92cSVlad Serebrennikov break; 76ed35a92cSVlad Serebrennikov case AMDGPU::BI__builtin_amdgcn_fence: 77ed35a92cSVlad Serebrennikov OrderIndex = 0; 78ed35a92cSVlad Serebrennikov ScopeIndex = 1; 79ed35a92cSVlad Serebrennikov break; 80ba1a09daSStanislav Mekhanoshin case AMDGPU::BI__builtin_amdgcn_mov_dpp: 81ba1a09daSStanislav Mekhanoshin return checkMovDPPFunctionCall(TheCall, 5, 1); 82ba1a09daSStanislav Mekhanoshin case AMDGPU::BI__builtin_amdgcn_mov_dpp8: 83ba1a09daSStanislav Mekhanoshin return checkMovDPPFunctionCall(TheCall, 2, 1); 84622e398dSStanislav Mekhanoshin case AMDGPU::BI__builtin_amdgcn_update_dpp: { 85ba1a09daSStanislav Mekhanoshin return checkMovDPPFunctionCall(TheCall, 6, 2); 86622e398dSStanislav Mekhanoshin } 87ed35a92cSVlad Serebrennikov default: 88ed35a92cSVlad Serebrennikov return false; 89ed35a92cSVlad Serebrennikov } 90ed35a92cSVlad Serebrennikov 91ed35a92cSVlad Serebrennikov ExprResult Arg = TheCall->getArg(OrderIndex); 92ed35a92cSVlad Serebrennikov auto ArgExpr = Arg.get(); 93ed35a92cSVlad Serebrennikov Expr::EvalResult ArgResult; 94ed35a92cSVlad Serebrennikov 95ed35a92cSVlad Serebrennikov if (!ArgExpr->EvaluateAsInt(ArgResult, getASTContext())) 96ed35a92cSVlad Serebrennikov return Diag(ArgExpr->getExprLoc(), diag::err_typecheck_expect_int) 97ed35a92cSVlad Serebrennikov << ArgExpr->getType(); 98ed35a92cSVlad Serebrennikov auto Ord = ArgResult.Val.getInt().getZExtValue(); 99ed35a92cSVlad Serebrennikov 100ed35a92cSVlad Serebrennikov // Check validity of memory ordering as per C11 / C++11's memody model. 101ed35a92cSVlad Serebrennikov // Only fence needs check. Atomic dec/inc allow all memory orders. 102ed35a92cSVlad Serebrennikov if (!llvm::isValidAtomicOrderingCABI(Ord)) 103ed35a92cSVlad Serebrennikov return Diag(ArgExpr->getBeginLoc(), 104ed35a92cSVlad Serebrennikov diag::warn_atomic_op_has_invalid_memory_order) 105ed35a92cSVlad Serebrennikov << 0 << ArgExpr->getSourceRange(); 106ed35a92cSVlad Serebrennikov switch (static_cast<llvm::AtomicOrderingCABI>(Ord)) { 107ed35a92cSVlad Serebrennikov case llvm::AtomicOrderingCABI::relaxed: 108ed35a92cSVlad Serebrennikov case llvm::AtomicOrderingCABI::consume: 109ed35a92cSVlad Serebrennikov if (BuiltinID == AMDGPU::BI__builtin_amdgcn_fence) 110ed35a92cSVlad Serebrennikov return Diag(ArgExpr->getBeginLoc(), 111ed35a92cSVlad Serebrennikov diag::warn_atomic_op_has_invalid_memory_order) 112ed35a92cSVlad Serebrennikov << 0 << ArgExpr->getSourceRange(); 113ed35a92cSVlad Serebrennikov break; 114ed35a92cSVlad Serebrennikov case llvm::AtomicOrderingCABI::acquire: 115ed35a92cSVlad Serebrennikov case llvm::AtomicOrderingCABI::release: 116ed35a92cSVlad Serebrennikov case llvm::AtomicOrderingCABI::acq_rel: 117ed35a92cSVlad Serebrennikov case llvm::AtomicOrderingCABI::seq_cst: 118ed35a92cSVlad Serebrennikov break; 119ed35a92cSVlad Serebrennikov } 120ed35a92cSVlad Serebrennikov 121ed35a92cSVlad Serebrennikov Arg = TheCall->getArg(ScopeIndex); 122ed35a92cSVlad Serebrennikov ArgExpr = Arg.get(); 123ed35a92cSVlad Serebrennikov Expr::EvalResult ArgResult1; 124ed35a92cSVlad Serebrennikov // Check that sync scope is a constant literal 125ed35a92cSVlad Serebrennikov if (!ArgExpr->EvaluateAsConstantExpr(ArgResult1, getASTContext())) 126ed35a92cSVlad Serebrennikov return Diag(ArgExpr->getExprLoc(), diag::err_expr_not_string_literal) 127ed35a92cSVlad Serebrennikov << ArgExpr->getType(); 128ed35a92cSVlad Serebrennikov 129ed35a92cSVlad Serebrennikov return false; 130ed35a92cSVlad Serebrennikov } 131ed35a92cSVlad Serebrennikov 132ba1a09daSStanislav Mekhanoshin bool SemaAMDGPU::checkMovDPPFunctionCall(CallExpr *TheCall, unsigned NumArgs, 133ba1a09daSStanislav Mekhanoshin unsigned NumDataArgs) { 134ba1a09daSStanislav Mekhanoshin assert(NumDataArgs <= 2); 135ba1a09daSStanislav Mekhanoshin if (SemaRef.checkArgCountRange(TheCall, NumArgs, NumArgs)) 136ba1a09daSStanislav Mekhanoshin return true; 137ba1a09daSStanislav Mekhanoshin Expr *Args[2]; 138ba1a09daSStanislav Mekhanoshin QualType ArgTys[2]; 139ba1a09daSStanislav Mekhanoshin for (unsigned I = 0; I != NumDataArgs; ++I) { 140ba1a09daSStanislav Mekhanoshin Args[I] = TheCall->getArg(I); 141ba1a09daSStanislav Mekhanoshin ArgTys[I] = Args[I]->getType(); 142ba1a09daSStanislav Mekhanoshin // TODO: Vectors can also be supported. 143ba1a09daSStanislav Mekhanoshin if (!ArgTys[I]->isArithmeticType() || ArgTys[I]->isAnyComplexType()) { 144ba1a09daSStanislav Mekhanoshin SemaRef.Diag(Args[I]->getBeginLoc(), 145ba1a09daSStanislav Mekhanoshin diag::err_typecheck_cond_expect_int_float) 146ba1a09daSStanislav Mekhanoshin << ArgTys[I] << Args[I]->getSourceRange(); 147ba1a09daSStanislav Mekhanoshin return true; 148ba1a09daSStanislav Mekhanoshin } 149ba1a09daSStanislav Mekhanoshin } 150ba1a09daSStanislav Mekhanoshin if (NumDataArgs < 2) 151ba1a09daSStanislav Mekhanoshin return false; 152ba1a09daSStanislav Mekhanoshin 153ba1a09daSStanislav Mekhanoshin if (getASTContext().hasSameUnqualifiedType(ArgTys[0], ArgTys[1])) 154ba1a09daSStanislav Mekhanoshin return false; 155ba1a09daSStanislav Mekhanoshin 156ba1a09daSStanislav Mekhanoshin if (((ArgTys[0]->isUnsignedIntegerType() && 157ba1a09daSStanislav Mekhanoshin ArgTys[1]->isSignedIntegerType()) || 158ba1a09daSStanislav Mekhanoshin (ArgTys[0]->isSignedIntegerType() && 159ba1a09daSStanislav Mekhanoshin ArgTys[1]->isUnsignedIntegerType())) && 160ba1a09daSStanislav Mekhanoshin getASTContext().getTypeSize(ArgTys[0]) == 161ba1a09daSStanislav Mekhanoshin getASTContext().getTypeSize(ArgTys[1])) 162ba1a09daSStanislav Mekhanoshin return false; 163ba1a09daSStanislav Mekhanoshin 164ba1a09daSStanislav Mekhanoshin SemaRef.Diag(Args[1]->getBeginLoc(), 165ba1a09daSStanislav Mekhanoshin diag::err_typecheck_call_different_arg_types) 166ba1a09daSStanislav Mekhanoshin << ArgTys[0] << ArgTys[1]; 167ba1a09daSStanislav Mekhanoshin return true; 168ba1a09daSStanislav Mekhanoshin } 169ba1a09daSStanislav Mekhanoshin 170ed35a92cSVlad Serebrennikov static bool 171ed35a92cSVlad Serebrennikov checkAMDGPUFlatWorkGroupSizeArguments(Sema &S, Expr *MinExpr, Expr *MaxExpr, 172ed35a92cSVlad Serebrennikov const AMDGPUFlatWorkGroupSizeAttr &Attr) { 173ed35a92cSVlad Serebrennikov // Accept template arguments for now as they depend on something else. 174ed35a92cSVlad Serebrennikov // We'll get to check them when they eventually get instantiated. 175ed35a92cSVlad Serebrennikov if (MinExpr->isValueDependent() || MaxExpr->isValueDependent()) 176ed35a92cSVlad Serebrennikov return false; 177ed35a92cSVlad Serebrennikov 178ed35a92cSVlad Serebrennikov uint32_t Min = 0; 179ed35a92cSVlad Serebrennikov if (!S.checkUInt32Argument(Attr, MinExpr, Min, 0)) 180ed35a92cSVlad Serebrennikov return true; 181ed35a92cSVlad Serebrennikov 182ed35a92cSVlad Serebrennikov uint32_t Max = 0; 183ed35a92cSVlad Serebrennikov if (!S.checkUInt32Argument(Attr, MaxExpr, Max, 1)) 184ed35a92cSVlad Serebrennikov return true; 185ed35a92cSVlad Serebrennikov 186ed35a92cSVlad Serebrennikov if (Min == 0 && Max != 0) { 187ed35a92cSVlad Serebrennikov S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid) 188ed35a92cSVlad Serebrennikov << &Attr << 0; 189ed35a92cSVlad Serebrennikov return true; 190ed35a92cSVlad Serebrennikov } 191ed35a92cSVlad Serebrennikov if (Min > Max) { 192ed35a92cSVlad Serebrennikov S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid) 193ed35a92cSVlad Serebrennikov << &Attr << 1; 194ed35a92cSVlad Serebrennikov return true; 195ed35a92cSVlad Serebrennikov } 196ed35a92cSVlad Serebrennikov 197ed35a92cSVlad Serebrennikov return false; 198ed35a92cSVlad Serebrennikov } 199ed35a92cSVlad Serebrennikov 200ed35a92cSVlad Serebrennikov AMDGPUFlatWorkGroupSizeAttr * 201ed35a92cSVlad Serebrennikov SemaAMDGPU::CreateAMDGPUFlatWorkGroupSizeAttr(const AttributeCommonInfo &CI, 202ed35a92cSVlad Serebrennikov Expr *MinExpr, Expr *MaxExpr) { 203ed35a92cSVlad Serebrennikov ASTContext &Context = getASTContext(); 204ed35a92cSVlad Serebrennikov AMDGPUFlatWorkGroupSizeAttr TmpAttr(Context, CI, MinExpr, MaxExpr); 205ed35a92cSVlad Serebrennikov 206ed35a92cSVlad Serebrennikov if (checkAMDGPUFlatWorkGroupSizeArguments(SemaRef, MinExpr, MaxExpr, TmpAttr)) 207ed35a92cSVlad Serebrennikov return nullptr; 208ed35a92cSVlad Serebrennikov return ::new (Context) 209ed35a92cSVlad Serebrennikov AMDGPUFlatWorkGroupSizeAttr(Context, CI, MinExpr, MaxExpr); 210ed35a92cSVlad Serebrennikov } 211ed35a92cSVlad Serebrennikov 212ed35a92cSVlad Serebrennikov void SemaAMDGPU::addAMDGPUFlatWorkGroupSizeAttr(Decl *D, 213ed35a92cSVlad Serebrennikov const AttributeCommonInfo &CI, 214ed35a92cSVlad Serebrennikov Expr *MinExpr, Expr *MaxExpr) { 215ed35a92cSVlad Serebrennikov if (auto *Attr = CreateAMDGPUFlatWorkGroupSizeAttr(CI, MinExpr, MaxExpr)) 216ed35a92cSVlad Serebrennikov D->addAttr(Attr); 217ed35a92cSVlad Serebrennikov } 218ed35a92cSVlad Serebrennikov 219ed35a92cSVlad Serebrennikov void SemaAMDGPU::handleAMDGPUFlatWorkGroupSizeAttr(Decl *D, 220ed35a92cSVlad Serebrennikov const ParsedAttr &AL) { 221ed35a92cSVlad Serebrennikov Expr *MinExpr = AL.getArgAsExpr(0); 222ed35a92cSVlad Serebrennikov Expr *MaxExpr = AL.getArgAsExpr(1); 223ed35a92cSVlad Serebrennikov 224ed35a92cSVlad Serebrennikov addAMDGPUFlatWorkGroupSizeAttr(D, AL, MinExpr, MaxExpr); 225ed35a92cSVlad Serebrennikov } 226ed35a92cSVlad Serebrennikov 227ed35a92cSVlad Serebrennikov static bool checkAMDGPUWavesPerEUArguments(Sema &S, Expr *MinExpr, 228ed35a92cSVlad Serebrennikov Expr *MaxExpr, 229ed35a92cSVlad Serebrennikov const AMDGPUWavesPerEUAttr &Attr) { 230ed35a92cSVlad Serebrennikov if (S.DiagnoseUnexpandedParameterPack(MinExpr) || 231ed35a92cSVlad Serebrennikov (MaxExpr && S.DiagnoseUnexpandedParameterPack(MaxExpr))) 232ed35a92cSVlad Serebrennikov return true; 233ed35a92cSVlad Serebrennikov 234ed35a92cSVlad Serebrennikov // Accept template arguments for now as they depend on something else. 235ed35a92cSVlad Serebrennikov // We'll get to check them when they eventually get instantiated. 236ed35a92cSVlad Serebrennikov if (MinExpr->isValueDependent() || (MaxExpr && MaxExpr->isValueDependent())) 237ed35a92cSVlad Serebrennikov return false; 238ed35a92cSVlad Serebrennikov 239ed35a92cSVlad Serebrennikov uint32_t Min = 0; 240ed35a92cSVlad Serebrennikov if (!S.checkUInt32Argument(Attr, MinExpr, Min, 0)) 241ed35a92cSVlad Serebrennikov return true; 242ed35a92cSVlad Serebrennikov 243ed35a92cSVlad Serebrennikov uint32_t Max = 0; 244ed35a92cSVlad Serebrennikov if (MaxExpr && !S.checkUInt32Argument(Attr, MaxExpr, Max, 1)) 245ed35a92cSVlad Serebrennikov return true; 246ed35a92cSVlad Serebrennikov 247ed35a92cSVlad Serebrennikov if (Min == 0 && Max != 0) { 248ed35a92cSVlad Serebrennikov S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid) 249ed35a92cSVlad Serebrennikov << &Attr << 0; 250ed35a92cSVlad Serebrennikov return true; 251ed35a92cSVlad Serebrennikov } 252ed35a92cSVlad Serebrennikov if (Max != 0 && Min > Max) { 253ed35a92cSVlad Serebrennikov S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid) 254ed35a92cSVlad Serebrennikov << &Attr << 1; 255ed35a92cSVlad Serebrennikov return true; 256ed35a92cSVlad Serebrennikov } 257ed35a92cSVlad Serebrennikov 258ed35a92cSVlad Serebrennikov return false; 259ed35a92cSVlad Serebrennikov } 260ed35a92cSVlad Serebrennikov 261ed35a92cSVlad Serebrennikov AMDGPUWavesPerEUAttr * 262ed35a92cSVlad Serebrennikov SemaAMDGPU::CreateAMDGPUWavesPerEUAttr(const AttributeCommonInfo &CI, 263ed35a92cSVlad Serebrennikov Expr *MinExpr, Expr *MaxExpr) { 264ed35a92cSVlad Serebrennikov ASTContext &Context = getASTContext(); 265ed35a92cSVlad Serebrennikov AMDGPUWavesPerEUAttr TmpAttr(Context, CI, MinExpr, MaxExpr); 266ed35a92cSVlad Serebrennikov 267ed35a92cSVlad Serebrennikov if (checkAMDGPUWavesPerEUArguments(SemaRef, MinExpr, MaxExpr, TmpAttr)) 268ed35a92cSVlad Serebrennikov return nullptr; 269ed35a92cSVlad Serebrennikov 270ed35a92cSVlad Serebrennikov return ::new (Context) AMDGPUWavesPerEUAttr(Context, CI, MinExpr, MaxExpr); 271ed35a92cSVlad Serebrennikov } 272ed35a92cSVlad Serebrennikov 273ed35a92cSVlad Serebrennikov void SemaAMDGPU::addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI, 274ed35a92cSVlad Serebrennikov Expr *MinExpr, Expr *MaxExpr) { 275ed35a92cSVlad Serebrennikov if (auto *Attr = CreateAMDGPUWavesPerEUAttr(CI, MinExpr, MaxExpr)) 276ed35a92cSVlad Serebrennikov D->addAttr(Attr); 277ed35a92cSVlad Serebrennikov } 278ed35a92cSVlad Serebrennikov 279ed35a92cSVlad Serebrennikov void SemaAMDGPU::handleAMDGPUWavesPerEUAttr(Decl *D, const ParsedAttr &AL) { 280ed35a92cSVlad Serebrennikov if (!AL.checkAtLeastNumArgs(SemaRef, 1) || !AL.checkAtMostNumArgs(SemaRef, 2)) 281ed35a92cSVlad Serebrennikov return; 282ed35a92cSVlad Serebrennikov 283ed35a92cSVlad Serebrennikov Expr *MinExpr = AL.getArgAsExpr(0); 284ed35a92cSVlad Serebrennikov Expr *MaxExpr = (AL.getNumArgs() > 1) ? AL.getArgAsExpr(1) : nullptr; 285ed35a92cSVlad Serebrennikov 286ed35a92cSVlad Serebrennikov addAMDGPUWavesPerEUAttr(D, AL, MinExpr, MaxExpr); 287ed35a92cSVlad Serebrennikov } 288ed35a92cSVlad Serebrennikov 289ed35a92cSVlad Serebrennikov void SemaAMDGPU::handleAMDGPUNumSGPRAttr(Decl *D, const ParsedAttr &AL) { 290ed35a92cSVlad Serebrennikov uint32_t NumSGPR = 0; 291ed35a92cSVlad Serebrennikov Expr *NumSGPRExpr = AL.getArgAsExpr(0); 292ed35a92cSVlad Serebrennikov if (!SemaRef.checkUInt32Argument(AL, NumSGPRExpr, NumSGPR)) 293ed35a92cSVlad Serebrennikov return; 294ed35a92cSVlad Serebrennikov 295ed35a92cSVlad Serebrennikov D->addAttr(::new (getASTContext()) 296ed35a92cSVlad Serebrennikov AMDGPUNumSGPRAttr(getASTContext(), AL, NumSGPR)); 297ed35a92cSVlad Serebrennikov } 298ed35a92cSVlad Serebrennikov 299ed35a92cSVlad Serebrennikov void SemaAMDGPU::handleAMDGPUNumVGPRAttr(Decl *D, const ParsedAttr &AL) { 300ed35a92cSVlad Serebrennikov uint32_t NumVGPR = 0; 301ed35a92cSVlad Serebrennikov Expr *NumVGPRExpr = AL.getArgAsExpr(0); 302ed35a92cSVlad Serebrennikov if (!SemaRef.checkUInt32Argument(AL, NumVGPRExpr, NumVGPR)) 303ed35a92cSVlad Serebrennikov return; 304ed35a92cSVlad Serebrennikov 305ed35a92cSVlad Serebrennikov D->addAttr(::new (getASTContext()) 306ed35a92cSVlad Serebrennikov AMDGPUNumVGPRAttr(getASTContext(), AL, NumVGPR)); 307ed35a92cSVlad Serebrennikov } 308ed35a92cSVlad Serebrennikov 309ed35a92cSVlad Serebrennikov static bool 310ed35a92cSVlad Serebrennikov checkAMDGPUMaxNumWorkGroupsArguments(Sema &S, Expr *XExpr, Expr *YExpr, 311ed35a92cSVlad Serebrennikov Expr *ZExpr, 312ed35a92cSVlad Serebrennikov const AMDGPUMaxNumWorkGroupsAttr &Attr) { 313ed35a92cSVlad Serebrennikov if (S.DiagnoseUnexpandedParameterPack(XExpr) || 314ed35a92cSVlad Serebrennikov (YExpr && S.DiagnoseUnexpandedParameterPack(YExpr)) || 315ed35a92cSVlad Serebrennikov (ZExpr && S.DiagnoseUnexpandedParameterPack(ZExpr))) 316ed35a92cSVlad Serebrennikov return true; 317ed35a92cSVlad Serebrennikov 318ed35a92cSVlad Serebrennikov // Accept template arguments for now as they depend on something else. 319ed35a92cSVlad Serebrennikov // We'll get to check them when they eventually get instantiated. 320ed35a92cSVlad Serebrennikov if (XExpr->isValueDependent() || (YExpr && YExpr->isValueDependent()) || 321ed35a92cSVlad Serebrennikov (ZExpr && ZExpr->isValueDependent())) 322ed35a92cSVlad Serebrennikov return false; 323ed35a92cSVlad Serebrennikov 324ed35a92cSVlad Serebrennikov uint32_t NumWG = 0; 325ed35a92cSVlad Serebrennikov Expr *Exprs[3] = {XExpr, YExpr, ZExpr}; 326ed35a92cSVlad Serebrennikov for (int i = 0; i < 3; i++) { 327ed35a92cSVlad Serebrennikov if (Exprs[i]) { 328ed35a92cSVlad Serebrennikov if (!S.checkUInt32Argument(Attr, Exprs[i], NumWG, i, 329ed35a92cSVlad Serebrennikov /*StrictlyUnsigned=*/true)) 330ed35a92cSVlad Serebrennikov return true; 331ed35a92cSVlad Serebrennikov if (NumWG == 0) { 332ed35a92cSVlad Serebrennikov S.Diag(Attr.getLoc(), diag::err_attribute_argument_is_zero) 333ed35a92cSVlad Serebrennikov << &Attr << Exprs[i]->getSourceRange(); 334ed35a92cSVlad Serebrennikov return true; 335ed35a92cSVlad Serebrennikov } 336ed35a92cSVlad Serebrennikov } 337ed35a92cSVlad Serebrennikov } 338ed35a92cSVlad Serebrennikov 339ed35a92cSVlad Serebrennikov return false; 340ed35a92cSVlad Serebrennikov } 341ed35a92cSVlad Serebrennikov 342ed35a92cSVlad Serebrennikov AMDGPUMaxNumWorkGroupsAttr *SemaAMDGPU::CreateAMDGPUMaxNumWorkGroupsAttr( 343ed35a92cSVlad Serebrennikov const AttributeCommonInfo &CI, Expr *XExpr, Expr *YExpr, Expr *ZExpr) { 344ed35a92cSVlad Serebrennikov ASTContext &Context = getASTContext(); 345ed35a92cSVlad Serebrennikov AMDGPUMaxNumWorkGroupsAttr TmpAttr(Context, CI, XExpr, YExpr, ZExpr); 346ed35a92cSVlad Serebrennikov 347ed35a92cSVlad Serebrennikov if (checkAMDGPUMaxNumWorkGroupsArguments(SemaRef, XExpr, YExpr, ZExpr, 348ed35a92cSVlad Serebrennikov TmpAttr)) 349ed35a92cSVlad Serebrennikov return nullptr; 350ed35a92cSVlad Serebrennikov 351ed35a92cSVlad Serebrennikov return ::new (Context) 352ed35a92cSVlad Serebrennikov AMDGPUMaxNumWorkGroupsAttr(Context, CI, XExpr, YExpr, ZExpr); 353ed35a92cSVlad Serebrennikov } 354ed35a92cSVlad Serebrennikov 355ed35a92cSVlad Serebrennikov void SemaAMDGPU::addAMDGPUMaxNumWorkGroupsAttr(Decl *D, 356ed35a92cSVlad Serebrennikov const AttributeCommonInfo &CI, 357ed35a92cSVlad Serebrennikov Expr *XExpr, Expr *YExpr, 358ed35a92cSVlad Serebrennikov Expr *ZExpr) { 359ed35a92cSVlad Serebrennikov if (auto *Attr = CreateAMDGPUMaxNumWorkGroupsAttr(CI, XExpr, YExpr, ZExpr)) 360ed35a92cSVlad Serebrennikov D->addAttr(Attr); 361ed35a92cSVlad Serebrennikov } 362ed35a92cSVlad Serebrennikov 363ed35a92cSVlad Serebrennikov void SemaAMDGPU::handleAMDGPUMaxNumWorkGroupsAttr(Decl *D, 364ed35a92cSVlad Serebrennikov const ParsedAttr &AL) { 365ed35a92cSVlad Serebrennikov Expr *YExpr = (AL.getNumArgs() > 1) ? AL.getArgAsExpr(1) : nullptr; 366ed35a92cSVlad Serebrennikov Expr *ZExpr = (AL.getNumArgs() > 2) ? AL.getArgAsExpr(2) : nullptr; 367ed35a92cSVlad Serebrennikov addAMDGPUMaxNumWorkGroupsAttr(D, AL, AL.getArgAsExpr(0), YExpr, ZExpr); 368ed35a92cSVlad Serebrennikov } 369ed35a92cSVlad Serebrennikov 370ed35a92cSVlad Serebrennikov } // namespace clang 371