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