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