xref: /llvm-project/clang/lib/Sema/SemaOpenCL.cpp (revision f1c54d72104cb163120c6ab65587766b12e7d959)
16b755b0cSVlad Serebrennikov //===--- SemaOpenCL.cpp --- Semantic Analysis for OpenCL constructs -------===//
26b755b0cSVlad Serebrennikov //
36b755b0cSVlad Serebrennikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
46b755b0cSVlad Serebrennikov // See https://llvm.org/LICENSE.txt for license information.
56b755b0cSVlad Serebrennikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66b755b0cSVlad Serebrennikov //
76b755b0cSVlad Serebrennikov //===----------------------------------------------------------------------===//
86b755b0cSVlad Serebrennikov /// \file
96b755b0cSVlad Serebrennikov /// This file implements semantic analysis for OpenCL.
106b755b0cSVlad Serebrennikov ///
116b755b0cSVlad Serebrennikov //===----------------------------------------------------------------------===//
126b755b0cSVlad Serebrennikov 
136b755b0cSVlad Serebrennikov #include "clang/Sema/SemaOpenCL.h"
146b755b0cSVlad Serebrennikov #include "clang/AST/Attr.h"
156b755b0cSVlad Serebrennikov #include "clang/AST/DeclBase.h"
166b755b0cSVlad Serebrennikov #include "clang/Basic/DiagnosticSema.h"
176b755b0cSVlad Serebrennikov #include "clang/Sema/ParsedAttr.h"
186b755b0cSVlad Serebrennikov #include "clang/Sema/Sema.h"
196b755b0cSVlad Serebrennikov 
206b755b0cSVlad Serebrennikov namespace clang {
SemaOpenCL(Sema & S)216b755b0cSVlad Serebrennikov SemaOpenCL::SemaOpenCL(Sema &S) : SemaBase(S) {}
226b755b0cSVlad Serebrennikov 
handleNoSVMAttr(Decl * D,const ParsedAttr & AL)236b755b0cSVlad Serebrennikov void SemaOpenCL::handleNoSVMAttr(Decl *D, const ParsedAttr &AL) {
246b755b0cSVlad Serebrennikov   if (getLangOpts().getOpenCLCompatibleVersion() < 200)
256b755b0cSVlad Serebrennikov     Diag(AL.getLoc(), diag::err_attribute_requires_opencl_version)
266b755b0cSVlad Serebrennikov         << AL << "2.0" << 1;
276b755b0cSVlad Serebrennikov   else
286b755b0cSVlad Serebrennikov     Diag(AL.getLoc(), diag::warn_opencl_attr_deprecated_ignored)
296b755b0cSVlad Serebrennikov         << AL << getLangOpts().getOpenCLVersionString();
306b755b0cSVlad Serebrennikov }
316b755b0cSVlad Serebrennikov 
handleAccessAttr(Decl * D,const ParsedAttr & AL)326b755b0cSVlad Serebrennikov void SemaOpenCL::handleAccessAttr(Decl *D, const ParsedAttr &AL) {
336b755b0cSVlad Serebrennikov   if (D->isInvalidDecl())
346b755b0cSVlad Serebrennikov     return;
356b755b0cSVlad Serebrennikov 
366b755b0cSVlad Serebrennikov   // Check if there is only one access qualifier.
376b755b0cSVlad Serebrennikov   if (D->hasAttr<OpenCLAccessAttr>()) {
386b755b0cSVlad Serebrennikov     if (D->getAttr<OpenCLAccessAttr>()->getSemanticSpelling() ==
396b755b0cSVlad Serebrennikov         AL.getSemanticSpelling()) {
406b755b0cSVlad Serebrennikov       Diag(AL.getLoc(), diag::warn_duplicate_declspec)
416b755b0cSVlad Serebrennikov           << AL.getAttrName()->getName() << AL.getRange();
426b755b0cSVlad Serebrennikov     } else {
436b755b0cSVlad Serebrennikov       Diag(AL.getLoc(), diag::err_opencl_multiple_access_qualifiers)
446b755b0cSVlad Serebrennikov           << D->getSourceRange();
456b755b0cSVlad Serebrennikov       D->setInvalidDecl(true);
466b755b0cSVlad Serebrennikov       return;
476b755b0cSVlad Serebrennikov     }
486b755b0cSVlad Serebrennikov   }
496b755b0cSVlad Serebrennikov 
506b755b0cSVlad Serebrennikov   // OpenCL v2.0 s6.6 - read_write can be used for image types to specify that
516b755b0cSVlad Serebrennikov   // an image object can be read and written. OpenCL v2.0 s6.13.6 - A kernel
526b755b0cSVlad Serebrennikov   // cannot read from and write to the same pipe object. Using the read_write
536b755b0cSVlad Serebrennikov   // (or __read_write) qualifier with the pipe qualifier is a compilation error.
546b755b0cSVlad Serebrennikov   // OpenCL v3.0 s6.8 - For OpenCL C 2.0, or with the
556b755b0cSVlad Serebrennikov   // __opencl_c_read_write_images feature, image objects specified as arguments
566b755b0cSVlad Serebrennikov   // to a kernel can additionally be declared to be read-write.
576b755b0cSVlad Serebrennikov   // C++ for OpenCL 1.0 inherits rule from OpenCL C v2.0.
586b755b0cSVlad Serebrennikov   // C++ for OpenCL 2021 inherits rule from OpenCL C v3.0.
596b755b0cSVlad Serebrennikov   if (const auto *PDecl = dyn_cast<ParmVarDecl>(D)) {
606b755b0cSVlad Serebrennikov     const Type *DeclTy = PDecl->getType().getCanonicalType().getTypePtr();
616b755b0cSVlad Serebrennikov     if (AL.getAttrName()->getName().contains("read_write")) {
626b755b0cSVlad Serebrennikov       bool ReadWriteImagesUnsupported =
636b755b0cSVlad Serebrennikov           (getLangOpts().getOpenCLCompatibleVersion() < 200) ||
646b755b0cSVlad Serebrennikov           (getLangOpts().getOpenCLCompatibleVersion() == 300 &&
656b755b0cSVlad Serebrennikov            !SemaRef.getOpenCLOptions().isSupported(
666b755b0cSVlad Serebrennikov                "__opencl_c_read_write_images", getLangOpts()));
676b755b0cSVlad Serebrennikov       if (ReadWriteImagesUnsupported || DeclTy->isPipeType()) {
686b755b0cSVlad Serebrennikov         Diag(AL.getLoc(), diag::err_opencl_invalid_read_write)
696b755b0cSVlad Serebrennikov             << AL << PDecl->getType() << DeclTy->isImageType();
706b755b0cSVlad Serebrennikov         D->setInvalidDecl(true);
716b755b0cSVlad Serebrennikov         return;
726b755b0cSVlad Serebrennikov       }
736b755b0cSVlad Serebrennikov     }
746b755b0cSVlad Serebrennikov   }
756b755b0cSVlad Serebrennikov 
766b755b0cSVlad Serebrennikov   D->addAttr(::new (getASTContext()) OpenCLAccessAttr(getASTContext(), AL));
776b755b0cSVlad Serebrennikov }
786b755b0cSVlad Serebrennikov 
handleSubGroupSize(Decl * D,const ParsedAttr & AL)796b755b0cSVlad Serebrennikov void SemaOpenCL::handleSubGroupSize(Decl *D, const ParsedAttr &AL) {
806b755b0cSVlad Serebrennikov   uint32_t SGSize;
816b755b0cSVlad Serebrennikov   const Expr *E = AL.getArgAsExpr(0);
826b755b0cSVlad Serebrennikov   if (!SemaRef.checkUInt32Argument(AL, E, SGSize))
836b755b0cSVlad Serebrennikov     return;
846b755b0cSVlad Serebrennikov   if (SGSize == 0) {
856b755b0cSVlad Serebrennikov     Diag(AL.getLoc(), diag::err_attribute_argument_is_zero)
866b755b0cSVlad Serebrennikov         << AL << E->getSourceRange();
876b755b0cSVlad Serebrennikov     return;
886b755b0cSVlad Serebrennikov   }
896b755b0cSVlad Serebrennikov 
906b755b0cSVlad Serebrennikov   OpenCLIntelReqdSubGroupSizeAttr *Existing =
916b755b0cSVlad Serebrennikov       D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>();
926b755b0cSVlad Serebrennikov   if (Existing && Existing->getSubGroupSize() != SGSize)
936b755b0cSVlad Serebrennikov     Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
946b755b0cSVlad Serebrennikov 
956b755b0cSVlad Serebrennikov   D->addAttr(::new (getASTContext())
966b755b0cSVlad Serebrennikov                  OpenCLIntelReqdSubGroupSizeAttr(getASTContext(), AL, SGSize));
976b755b0cSVlad Serebrennikov }
986b755b0cSVlad Serebrennikov 
isBlockPointer(Expr * Arg)99*f1c54d72SVlad Serebrennikov static inline bool isBlockPointer(Expr *Arg) {
100*f1c54d72SVlad Serebrennikov   return Arg->getType()->isBlockPointerType();
101*f1c54d72SVlad Serebrennikov }
102*f1c54d72SVlad Serebrennikov 
103*f1c54d72SVlad Serebrennikov /// OpenCL C v2.0, s6.13.17.2 - Checks that the block parameters are all local
104*f1c54d72SVlad Serebrennikov /// void*, which is a requirement of device side enqueue.
checkBlockArgs(Sema & S,Expr * BlockArg)105*f1c54d72SVlad Serebrennikov static bool checkBlockArgs(Sema &S, Expr *BlockArg) {
106*f1c54d72SVlad Serebrennikov   const BlockPointerType *BPT =
107*f1c54d72SVlad Serebrennikov       cast<BlockPointerType>(BlockArg->getType().getCanonicalType());
108*f1c54d72SVlad Serebrennikov   ArrayRef<QualType> Params =
109*f1c54d72SVlad Serebrennikov       BPT->getPointeeType()->castAs<FunctionProtoType>()->getParamTypes();
110*f1c54d72SVlad Serebrennikov   unsigned ArgCounter = 0;
111*f1c54d72SVlad Serebrennikov   bool IllegalParams = false;
112*f1c54d72SVlad Serebrennikov   // Iterate through the block parameters until either one is found that is not
113*f1c54d72SVlad Serebrennikov   // a local void*, or the block is valid.
114*f1c54d72SVlad Serebrennikov   for (ArrayRef<QualType>::iterator I = Params.begin(), E = Params.end();
115*f1c54d72SVlad Serebrennikov        I != E; ++I, ++ArgCounter) {
116*f1c54d72SVlad Serebrennikov     if (!(*I)->isPointerType() || !(*I)->getPointeeType()->isVoidType() ||
117*f1c54d72SVlad Serebrennikov         (*I)->getPointeeType().getQualifiers().getAddressSpace() !=
118*f1c54d72SVlad Serebrennikov             LangAS::opencl_local) {
119*f1c54d72SVlad Serebrennikov       // Get the location of the error. If a block literal has been passed
120*f1c54d72SVlad Serebrennikov       // (BlockExpr) then we can point straight to the offending argument,
121*f1c54d72SVlad Serebrennikov       // else we just point to the variable reference.
122*f1c54d72SVlad Serebrennikov       SourceLocation ErrorLoc;
123*f1c54d72SVlad Serebrennikov       if (isa<BlockExpr>(BlockArg)) {
124*f1c54d72SVlad Serebrennikov         BlockDecl *BD = cast<BlockExpr>(BlockArg)->getBlockDecl();
125*f1c54d72SVlad Serebrennikov         ErrorLoc = BD->getParamDecl(ArgCounter)->getBeginLoc();
126*f1c54d72SVlad Serebrennikov       } else if (isa<DeclRefExpr>(BlockArg)) {
127*f1c54d72SVlad Serebrennikov         ErrorLoc = cast<DeclRefExpr>(BlockArg)->getBeginLoc();
128*f1c54d72SVlad Serebrennikov       }
129*f1c54d72SVlad Serebrennikov       S.Diag(ErrorLoc,
130*f1c54d72SVlad Serebrennikov              diag::err_opencl_enqueue_kernel_blocks_non_local_void_args);
131*f1c54d72SVlad Serebrennikov       IllegalParams = true;
132*f1c54d72SVlad Serebrennikov     }
133*f1c54d72SVlad Serebrennikov   }
134*f1c54d72SVlad Serebrennikov 
135*f1c54d72SVlad Serebrennikov   return IllegalParams;
136*f1c54d72SVlad Serebrennikov }
137*f1c54d72SVlad Serebrennikov 
checkSubgroupExt(CallExpr * Call)138*f1c54d72SVlad Serebrennikov bool SemaOpenCL::checkSubgroupExt(CallExpr *Call) {
139*f1c54d72SVlad Serebrennikov   // OpenCL device can support extension but not the feature as extension
140*f1c54d72SVlad Serebrennikov   // requires subgroup independent forward progress, but subgroup independent
141*f1c54d72SVlad Serebrennikov   // forward progress is optional in OpenCL C 3.0 __opencl_c_subgroups feature.
142*f1c54d72SVlad Serebrennikov   if (!SemaRef.getOpenCLOptions().isSupported("cl_khr_subgroups",
143*f1c54d72SVlad Serebrennikov                                               getLangOpts()) &&
144*f1c54d72SVlad Serebrennikov       !SemaRef.getOpenCLOptions().isSupported("__opencl_c_subgroups",
145*f1c54d72SVlad Serebrennikov                                               getLangOpts())) {
146*f1c54d72SVlad Serebrennikov     Diag(Call->getBeginLoc(), diag::err_opencl_requires_extension)
147*f1c54d72SVlad Serebrennikov         << 1 << Call->getDirectCallee()
148*f1c54d72SVlad Serebrennikov         << "cl_khr_subgroups or __opencl_c_subgroups";
149*f1c54d72SVlad Serebrennikov     return true;
150*f1c54d72SVlad Serebrennikov   }
151*f1c54d72SVlad Serebrennikov   return false;
152*f1c54d72SVlad Serebrennikov }
153*f1c54d72SVlad Serebrennikov 
checkBuiltinNDRangeAndBlock(CallExpr * TheCall)154*f1c54d72SVlad Serebrennikov bool SemaOpenCL::checkBuiltinNDRangeAndBlock(CallExpr *TheCall) {
155*f1c54d72SVlad Serebrennikov   if (SemaRef.checkArgCount(TheCall, 2))
156*f1c54d72SVlad Serebrennikov     return true;
157*f1c54d72SVlad Serebrennikov 
158*f1c54d72SVlad Serebrennikov   if (checkSubgroupExt(TheCall))
159*f1c54d72SVlad Serebrennikov     return true;
160*f1c54d72SVlad Serebrennikov 
161*f1c54d72SVlad Serebrennikov   // First argument is an ndrange_t type.
162*f1c54d72SVlad Serebrennikov   Expr *NDRangeArg = TheCall->getArg(0);
163*f1c54d72SVlad Serebrennikov   if (NDRangeArg->getType().getUnqualifiedType().getAsString() != "ndrange_t") {
164*f1c54d72SVlad Serebrennikov     Diag(NDRangeArg->getBeginLoc(), diag::err_opencl_builtin_expected_type)
165*f1c54d72SVlad Serebrennikov         << TheCall->getDirectCallee() << "'ndrange_t'";
166*f1c54d72SVlad Serebrennikov     return true;
167*f1c54d72SVlad Serebrennikov   }
168*f1c54d72SVlad Serebrennikov 
169*f1c54d72SVlad Serebrennikov   Expr *BlockArg = TheCall->getArg(1);
170*f1c54d72SVlad Serebrennikov   if (!isBlockPointer(BlockArg)) {
171*f1c54d72SVlad Serebrennikov     Diag(BlockArg->getBeginLoc(), diag::err_opencl_builtin_expected_type)
172*f1c54d72SVlad Serebrennikov         << TheCall->getDirectCallee() << "block";
173*f1c54d72SVlad Serebrennikov     return true;
174*f1c54d72SVlad Serebrennikov   }
175*f1c54d72SVlad Serebrennikov   return checkBlockArgs(SemaRef, BlockArg);
176*f1c54d72SVlad Serebrennikov }
177*f1c54d72SVlad Serebrennikov 
checkBuiltinKernelWorkGroupSize(CallExpr * TheCall)178*f1c54d72SVlad Serebrennikov bool SemaOpenCL::checkBuiltinKernelWorkGroupSize(CallExpr *TheCall) {
179*f1c54d72SVlad Serebrennikov   if (SemaRef.checkArgCount(TheCall, 1))
180*f1c54d72SVlad Serebrennikov     return true;
181*f1c54d72SVlad Serebrennikov 
182*f1c54d72SVlad Serebrennikov   Expr *BlockArg = TheCall->getArg(0);
183*f1c54d72SVlad Serebrennikov   if (!isBlockPointer(BlockArg)) {
184*f1c54d72SVlad Serebrennikov     Diag(BlockArg->getBeginLoc(), diag::err_opencl_builtin_expected_type)
185*f1c54d72SVlad Serebrennikov         << TheCall->getDirectCallee() << "block";
186*f1c54d72SVlad Serebrennikov     return true;
187*f1c54d72SVlad Serebrennikov   }
188*f1c54d72SVlad Serebrennikov   return checkBlockArgs(SemaRef, BlockArg);
189*f1c54d72SVlad Serebrennikov }
190*f1c54d72SVlad Serebrennikov 
191*f1c54d72SVlad Serebrennikov /// Diagnose integer type and any valid implicit conversion to it.
checkOpenCLEnqueueIntType(Sema & S,Expr * E,const QualType & IntT)192*f1c54d72SVlad Serebrennikov static bool checkOpenCLEnqueueIntType(Sema &S, Expr *E, const QualType &IntT) {
193*f1c54d72SVlad Serebrennikov   // Taking into account implicit conversions,
194*f1c54d72SVlad Serebrennikov   // allow any integer.
195*f1c54d72SVlad Serebrennikov   if (!E->getType()->isIntegerType()) {
196*f1c54d72SVlad Serebrennikov     S.Diag(E->getBeginLoc(),
197*f1c54d72SVlad Serebrennikov            diag::err_opencl_enqueue_kernel_invalid_local_size_type);
198*f1c54d72SVlad Serebrennikov     return true;
199*f1c54d72SVlad Serebrennikov   }
200*f1c54d72SVlad Serebrennikov   // Potentially emit standard warnings for implicit conversions if enabled
201*f1c54d72SVlad Serebrennikov   // using -Wconversion.
202*f1c54d72SVlad Serebrennikov   S.CheckImplicitConversion(E, IntT, E->getBeginLoc());
203*f1c54d72SVlad Serebrennikov   return false;
204*f1c54d72SVlad Serebrennikov }
205*f1c54d72SVlad Serebrennikov 
checkOpenCLEnqueueLocalSizeArgs(Sema & S,CallExpr * TheCall,unsigned Start,unsigned End)206*f1c54d72SVlad Serebrennikov static bool checkOpenCLEnqueueLocalSizeArgs(Sema &S, CallExpr *TheCall,
207*f1c54d72SVlad Serebrennikov                                             unsigned Start, unsigned End) {
208*f1c54d72SVlad Serebrennikov   bool IllegalParams = false;
209*f1c54d72SVlad Serebrennikov   for (unsigned I = Start; I <= End; ++I)
210*f1c54d72SVlad Serebrennikov     IllegalParams |= checkOpenCLEnqueueIntType(S, TheCall->getArg(I),
211*f1c54d72SVlad Serebrennikov                                                S.Context.getSizeType());
212*f1c54d72SVlad Serebrennikov   return IllegalParams;
213*f1c54d72SVlad Serebrennikov }
214*f1c54d72SVlad Serebrennikov 
215*f1c54d72SVlad Serebrennikov /// OpenCL v2.0, s6.13.17.1 - Check that sizes are provided for all
216*f1c54d72SVlad Serebrennikov /// 'local void*' parameter of passed block.
checkOpenCLEnqueueVariadicArgs(Sema & S,CallExpr * TheCall,Expr * BlockArg,unsigned NumNonVarArgs)217*f1c54d72SVlad Serebrennikov static bool checkOpenCLEnqueueVariadicArgs(Sema &S, CallExpr *TheCall,
218*f1c54d72SVlad Serebrennikov                                            Expr *BlockArg,
219*f1c54d72SVlad Serebrennikov                                            unsigned NumNonVarArgs) {
220*f1c54d72SVlad Serebrennikov   const BlockPointerType *BPT =
221*f1c54d72SVlad Serebrennikov       cast<BlockPointerType>(BlockArg->getType().getCanonicalType());
222*f1c54d72SVlad Serebrennikov   unsigned NumBlockParams =
223*f1c54d72SVlad Serebrennikov       BPT->getPointeeType()->castAs<FunctionProtoType>()->getNumParams();
224*f1c54d72SVlad Serebrennikov   unsigned TotalNumArgs = TheCall->getNumArgs();
225*f1c54d72SVlad Serebrennikov 
226*f1c54d72SVlad Serebrennikov   // For each argument passed to the block, a corresponding uint needs to
227*f1c54d72SVlad Serebrennikov   // be passed to describe the size of the local memory.
228*f1c54d72SVlad Serebrennikov   if (TotalNumArgs != NumBlockParams + NumNonVarArgs) {
229*f1c54d72SVlad Serebrennikov     S.Diag(TheCall->getBeginLoc(),
230*f1c54d72SVlad Serebrennikov            diag::err_opencl_enqueue_kernel_local_size_args);
231*f1c54d72SVlad Serebrennikov     return true;
232*f1c54d72SVlad Serebrennikov   }
233*f1c54d72SVlad Serebrennikov 
234*f1c54d72SVlad Serebrennikov   // Check that the sizes of the local memory are specified by integers.
235*f1c54d72SVlad Serebrennikov   return checkOpenCLEnqueueLocalSizeArgs(S, TheCall, NumNonVarArgs,
236*f1c54d72SVlad Serebrennikov                                          TotalNumArgs - 1);
237*f1c54d72SVlad Serebrennikov }
238*f1c54d72SVlad Serebrennikov 
checkBuiltinEnqueueKernel(CallExpr * TheCall)239*f1c54d72SVlad Serebrennikov bool SemaOpenCL::checkBuiltinEnqueueKernel(CallExpr *TheCall) {
240*f1c54d72SVlad Serebrennikov   ASTContext &Context = getASTContext();
241*f1c54d72SVlad Serebrennikov   unsigned NumArgs = TheCall->getNumArgs();
242*f1c54d72SVlad Serebrennikov 
243*f1c54d72SVlad Serebrennikov   if (NumArgs < 4) {
244*f1c54d72SVlad Serebrennikov     Diag(TheCall->getBeginLoc(), diag::err_typecheck_call_too_few_args_at_least)
245*f1c54d72SVlad Serebrennikov         << 0 << 4 << NumArgs << /*is non object*/ 0;
246*f1c54d72SVlad Serebrennikov     return true;
247*f1c54d72SVlad Serebrennikov   }
248*f1c54d72SVlad Serebrennikov 
249*f1c54d72SVlad Serebrennikov   Expr *Arg0 = TheCall->getArg(0);
250*f1c54d72SVlad Serebrennikov   Expr *Arg1 = TheCall->getArg(1);
251*f1c54d72SVlad Serebrennikov   Expr *Arg2 = TheCall->getArg(2);
252*f1c54d72SVlad Serebrennikov   Expr *Arg3 = TheCall->getArg(3);
253*f1c54d72SVlad Serebrennikov 
254*f1c54d72SVlad Serebrennikov   // First argument always needs to be a queue_t type.
255*f1c54d72SVlad Serebrennikov   if (!Arg0->getType()->isQueueT()) {
256*f1c54d72SVlad Serebrennikov     Diag(TheCall->getArg(0)->getBeginLoc(),
257*f1c54d72SVlad Serebrennikov          diag::err_opencl_builtin_expected_type)
258*f1c54d72SVlad Serebrennikov         << TheCall->getDirectCallee() << getASTContext().OCLQueueTy;
259*f1c54d72SVlad Serebrennikov     return true;
260*f1c54d72SVlad Serebrennikov   }
261*f1c54d72SVlad Serebrennikov 
262*f1c54d72SVlad Serebrennikov   // Second argument always needs to be a kernel_enqueue_flags_t enum value.
263*f1c54d72SVlad Serebrennikov   if (!Arg1->getType()->isIntegerType()) {
264*f1c54d72SVlad Serebrennikov     Diag(TheCall->getArg(1)->getBeginLoc(),
265*f1c54d72SVlad Serebrennikov          diag::err_opencl_builtin_expected_type)
266*f1c54d72SVlad Serebrennikov         << TheCall->getDirectCallee() << "'kernel_enqueue_flags_t' (i.e. uint)";
267*f1c54d72SVlad Serebrennikov     return true;
268*f1c54d72SVlad Serebrennikov   }
269*f1c54d72SVlad Serebrennikov 
270*f1c54d72SVlad Serebrennikov   // Third argument is always an ndrange_t type.
271*f1c54d72SVlad Serebrennikov   if (Arg2->getType().getUnqualifiedType().getAsString() != "ndrange_t") {
272*f1c54d72SVlad Serebrennikov     Diag(TheCall->getArg(2)->getBeginLoc(),
273*f1c54d72SVlad Serebrennikov          diag::err_opencl_builtin_expected_type)
274*f1c54d72SVlad Serebrennikov         << TheCall->getDirectCallee() << "'ndrange_t'";
275*f1c54d72SVlad Serebrennikov     return true;
276*f1c54d72SVlad Serebrennikov   }
277*f1c54d72SVlad Serebrennikov 
278*f1c54d72SVlad Serebrennikov   // With four arguments, there is only one form that the function could be
279*f1c54d72SVlad Serebrennikov   // called in: no events and no variable arguments.
280*f1c54d72SVlad Serebrennikov   if (NumArgs == 4) {
281*f1c54d72SVlad Serebrennikov     // check that the last argument is the right block type.
282*f1c54d72SVlad Serebrennikov     if (!isBlockPointer(Arg3)) {
283*f1c54d72SVlad Serebrennikov       Diag(Arg3->getBeginLoc(), diag::err_opencl_builtin_expected_type)
284*f1c54d72SVlad Serebrennikov           << TheCall->getDirectCallee() << "block";
285*f1c54d72SVlad Serebrennikov       return true;
286*f1c54d72SVlad Serebrennikov     }
287*f1c54d72SVlad Serebrennikov     // we have a block type, check the prototype
288*f1c54d72SVlad Serebrennikov     const BlockPointerType *BPT =
289*f1c54d72SVlad Serebrennikov         cast<BlockPointerType>(Arg3->getType().getCanonicalType());
290*f1c54d72SVlad Serebrennikov     if (BPT->getPointeeType()->castAs<FunctionProtoType>()->getNumParams() >
291*f1c54d72SVlad Serebrennikov         0) {
292*f1c54d72SVlad Serebrennikov       Diag(Arg3->getBeginLoc(), diag::err_opencl_enqueue_kernel_blocks_no_args);
293*f1c54d72SVlad Serebrennikov       return true;
294*f1c54d72SVlad Serebrennikov     }
295*f1c54d72SVlad Serebrennikov     return false;
296*f1c54d72SVlad Serebrennikov   }
297*f1c54d72SVlad Serebrennikov   // we can have block + varargs.
298*f1c54d72SVlad Serebrennikov   if (isBlockPointer(Arg3))
299*f1c54d72SVlad Serebrennikov     return (checkBlockArgs(SemaRef, Arg3) ||
300*f1c54d72SVlad Serebrennikov             checkOpenCLEnqueueVariadicArgs(SemaRef, TheCall, Arg3, 4));
301*f1c54d72SVlad Serebrennikov   // last two cases with either exactly 7 args or 7 args and varargs.
302*f1c54d72SVlad Serebrennikov   if (NumArgs >= 7) {
303*f1c54d72SVlad Serebrennikov     // check common block argument.
304*f1c54d72SVlad Serebrennikov     Expr *Arg6 = TheCall->getArg(6);
305*f1c54d72SVlad Serebrennikov     if (!isBlockPointer(Arg6)) {
306*f1c54d72SVlad Serebrennikov       Diag(Arg6->getBeginLoc(), diag::err_opencl_builtin_expected_type)
307*f1c54d72SVlad Serebrennikov           << TheCall->getDirectCallee() << "block";
308*f1c54d72SVlad Serebrennikov       return true;
309*f1c54d72SVlad Serebrennikov     }
310*f1c54d72SVlad Serebrennikov     if (checkBlockArgs(SemaRef, Arg6))
311*f1c54d72SVlad Serebrennikov       return true;
312*f1c54d72SVlad Serebrennikov 
313*f1c54d72SVlad Serebrennikov     // Forth argument has to be any integer type.
314*f1c54d72SVlad Serebrennikov     if (!Arg3->getType()->isIntegerType()) {
315*f1c54d72SVlad Serebrennikov       Diag(TheCall->getArg(3)->getBeginLoc(),
316*f1c54d72SVlad Serebrennikov            diag::err_opencl_builtin_expected_type)
317*f1c54d72SVlad Serebrennikov           << TheCall->getDirectCallee() << "integer";
318*f1c54d72SVlad Serebrennikov       return true;
319*f1c54d72SVlad Serebrennikov     }
320*f1c54d72SVlad Serebrennikov     // check remaining common arguments.
321*f1c54d72SVlad Serebrennikov     Expr *Arg4 = TheCall->getArg(4);
322*f1c54d72SVlad Serebrennikov     Expr *Arg5 = TheCall->getArg(5);
323*f1c54d72SVlad Serebrennikov 
324*f1c54d72SVlad Serebrennikov     // Fifth argument is always passed as a pointer to clk_event_t.
325*f1c54d72SVlad Serebrennikov     if (!Arg4->isNullPointerConstant(Context,
326*f1c54d72SVlad Serebrennikov                                      Expr::NPC_ValueDependentIsNotNull) &&
327*f1c54d72SVlad Serebrennikov         !Arg4->getType()->getPointeeOrArrayElementType()->isClkEventT()) {
328*f1c54d72SVlad Serebrennikov       Diag(TheCall->getArg(4)->getBeginLoc(),
329*f1c54d72SVlad Serebrennikov            diag::err_opencl_builtin_expected_type)
330*f1c54d72SVlad Serebrennikov           << TheCall->getDirectCallee()
331*f1c54d72SVlad Serebrennikov           << Context.getPointerType(Context.OCLClkEventTy);
332*f1c54d72SVlad Serebrennikov       return true;
333*f1c54d72SVlad Serebrennikov     }
334*f1c54d72SVlad Serebrennikov 
335*f1c54d72SVlad Serebrennikov     // Sixth argument is always passed as a pointer to clk_event_t.
336*f1c54d72SVlad Serebrennikov     if (!Arg5->isNullPointerConstant(Context,
337*f1c54d72SVlad Serebrennikov                                      Expr::NPC_ValueDependentIsNotNull) &&
338*f1c54d72SVlad Serebrennikov         !(Arg5->getType()->isPointerType() &&
339*f1c54d72SVlad Serebrennikov           Arg5->getType()->getPointeeType()->isClkEventT())) {
340*f1c54d72SVlad Serebrennikov       Diag(TheCall->getArg(5)->getBeginLoc(),
341*f1c54d72SVlad Serebrennikov            diag::err_opencl_builtin_expected_type)
342*f1c54d72SVlad Serebrennikov           << TheCall->getDirectCallee()
343*f1c54d72SVlad Serebrennikov           << Context.getPointerType(Context.OCLClkEventTy);
344*f1c54d72SVlad Serebrennikov       return true;
345*f1c54d72SVlad Serebrennikov     }
346*f1c54d72SVlad Serebrennikov 
347*f1c54d72SVlad Serebrennikov     if (NumArgs == 7)
348*f1c54d72SVlad Serebrennikov       return false;
349*f1c54d72SVlad Serebrennikov 
350*f1c54d72SVlad Serebrennikov     return checkOpenCLEnqueueVariadicArgs(SemaRef, TheCall, Arg6, 7);
351*f1c54d72SVlad Serebrennikov   }
352*f1c54d72SVlad Serebrennikov 
353*f1c54d72SVlad Serebrennikov   // None of the specific case has been detected, give generic error
354*f1c54d72SVlad Serebrennikov   Diag(TheCall->getBeginLoc(), diag::err_opencl_enqueue_kernel_incorrect_args);
355*f1c54d72SVlad Serebrennikov   return true;
356*f1c54d72SVlad Serebrennikov }
357*f1c54d72SVlad Serebrennikov 
358*f1c54d72SVlad Serebrennikov /// Returns OpenCL access qual.
getOpenCLArgAccess(const Decl * D)359*f1c54d72SVlad Serebrennikov static OpenCLAccessAttr *getOpenCLArgAccess(const Decl *D) {
360*f1c54d72SVlad Serebrennikov   return D->getAttr<OpenCLAccessAttr>();
361*f1c54d72SVlad Serebrennikov }
362*f1c54d72SVlad Serebrennikov 
363*f1c54d72SVlad Serebrennikov /// Returns true if pipe element type is different from the pointer.
checkPipeArg(Sema & S,CallExpr * Call)364*f1c54d72SVlad Serebrennikov static bool checkPipeArg(Sema &S, CallExpr *Call) {
365*f1c54d72SVlad Serebrennikov   const Expr *Arg0 = Call->getArg(0);
366*f1c54d72SVlad Serebrennikov   // First argument type should always be pipe.
367*f1c54d72SVlad Serebrennikov   if (!Arg0->getType()->isPipeType()) {
368*f1c54d72SVlad Serebrennikov     S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_first_arg)
369*f1c54d72SVlad Serebrennikov         << Call->getDirectCallee() << Arg0->getSourceRange();
370*f1c54d72SVlad Serebrennikov     return true;
371*f1c54d72SVlad Serebrennikov   }
372*f1c54d72SVlad Serebrennikov   OpenCLAccessAttr *AccessQual =
373*f1c54d72SVlad Serebrennikov       getOpenCLArgAccess(cast<DeclRefExpr>(Arg0)->getDecl());
374*f1c54d72SVlad Serebrennikov   // Validates the access qualifier is compatible with the call.
375*f1c54d72SVlad Serebrennikov   // OpenCL v2.0 s6.13.16 - The access qualifiers for pipe should only be
376*f1c54d72SVlad Serebrennikov   // read_only and write_only, and assumed to be read_only if no qualifier is
377*f1c54d72SVlad Serebrennikov   // specified.
378*f1c54d72SVlad Serebrennikov   switch (Call->getDirectCallee()->getBuiltinID()) {
379*f1c54d72SVlad Serebrennikov   case Builtin::BIread_pipe:
380*f1c54d72SVlad Serebrennikov   case Builtin::BIreserve_read_pipe:
381*f1c54d72SVlad Serebrennikov   case Builtin::BIcommit_read_pipe:
382*f1c54d72SVlad Serebrennikov   case Builtin::BIwork_group_reserve_read_pipe:
383*f1c54d72SVlad Serebrennikov   case Builtin::BIsub_group_reserve_read_pipe:
384*f1c54d72SVlad Serebrennikov   case Builtin::BIwork_group_commit_read_pipe:
385*f1c54d72SVlad Serebrennikov   case Builtin::BIsub_group_commit_read_pipe:
386*f1c54d72SVlad Serebrennikov     if (!(!AccessQual || AccessQual->isReadOnly())) {
387*f1c54d72SVlad Serebrennikov       S.Diag(Arg0->getBeginLoc(),
388*f1c54d72SVlad Serebrennikov              diag::err_opencl_builtin_pipe_invalid_access_modifier)
389*f1c54d72SVlad Serebrennikov           << "read_only" << Arg0->getSourceRange();
390*f1c54d72SVlad Serebrennikov       return true;
391*f1c54d72SVlad Serebrennikov     }
392*f1c54d72SVlad Serebrennikov     break;
393*f1c54d72SVlad Serebrennikov   case Builtin::BIwrite_pipe:
394*f1c54d72SVlad Serebrennikov   case Builtin::BIreserve_write_pipe:
395*f1c54d72SVlad Serebrennikov   case Builtin::BIcommit_write_pipe:
396*f1c54d72SVlad Serebrennikov   case Builtin::BIwork_group_reserve_write_pipe:
397*f1c54d72SVlad Serebrennikov   case Builtin::BIsub_group_reserve_write_pipe:
398*f1c54d72SVlad Serebrennikov   case Builtin::BIwork_group_commit_write_pipe:
399*f1c54d72SVlad Serebrennikov   case Builtin::BIsub_group_commit_write_pipe:
400*f1c54d72SVlad Serebrennikov     if (!(AccessQual && AccessQual->isWriteOnly())) {
401*f1c54d72SVlad Serebrennikov       S.Diag(Arg0->getBeginLoc(),
402*f1c54d72SVlad Serebrennikov              diag::err_opencl_builtin_pipe_invalid_access_modifier)
403*f1c54d72SVlad Serebrennikov           << "write_only" << Arg0->getSourceRange();
404*f1c54d72SVlad Serebrennikov       return true;
405*f1c54d72SVlad Serebrennikov     }
406*f1c54d72SVlad Serebrennikov     break;
407*f1c54d72SVlad Serebrennikov   default:
408*f1c54d72SVlad Serebrennikov     break;
409*f1c54d72SVlad Serebrennikov   }
410*f1c54d72SVlad Serebrennikov   return false;
411*f1c54d72SVlad Serebrennikov }
412*f1c54d72SVlad Serebrennikov 
413*f1c54d72SVlad Serebrennikov /// Returns true if pipe element type is different from the pointer.
checkPipePacketType(Sema & S,CallExpr * Call,unsigned Idx)414*f1c54d72SVlad Serebrennikov static bool checkPipePacketType(Sema &S, CallExpr *Call, unsigned Idx) {
415*f1c54d72SVlad Serebrennikov   const Expr *Arg0 = Call->getArg(0);
416*f1c54d72SVlad Serebrennikov   const Expr *ArgIdx = Call->getArg(Idx);
417*f1c54d72SVlad Serebrennikov   const PipeType *PipeTy = cast<PipeType>(Arg0->getType());
418*f1c54d72SVlad Serebrennikov   const QualType EltTy = PipeTy->getElementType();
419*f1c54d72SVlad Serebrennikov   const PointerType *ArgTy = ArgIdx->getType()->getAs<PointerType>();
420*f1c54d72SVlad Serebrennikov   // The Idx argument should be a pointer and the type of the pointer and
421*f1c54d72SVlad Serebrennikov   // the type of pipe element should also be the same.
422*f1c54d72SVlad Serebrennikov   if (!ArgTy ||
423*f1c54d72SVlad Serebrennikov       !S.Context.hasSameType(
424*f1c54d72SVlad Serebrennikov           EltTy, ArgTy->getPointeeType()->getCanonicalTypeInternal())) {
425*f1c54d72SVlad Serebrennikov     S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
426*f1c54d72SVlad Serebrennikov         << Call->getDirectCallee() << S.Context.getPointerType(EltTy)
427*f1c54d72SVlad Serebrennikov         << ArgIdx->getType() << ArgIdx->getSourceRange();
428*f1c54d72SVlad Serebrennikov     return true;
429*f1c54d72SVlad Serebrennikov   }
430*f1c54d72SVlad Serebrennikov   return false;
431*f1c54d72SVlad Serebrennikov }
432*f1c54d72SVlad Serebrennikov 
checkBuiltinRWPipe(CallExpr * Call)433*f1c54d72SVlad Serebrennikov bool SemaOpenCL::checkBuiltinRWPipe(CallExpr *Call) {
434*f1c54d72SVlad Serebrennikov   // OpenCL v2.0 s6.13.16.2 - The built-in read/write
435*f1c54d72SVlad Serebrennikov   // functions have two forms.
436*f1c54d72SVlad Serebrennikov   switch (Call->getNumArgs()) {
437*f1c54d72SVlad Serebrennikov   case 2:
438*f1c54d72SVlad Serebrennikov     if (checkPipeArg(SemaRef, Call))
439*f1c54d72SVlad Serebrennikov       return true;
440*f1c54d72SVlad Serebrennikov     // The call with 2 arguments should be
441*f1c54d72SVlad Serebrennikov     // read/write_pipe(pipe T, T*).
442*f1c54d72SVlad Serebrennikov     // Check packet type T.
443*f1c54d72SVlad Serebrennikov     if (checkPipePacketType(SemaRef, Call, 1))
444*f1c54d72SVlad Serebrennikov       return true;
445*f1c54d72SVlad Serebrennikov     break;
446*f1c54d72SVlad Serebrennikov 
447*f1c54d72SVlad Serebrennikov   case 4: {
448*f1c54d72SVlad Serebrennikov     if (checkPipeArg(SemaRef, Call))
449*f1c54d72SVlad Serebrennikov       return true;
450*f1c54d72SVlad Serebrennikov     // The call with 4 arguments should be
451*f1c54d72SVlad Serebrennikov     // read/write_pipe(pipe T, reserve_id_t, uint, T*).
452*f1c54d72SVlad Serebrennikov     // Check reserve_id_t.
453*f1c54d72SVlad Serebrennikov     if (!Call->getArg(1)->getType()->isReserveIDT()) {
454*f1c54d72SVlad Serebrennikov       Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
455*f1c54d72SVlad Serebrennikov           << Call->getDirectCallee() << getASTContext().OCLReserveIDTy
456*f1c54d72SVlad Serebrennikov           << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange();
457*f1c54d72SVlad Serebrennikov       return true;
458*f1c54d72SVlad Serebrennikov     }
459*f1c54d72SVlad Serebrennikov 
460*f1c54d72SVlad Serebrennikov     // Check the index.
461*f1c54d72SVlad Serebrennikov     const Expr *Arg2 = Call->getArg(2);
462*f1c54d72SVlad Serebrennikov     if (!Arg2->getType()->isIntegerType() &&
463*f1c54d72SVlad Serebrennikov         !Arg2->getType()->isUnsignedIntegerType()) {
464*f1c54d72SVlad Serebrennikov       Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
465*f1c54d72SVlad Serebrennikov           << Call->getDirectCallee() << getASTContext().UnsignedIntTy
466*f1c54d72SVlad Serebrennikov           << Arg2->getType() << Arg2->getSourceRange();
467*f1c54d72SVlad Serebrennikov       return true;
468*f1c54d72SVlad Serebrennikov     }
469*f1c54d72SVlad Serebrennikov 
470*f1c54d72SVlad Serebrennikov     // Check packet type T.
471*f1c54d72SVlad Serebrennikov     if (checkPipePacketType(SemaRef, Call, 3))
472*f1c54d72SVlad Serebrennikov       return true;
473*f1c54d72SVlad Serebrennikov   } break;
474*f1c54d72SVlad Serebrennikov   default:
475*f1c54d72SVlad Serebrennikov     Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_arg_num)
476*f1c54d72SVlad Serebrennikov         << Call->getDirectCallee() << Call->getSourceRange();
477*f1c54d72SVlad Serebrennikov     return true;
478*f1c54d72SVlad Serebrennikov   }
479*f1c54d72SVlad Serebrennikov 
480*f1c54d72SVlad Serebrennikov   return false;
481*f1c54d72SVlad Serebrennikov }
482*f1c54d72SVlad Serebrennikov 
checkBuiltinReserveRWPipe(CallExpr * Call)483*f1c54d72SVlad Serebrennikov bool SemaOpenCL::checkBuiltinReserveRWPipe(CallExpr *Call) {
484*f1c54d72SVlad Serebrennikov   if (SemaRef.checkArgCount(Call, 2))
485*f1c54d72SVlad Serebrennikov     return true;
486*f1c54d72SVlad Serebrennikov 
487*f1c54d72SVlad Serebrennikov   if (checkPipeArg(SemaRef, Call))
488*f1c54d72SVlad Serebrennikov     return true;
489*f1c54d72SVlad Serebrennikov 
490*f1c54d72SVlad Serebrennikov   // Check the reserve size.
491*f1c54d72SVlad Serebrennikov   if (!Call->getArg(1)->getType()->isIntegerType() &&
492*f1c54d72SVlad Serebrennikov       !Call->getArg(1)->getType()->isUnsignedIntegerType()) {
493*f1c54d72SVlad Serebrennikov     Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
494*f1c54d72SVlad Serebrennikov         << Call->getDirectCallee() << getASTContext().UnsignedIntTy
495*f1c54d72SVlad Serebrennikov         << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange();
496*f1c54d72SVlad Serebrennikov     return true;
497*f1c54d72SVlad Serebrennikov   }
498*f1c54d72SVlad Serebrennikov 
499*f1c54d72SVlad Serebrennikov   // Since return type of reserve_read/write_pipe built-in function is
500*f1c54d72SVlad Serebrennikov   // reserve_id_t, which is not defined in the builtin def file , we used int
501*f1c54d72SVlad Serebrennikov   // as return type and need to override the return type of these functions.
502*f1c54d72SVlad Serebrennikov   Call->setType(getASTContext().OCLReserveIDTy);
503*f1c54d72SVlad Serebrennikov 
504*f1c54d72SVlad Serebrennikov   return false;
505*f1c54d72SVlad Serebrennikov }
506*f1c54d72SVlad Serebrennikov 
checkBuiltinCommitRWPipe(CallExpr * Call)507*f1c54d72SVlad Serebrennikov bool SemaOpenCL::checkBuiltinCommitRWPipe(CallExpr *Call) {
508*f1c54d72SVlad Serebrennikov   if (SemaRef.checkArgCount(Call, 2))
509*f1c54d72SVlad Serebrennikov     return true;
510*f1c54d72SVlad Serebrennikov 
511*f1c54d72SVlad Serebrennikov   if (checkPipeArg(SemaRef, Call))
512*f1c54d72SVlad Serebrennikov     return true;
513*f1c54d72SVlad Serebrennikov 
514*f1c54d72SVlad Serebrennikov   // Check reserve_id_t.
515*f1c54d72SVlad Serebrennikov   if (!Call->getArg(1)->getType()->isReserveIDT()) {
516*f1c54d72SVlad Serebrennikov     Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
517*f1c54d72SVlad Serebrennikov         << Call->getDirectCallee() << getASTContext().OCLReserveIDTy
518*f1c54d72SVlad Serebrennikov         << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange();
519*f1c54d72SVlad Serebrennikov     return true;
520*f1c54d72SVlad Serebrennikov   }
521*f1c54d72SVlad Serebrennikov 
522*f1c54d72SVlad Serebrennikov   return false;
523*f1c54d72SVlad Serebrennikov }
524*f1c54d72SVlad Serebrennikov 
checkBuiltinPipePackets(CallExpr * Call)525*f1c54d72SVlad Serebrennikov bool SemaOpenCL::checkBuiltinPipePackets(CallExpr *Call) {
526*f1c54d72SVlad Serebrennikov   if (SemaRef.checkArgCount(Call, 1))
527*f1c54d72SVlad Serebrennikov     return true;
528*f1c54d72SVlad Serebrennikov 
529*f1c54d72SVlad Serebrennikov   if (!Call->getArg(0)->getType()->isPipeType()) {
530*f1c54d72SVlad Serebrennikov     Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_first_arg)
531*f1c54d72SVlad Serebrennikov         << Call->getDirectCallee() << Call->getArg(0)->getSourceRange();
532*f1c54d72SVlad Serebrennikov     return true;
533*f1c54d72SVlad Serebrennikov   }
534*f1c54d72SVlad Serebrennikov 
535*f1c54d72SVlad Serebrennikov   return false;
536*f1c54d72SVlad Serebrennikov }
537*f1c54d72SVlad Serebrennikov 
checkBuiltinToAddr(unsigned BuiltinID,CallExpr * Call)538*f1c54d72SVlad Serebrennikov bool SemaOpenCL::checkBuiltinToAddr(unsigned BuiltinID, CallExpr *Call) {
539*f1c54d72SVlad Serebrennikov   if (SemaRef.checkArgCount(Call, 1))
540*f1c54d72SVlad Serebrennikov     return true;
541*f1c54d72SVlad Serebrennikov 
542*f1c54d72SVlad Serebrennikov   auto RT = Call->getArg(0)->getType();
543*f1c54d72SVlad Serebrennikov   if (!RT->isPointerType() ||
544*f1c54d72SVlad Serebrennikov       RT->getPointeeType().getAddressSpace() == LangAS::opencl_constant) {
545*f1c54d72SVlad Serebrennikov     Diag(Call->getBeginLoc(), diag::err_opencl_builtin_to_addr_invalid_arg)
546*f1c54d72SVlad Serebrennikov         << Call->getArg(0) << Call->getDirectCallee() << Call->getSourceRange();
547*f1c54d72SVlad Serebrennikov     return true;
548*f1c54d72SVlad Serebrennikov   }
549*f1c54d72SVlad Serebrennikov 
550*f1c54d72SVlad Serebrennikov   if (RT->getPointeeType().getAddressSpace() != LangAS::opencl_generic) {
551*f1c54d72SVlad Serebrennikov     Diag(Call->getArg(0)->getBeginLoc(),
552*f1c54d72SVlad Serebrennikov          diag::warn_opencl_generic_address_space_arg)
553*f1c54d72SVlad Serebrennikov         << Call->getDirectCallee()->getNameInfo().getAsString()
554*f1c54d72SVlad Serebrennikov         << Call->getArg(0)->getSourceRange();
555*f1c54d72SVlad Serebrennikov   }
556*f1c54d72SVlad Serebrennikov 
557*f1c54d72SVlad Serebrennikov   RT = RT->getPointeeType();
558*f1c54d72SVlad Serebrennikov   auto Qual = RT.getQualifiers();
559*f1c54d72SVlad Serebrennikov   switch (BuiltinID) {
560*f1c54d72SVlad Serebrennikov   case Builtin::BIto_global:
561*f1c54d72SVlad Serebrennikov     Qual.setAddressSpace(LangAS::opencl_global);
562*f1c54d72SVlad Serebrennikov     break;
563*f1c54d72SVlad Serebrennikov   case Builtin::BIto_local:
564*f1c54d72SVlad Serebrennikov     Qual.setAddressSpace(LangAS::opencl_local);
565*f1c54d72SVlad Serebrennikov     break;
566*f1c54d72SVlad Serebrennikov   case Builtin::BIto_private:
567*f1c54d72SVlad Serebrennikov     Qual.setAddressSpace(LangAS::opencl_private);
568*f1c54d72SVlad Serebrennikov     break;
569*f1c54d72SVlad Serebrennikov   default:
570*f1c54d72SVlad Serebrennikov     llvm_unreachable("Invalid builtin function");
571*f1c54d72SVlad Serebrennikov   }
572*f1c54d72SVlad Serebrennikov   Call->setType(getASTContext().getPointerType(
573*f1c54d72SVlad Serebrennikov       getASTContext().getQualifiedType(RT.getUnqualifiedType(), Qual)));
574*f1c54d72SVlad Serebrennikov 
575*f1c54d72SVlad Serebrennikov   return false;
576*f1c54d72SVlad Serebrennikov }
577*f1c54d72SVlad Serebrennikov 
5786b755b0cSVlad Serebrennikov } // namespace clang
579