Thank you for you advise, I will make these fixed in some later commit. -----Original Message----- From: meta...@gmail.com [mailto:meta...@gmail.com] On Behalf Of Richard Smith Sent: Tuesday, February 2, 2016 5:53 AM To: Xiuli Pan <xiuli...@outlook.com> Cc: cfe-commits <cfe-commits@lists.llvm.org> Subject: Re: r258782 - Recommit: R258773 [OpenCL] Pipe builtin functions
On Mon, Jan 25, 2016 at 8:03 PM, Xiuli Pan via cfe-commits <cfe-commits@lists.llvm.org> wrote: > Author: pxl > Date: Mon Jan 25 22:03:48 2016 > New Revision: 258782 > > URL: http://llvm.org/viewvc/llvm-project?rev=258782&view=rev > Log: > Recommit: R258773 [OpenCL] Pipe builtin functions Fix arc patch fuzz > error. > Summary: > Support for the pipe built-in functions for OpenCL 2.0. > The pipe builtin functions may have infinite kinds of element types, > one approach would be to just generate calls that would always use generic > types such as void*. > This patch is based on bader's opencl support patch on SPIR-V branch. > > Reviewers: Anastasia, pekka.jaaskelainen > > Subscribers: keryell, bader, cfe-commits > > Differential Revision: http://reviews.llvm.org/D15914 > > Added: > cfe/trunk/test/CodeGenOpenCL/pipe_builtin.cl > cfe/trunk/test/SemaOpenCL/invalid-pipe-builtin-cl2.0.cl > Modified: > cfe/trunk/include/clang/Basic/Builtins.def > cfe/trunk/include/clang/Basic/Builtins.h > cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > cfe/trunk/lib/Basic/Builtins.cpp > cfe/trunk/lib/CodeGen/CGBuiltin.cpp > cfe/trunk/lib/Sema/SemaChecking.cpp > > Modified: cfe/trunk/include/clang/Basic/Builtins.def > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Buil > tins.def?rev=258782&r1=258781&r2=258782&view=diff > ====================================================================== > ======== > --- cfe/trunk/include/clang/Basic/Builtins.def (original) > +++ cfe/trunk/include/clang/Basic/Builtins.def Mon Jan 25 22:03:48 > +++ 2016 > @@ -1252,6 +1252,32 @@ BUILTIN(__builtin___get_unsafe_stack_ptr > BUILTIN(__builtin_nontemporal_store, "v.", "t") > BUILTIN(__builtin_nontemporal_load, "v.", "t") > > +// OpenCL v2.0 s6.13.16, s9.17.3.5 - Pipe functions. > +// We need the generic prototype, since the packet type could be anything. > +LANGBUILTIN(read_pipe, "i.", "tn", OCLC_LANG) LANGBUILTIN(write_pipe, > +"i.", "tn", OCLC_LANG) > + > +LANGBUILTIN(reserve_read_pipe, "i.", "tn", OCLC_LANG) > +LANGBUILTIN(reserve_write_pipe, "i.", "tn", OCLC_LANG) > + > +LANGBUILTIN(commit_write_pipe, "v.", "tn", OCLC_LANG) > +LANGBUILTIN(commit_read_pipe, "v.", "tn", OCLC_LANG) > + > +LANGBUILTIN(sub_group_reserve_read_pipe, "i.", "tn", OCLC_LANG) > +LANGBUILTIN(sub_group_reserve_write_pipe, "i.", "tn", OCLC_LANG) > + > +LANGBUILTIN(sub_group_commit_read_pipe, "v.", "tn", OCLC_LANG) > +LANGBUILTIN(sub_group_commit_write_pipe, "v.", "tn", OCLC_LANG) > + > +LANGBUILTIN(work_group_reserve_read_pipe, "i.", "tn", OCLC_LANG) > +LANGBUILTIN(work_group_reserve_write_pipe, "i.", "tn", OCLC_LANG) > + > +LANGBUILTIN(work_group_commit_read_pipe, "v.", "tn", OCLC_LANG) > +LANGBUILTIN(work_group_commit_write_pipe, "v.", "tn", OCLC_LANG) > + > +LANGBUILTIN(get_pipe_num_packets, "Ui.", "tn", OCLC_LANG) > +LANGBUILTIN(get_pipe_max_packets, "Ui.", "tn", OCLC_LANG) > + > #undef BUILTIN > #undef LIBBUILTIN > #undef LANGBUILTIN > > Modified: cfe/trunk/include/clang/Basic/Builtins.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Buil > tins.h?rev=258782&r1=258781&r2=258782&view=diff > ====================================================================== > ======== > --- cfe/trunk/include/clang/Basic/Builtins.h (original) > +++ cfe/trunk/include/clang/Basic/Builtins.h Mon Jan 25 22:03:48 2016 > @@ -36,6 +36,7 @@ enum LanguageID { > CXX_LANG = 0x4, // builtin for cplusplus only. > OBJC_LANG = 0x8, // builtin for objective-c and objective-c++ > MS_LANG = 0x10, // builtin requires MS mode. > + OCLC_LANG = 0x20,// builtin for OpenCL C only. Missing space after comma. > ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all > languages. > ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU > mode. > ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG // builtin requires MS mode. > > Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diag > nosticSemaKinds.td?rev=258782&r1=258781&r2=258782&view=diff > ====================================================================== > ======== > --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) > +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Jan 25 > +++ 22:03:48 2016 > @@ -7680,6 +7680,16 @@ def err_atomic_init_constant : Error< def > err_opencl_implicit_vector_conversion : Error< > "implicit conversions between vector types (%0 and %1) are not > permitted">; > > +// OpenCL v2.0 s6.13.6 -- Builtin Pipe Functions def > +err_opencl_builtin_pipe_first_arg : Error< > + "first argument to %0 must be a pipe type">; def > +err_opencl_builtin_pipe_arg_num : Error< > + "invalid number of arguments to function: %0">; Too much indentation here. > +def err_opencl_builtin_pipe_invalid_arg : Error< > + "invalid argument type to function %0 (expecting %1)">; def > +err_opencl_builtin_pipe_invalid_access_modifier : Error< > + "invalid pipe access modifier (expecting %0)">; > + > // OpenCL Section 6.8.g > def err_opencl_unknown_type_specifier : Error< > "OpenCL does not support the '%0' %select{type qualifier|storage > class specifier}1">; > > Modified: cfe/trunk/lib/Basic/Builtins.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Builtins.cpp?r > ev=258782&r1=258781&r2=258782&view=diff > ====================================================================== > ======== > --- cfe/trunk/lib/Basic/Builtins.cpp (original) > +++ cfe/trunk/lib/Basic/Builtins.cpp Mon Jan 25 22:03:48 2016 > @@ -69,7 +69,8 @@ bool Builtin::Context::builtinIsSupporte > bool MSModeUnsupported = > !LangOpts.MicrosoftExt && (BuiltinInfo.Langs & MS_LANG); > bool ObjCUnsupported = !LangOpts.ObjC1 && BuiltinInfo.Langs == > OBJC_LANG; > - return !BuiltinsUnsupported && !MathBuiltinsUnsupported && > + bool OclCUnsupported = !LangOpts.OpenCL && BuiltinInfo.Langs == > + OCLC_LANG; return !BuiltinsUnsupported && !MathBuiltinsUnsupported > + && !OclCUnsupported && > !GnuModeUnsupported && !MSModeUnsupported && > !ObjCUnsupported; } > > > Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cp > p?rev=258782&r1=258781&r2=258782&view=diff > ====================================================================== > ======== > --- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Mon Jan 25 22:03:48 2016 > @@ -1963,6 +1963,142 @@ RValue CodeGenFunction::EmitBuiltinExpr( > return RValue::get(llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy)); > break; > } > + > + // OpenCL v2.0 s6.13.16.2, Built-in pipe read and write functions > + case Builtin::BIread_pipe: > + case Builtin::BIwrite_pipe: { > + Value *Arg0 = EmitScalarExpr(E->getArg(0)), > + *Arg1 = EmitScalarExpr(E->getArg(1)); > + > + // Type of the generic packet parameter. > + unsigned GenericAS = > + getContext().getTargetAddressSpace(LangAS::opencl_generic); > + llvm::Type *I8PTy = llvm::PointerType::get( > + llvm::Type::getInt8Ty(getLLVMContext()), GenericAS); > + > + // Testing which overloaded version we should generate the call for. > + if (2U == E->getNumArgs()) { > + const char *Name = (BuiltinID == Builtin::BIread_pipe) ? > "__read_pipe_2" > + : > "__write_pipe_2"; > + // Creating a generic function type to be able to call with any > builtin or > + // user defined type. > + llvm::Type *ArgTys[] = {Arg0->getType(), I8PTy}; > + llvm::FunctionType *FTy = llvm::FunctionType::get( > + Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false); > + Value *BCast = Builder.CreatePointerCast(Arg1, I8PTy); > + return RValue::get(Builder.CreateCall( > + CGM.CreateRuntimeFunction(FTy, Name), {Arg0, BCast})); > + } else { > + assert(4 == E->getNumArgs() && > + "Illegal number of parameters to pipe function"); > + const char *Name = (BuiltinID == Builtin::BIread_pipe) ? > "__read_pipe_4" > + : > + "__write_pipe_4"; > + > + llvm::Type *ArgTys[] = {Arg0->getType(), Arg1->getType(), Int32Ty, > I8PTy}; > + Value *Arg2 = EmitScalarExpr(E->getArg(2)), > + *Arg3 = EmitScalarExpr(E->getArg(3)); > + llvm::FunctionType *FTy = llvm::FunctionType::get( > + Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false); > + Value *BCast = Builder.CreatePointerCast(Arg3, I8PTy); > + // We know the third argument is an integer type, but we may need to > cast > + // it to i32. > + if (Arg2->getType() != Int32Ty) > + Arg2 = Builder.CreateZExtOrTrunc(Arg2, Int32Ty); Why are these conversions performed here rather than in Sema? > + return RValue::get(Builder.CreateCall( > + CGM.CreateRuntimeFunction(FTy, Name), {Arg0, Arg1, Arg2, BCast})); > + } > + } > + // OpenCL v2.0 s6.13.16 ,s9.17.3.5 - Built-in pipe reserve read and > + write // functions case Builtin::BIreserve_read_pipe: > + case Builtin::BIreserve_write_pipe: > + case Builtin::BIwork_group_reserve_read_pipe: > + case Builtin::BIwork_group_reserve_write_pipe: > + case Builtin::BIsub_group_reserve_read_pipe: > + case Builtin::BIsub_group_reserve_write_pipe: { > + // Composing the mangled name for the function. > + const char *Name; > + if (BuiltinID == Builtin::BIreserve_read_pipe) > + Name = "__reserve_read_pipe"; > + else if (BuiltinID == Builtin::BIreserve_write_pipe) > + Name = "__reserve_write_pipe"; > + else if (BuiltinID == Builtin::BIwork_group_reserve_read_pipe) > + Name = "__work_group_reserve_read_pipe"; > + else if (BuiltinID == Builtin::BIwork_group_reserve_write_pipe) > + Name = "__work_group_reserve_write_pipe"; > + else if (BuiltinID == Builtin::BIsub_group_reserve_read_pipe) > + Name = "__sub_group_reserve_read_pipe"; > + else > + Name = "__sub_group_reserve_write_pipe"; > + > + Value *Arg0 = EmitScalarExpr(E->getArg(0)), > + *Arg1 = EmitScalarExpr(E->getArg(1)); > + llvm::Type *ReservedIDTy = > + ConvertType(getContext().OCLReserveIDTy); > + > + // Building the generic function prototype. > + llvm::Type *ArgTys[] = {Arg0->getType(), Int32Ty}; > + llvm::FunctionType *FTy = llvm::FunctionType::get( > + ReservedIDTy, llvm::ArrayRef<llvm::Type *>(ArgTys), false); > + // We know the second argument is an integer type, but we may need to > cast > + // it to i32. > + if (Arg1->getType() != Int32Ty) > + Arg1 = Builder.CreateZExtOrTrunc(Arg1, Int32Ty); > + return RValue::get( > + Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), > + {Arg0, Arg1})); } // OpenCL v2.0 s6.13.16 ,s9.17.3.5 - Built-in > + pipe commit read and write // functions case > + Builtin::BIcommit_read_pipe: > + case Builtin::BIcommit_write_pipe: > + case Builtin::BIwork_group_commit_read_pipe: > + case Builtin::BIwork_group_commit_write_pipe: > + case Builtin::BIsub_group_commit_read_pipe: > + case Builtin::BIsub_group_commit_write_pipe: { > + const char *Name; > + if (BuiltinID == Builtin::BIcommit_read_pipe) > + Name = "__commit_read_pipe"; > + else if (BuiltinID == Builtin::BIcommit_write_pipe) > + Name = "__commit_write_pipe"; > + else if (BuiltinID == Builtin::BIwork_group_commit_read_pipe) > + Name = "__work_group_commit_read_pipe"; > + else if (BuiltinID == Builtin::BIwork_group_commit_write_pipe) > + Name = "__work_group_commit_write_pipe"; > + else if (BuiltinID == Builtin::BIsub_group_commit_read_pipe) > + Name = "__sub_group_commit_read_pipe"; > + else > + Name = "__sub_group_commit_write_pipe"; > + > + Value *Arg0 = EmitScalarExpr(E->getArg(0)), > + *Arg1 = EmitScalarExpr(E->getArg(1)); > + > + // Building the generic function prototype. > + llvm::Type *ArgTys[] = {Arg0->getType(), Arg1->getType()}; > + llvm::FunctionType *FTy = > + llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()), > + llvm::ArrayRef<llvm::Type *>(ArgTys), > + false); > + > + return RValue::get( > + Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), > + {Arg0, Arg1})); } // OpenCL v2.0 s6.13.16.4 Built-in pipe query > + functions case Builtin::BIget_pipe_num_packets: > + case Builtin::BIget_pipe_max_packets: { > + const char *Name; > + if (BuiltinID == Builtin::BIget_pipe_num_packets) > + Name = "__get_pipe_num_packets"; > + else > + Name = "__get_pipe_max_packets"; > + > + // Building the generic function prototype. > + Value *Arg0 = EmitScalarExpr(E->getArg(0)); > + llvm::Type *ArgTys[] = {Arg0->getType()}; > + llvm::FunctionType *FTy = llvm::FunctionType::get( > + Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false); > + > + return RValue::get( > + Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), > + {Arg0})); } > + > case Builtin::BIprintf: > if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice) > return EmitCUDADevicePrintfCallExpr(E, ReturnValue); > > Modified: cfe/trunk/lib/Sema/SemaChecking.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cp > p?rev=258782&r1=258781&r2=258782&view=diff > ====================================================================== > ======== > --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) > +++ cfe/trunk/lib/Sema/SemaChecking.cpp Mon Jan 25 22:03:48 2016 > @@ -258,6 +258,192 @@ static bool SemaBuiltinSEHScopeCheck(Sem > return false; > } > > +/// Returns readable name for a call. > +static StringRef getFunctionName(CallExpr *Call) { > + return cast<FunctionDecl>(Call->getCalleeDecl())->getName(); > +} Don't map to a string here; instead, stream the FunctionDecl* into the diagnostic, so the diagnostic renderer can choose the most appropriate way to produce a useful name for the declaration. > + > +/// Returns OpenCL access qual. > +// TODO: Refine OpenCLImageAccessAttr to OpenCLAccessAttr since pipe > +can use // it too static OpenCLImageAccessAttr > +*getOpenCLArgAccess(const Decl *D) { > + if (D->hasAttr<OpenCLImageAccessAttr>()) > + return D->getAttr<OpenCLImageAccessAttr>(); > + return nullptr; > +} This is redundant; just use 'D->getAttr<OpenCLImageAccessAttr>()'. > + > +/// Returns true if pipe element type is different from the pointer. > +static bool checkOpenCLPipeArg(Sema &S, CallExpr *Call) { > + const Expr *Arg0 = Call->getArg(0); > + // First argument type should always be pipe. > + if (!Arg0->getType()->isPipeType()) { > + S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_first_arg) > + << getFunctionName(Call) << Arg0->getSourceRange(); > + return true; > + } > + OpenCLImageAccessAttr *AccessQual = > + getOpenCLArgAccess(cast<DeclRefExpr>(Arg0)->getDecl()); > + // Validates the access qualifier is compatible with the call. > + // OpenCL v2.0 s6.13.16 - The access qualifiers for pipe should > +only be > + // read_only and write_only, and assumed to be read_only if no > +qualifier is > + // specified. > + bool isValid = true; > + bool ReadOnly = getFunctionName(Call).find("read") != > +StringRef::npos; Please check the builtin ID instead of looking for a string in the name. > + if (ReadOnly) > + isValid = AccessQual == nullptr || AccessQual->isReadOnly(); > + else > + isValid = AccessQual != nullptr && AccessQual->isWriteOnly(); if > + (!isValid) { > + const char *AM = ReadOnly ? "read_only" : "write_only"; > + S.Diag(Arg0->getLocStart(), > + diag::err_opencl_builtin_pipe_invalid_access_modifier) > + << AM << Arg0->getSourceRange(); > + return true; > + } > + > + return false; > +} > + > +/// Returns true if pipe element type is different from the pointer. > +static bool checkOpenCLPipePacketType(Sema &S, CallExpr *Call, > +unsigned Idx) { > + const Expr *Arg0 = Call->getArg(0); > + const Expr *ArgIdx = Call->getArg(Idx); > + const PipeType *PipeTy = cast<PipeType>(Arg0->getType()); > + const Type *EltTy = PipeTy->getElementType().getTypePtr(); > + const PointerType *ArgTy = > + dyn_cast<PointerType>(ArgIdx->getType().getTypePtr()); Use ArgIdx->getType()->getAs<PointerType>(). This is wrong in the presence of type sugar. > + // The Idx argument should be a pointer and the type of the pointer > + and // the type of pipe element should also be the same. > + if (!ArgTy || EltTy != ArgTy->getPointeeType().getTypePtr()) { Don't compare type pointers like this; this is also wrong in the case of type sugar. Use ASTContext::hasSameType instead. > + S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) > + << getFunctionName(Call) > + << S.Context.getPointerType(PipeTy->getElementType()) > + << ArgIdx->getSourceRange(); > + return true; > + } > + return false; > +} > + > +// \brief Performs semantic analysis for the read/write_pipe call. > +// \param S Reference to the semantic analyzer. > +// \param Call A pointer to the builtin call. > +// \return True if a semantic error has been found, false otherwise. > +static bool SemaBuiltinRWPipe(Sema &S, CallExpr *Call) { > + // Two kinds of read/write pipe > + // From OpenCL C Specification 6.13.16.2 the built-in read/write > + // functions have following forms. > + switch (Call->getNumArgs()) { > + case 2: { > + if (checkOpenCLPipeArg(S, Call)) > + return true; > + // The call with 2 arguments should be > + // read/write_pipe(pipe T, T*) > + // check packet type T > + if (checkOpenCLPipePacketType(S, Call, 1)) > + return true; > + } break; > + > + case 4: { > + if (checkOpenCLPipeArg(S, Call)) > + return true; > + // The call with 4 arguments should be > + // read/write_pipe(pipe T, reserve_id_t, uint, T*) > + // check reserve_id_t > + if (!Call->getArg(1)->getType()->isReserveIDT()) { You should attempt to implicitly convert to the desired type here, rather than demanding the right type, to match the normal call semantics. Likewise elsewhere in this patch. > + S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) > + << getFunctionName(Call) << S.Context.OCLReserveIDTy > + << Call->getArg(1)->getSourceRange(); > + return true; > + } > + > + // check the index Per the coding guidelines, please start comments with a capital letter and end them with a period. > + const Expr *Arg2 = Call->getArg(2); > + if (!Arg2->getType()->isIntegerType() && > + !Arg2->getType()->isUnsignedIntegerType()) { > + S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) > + << getFunctionName(Call) << S.Context.UnsignedIntTy > + << Arg2->getSourceRange(); > + return true; > + } > + > + // check packet type T > + if (checkOpenCLPipePacketType(S, Call, 3)) > + return true; > + } break; > + default: > + S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_arg_num) > + << getFunctionName(Call) << Call->getSourceRange(); > + return true; > + } > + > + return false; > +} > + > +// \brief Performs a semantic analysis on the {work_group_/sub_group_ > +// /_}reserve_{read/write}_pipe > +// \param S Reference to the semantic analyzer. > +// \param Call The call to the builtin function to be analyzed. > +// \return True if a semantic error was found, false otherwise. > +static bool SemaBuiltinReserveRWPipe(Sema &S, CallExpr *Call) { > + if (checkArgCount(S, Call, 2)) > + return true; > + > + if (checkOpenCLPipeArg(S, Call)) > + return true; > + > + // check the reserve size > + if (!Call->getArg(1)->getType()->isIntegerType() && > + !Call->getArg(1)->getType()->isUnsignedIntegerType()) { > + S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) > + << getFunctionName(Call) << S.Context.UnsignedIntTy > + << Call->getArg(1)->getSourceRange(); > + return true; > + } > + > + return false; > +} > + > +// \brief Performs a semantic analysis on {work_group_/sub_group_ > +// /_}commit_{read/write}_pipe > +// \param S Reference to the semantic analyzer. > +// \param Call The call to the builtin function to be analyzed. > +// \return True if a semantic error was found, false otherwise. > +static bool SemaBuiltinCommitRWPipe(Sema &S, CallExpr *Call) { > + if (checkArgCount(S, Call, 2)) > + return true; > + > + if (checkOpenCLPipeArg(S, Call)) > + return true; > + > + // check reserve_id_t > + if (!Call->getArg(1)->getType()->isReserveIDT()) { > + S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) > + << getFunctionName(Call) << S.Context.OCLReserveIDTy > + << Call->getArg(1)->getSourceRange(); > + return true; > + } > + > + return false; > +} > + > +// \brief Performs a semantic analysis on the call to built-in Pipe > +// Query Functions. > +// \param S Reference to the semantic analyzer. > +// \param Call The call to the builtin function to be analyzed. > +// \return True if a semantic error was found, false otherwise. > +static bool SemaBuiltinPipePackets(Sema &S, CallExpr *Call) { > + if (checkArgCount(S, Call, 1)) > + return true; > + > + if (!Call->getArg(0)->getType()->isPipeType()) { > + S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_first_arg) > + << getFunctionName(Call) << Call->getArg(0)->getSourceRange(); > + return true; > + } > + > + return false; > +} > + > ExprResult > Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, > CallExpr *TheCall) { @@ -563,6 +749,40 > @@ Sema::CheckBuiltinFunctionCall(FunctionD > > TheCall->setType(Context.VoidPtrTy); > break; > + case Builtin::BIread_pipe: > + case Builtin::BIwrite_pipe: > + // Since those two functions are declared with var args, we need a > semantic > + // check for the argument. > + if (SemaBuiltinRWPipe(*this, TheCall)) > + return ExprError(); > + break; > + case Builtin::BIreserve_read_pipe: > + case Builtin::BIreserve_write_pipe: > + case Builtin::BIwork_group_reserve_read_pipe: > + case Builtin::BIwork_group_reserve_write_pipe: > + case Builtin::BIsub_group_reserve_read_pipe: > + case Builtin::BIsub_group_reserve_write_pipe: > + if (SemaBuiltinReserveRWPipe(*this, TheCall)) > + return ExprError(); > + // Since return type of reserve_read/write_pipe built-in function is > + // reserve_id_t, which is not defined in the builtin def file , we used > int > + // as return type and need to override the return type of these > functions. > + TheCall->setType(Context.OCLReserveIDTy); > + break; > + case Builtin::BIcommit_read_pipe: > + case Builtin::BIcommit_write_pipe: > + case Builtin::BIwork_group_commit_read_pipe: > + case Builtin::BIwork_group_commit_write_pipe: > + case Builtin::BIsub_group_commit_read_pipe: > + case Builtin::BIsub_group_commit_write_pipe: > + if (SemaBuiltinCommitRWPipe(*this, TheCall)) > + return ExprError(); > + break; > + case Builtin::BIget_pipe_num_packets: > + case Builtin::BIget_pipe_max_packets: > + if (SemaBuiltinPipePackets(*this, TheCall)) > + return ExprError(); > + break; > > } > > > Added: cfe/trunk/test/CodeGenOpenCL/pipe_builtin.cl > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenOpenCL/pipe_ > builtin.cl?rev=258782&view=auto > ====================================================================== > ======== > --- cfe/trunk/test/CodeGenOpenCL/pipe_builtin.cl (added) > +++ cfe/trunk/test/CodeGenOpenCL/pipe_builtin.cl Mon Jan 25 22:03:48 > +++ 2016 > @@ -0,0 +1,61 @@ > +// RUN: %clang_cc1 -emit-llvm -O0 -cl-std=CL2.0 -o - %s | FileCheck > +%s > + > +// CHECK: %opencl.pipe_t = type opaque // CHECK: %opencl.reserve_id_t > += type opaque > + > +void test1(read_only pipe int p, global int *ptr) { > + // CHECK: call i32 @__read_pipe_2(%opencl.pipe_t* %{{.*}}, i8* > +%{{.*}}) > + read_pipe(p, ptr); > + // CHECK: call %opencl.reserve_id_t* > +@__reserve_read_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}}) > + reserve_id_t rid = reserve_read_pipe(p, 2); > + // CHECK: call i32 @__read_pipe_4(%opencl.pipe_t* %{{.*}}, > +%opencl.reserve_id_t* %{{.*}}, i32 {{.*}}, i8* %{{.*}}) > + read_pipe(p, rid, 2, ptr); > + // CHECK: call void @__commit_read_pipe(%opencl.pipe_t* %{{.*}}, > +%opencl.reserve_id_t* %{{.*}}) > + commit_read_pipe(p, rid); > +} > + > +void test2(write_only pipe int p, global int *ptr) { > + // CHECK: call i32 @__write_pipe_2(%opencl.pipe_t* %{{.*}}, i8* > +%{{.*}}) > + write_pipe(p, ptr); > + // CHECK: call %opencl.reserve_id_t* > +@__reserve_write_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}}) > + reserve_id_t rid = reserve_write_pipe(p, 2); > + // CHECK: call i32 @__write_pipe_4(%opencl.pipe_t* %{{.*}}, > +%opencl.reserve_id_t* %{{.*}}, i32 {{.*}}, i8* %{{.*}}) > + write_pipe(p, rid, 2, ptr); > + // CHECK: call void @__commit_write_pipe(%opencl.pipe_t* %{{.*}}, > +%opencl.reserve_id_t* %{{.*}}) > + commit_write_pipe(p, rid); > +} > + > +void test3(read_only pipe int p, global int *ptr) { > + // CHECK: call %opencl.reserve_id_t* > +@__work_group_reserve_read_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}}) > + reserve_id_t rid = work_group_reserve_read_pipe(p, 2); > + // CHECK: call void @__work_group_commit_read_pipe(%opencl.pipe_t* > +%{{.*}}, %opencl.reserve_id_t* %{{.*}}) > + work_group_commit_read_pipe(p, rid); } > + > +void test4(write_only pipe int p, global int *ptr) { > + // CHECK: call %opencl.reserve_id_t* > +@__work_group_reserve_write_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}}) > + reserve_id_t rid = work_group_reserve_write_pipe(p, 2); > + // CHECK: call void @__work_group_commit_write_pipe(%opencl.pipe_t* > +%{{.*}}, %opencl.reserve_id_t* %{{.*}}) > + work_group_commit_write_pipe(p, rid); } > + > +void test5(read_only pipe int p, global int *ptr) { > + // CHECK: call %opencl.reserve_id_t* > +@__sub_group_reserve_read_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}}) > + reserve_id_t rid = sub_group_reserve_read_pipe(p, 2); > + // CHECK: call void @__sub_group_commit_read_pipe(%opencl.pipe_t* > +%{{.*}}, %opencl.reserve_id_t* %{{.*}}) > + sub_group_commit_read_pipe(p, rid); } > + > +void test6(write_only pipe int p, global int *ptr) { > + // CHECK: call %opencl.reserve_id_t* > +@__sub_group_reserve_write_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}}) > + reserve_id_t rid = sub_group_reserve_write_pipe(p, 2); > + // CHECK: call void @__sub_group_commit_write_pipe(%opencl.pipe_t* > +%{{.*}}, %opencl.reserve_id_t* %{{.*}}) > + sub_group_commit_write_pipe(p, rid); } > + > +void test7(write_only pipe int p, global int *ptr) { > + // CHECK: call i32 @__get_pipe_num_packets(%opencl.pipe_t* %{{.*}}) > + *ptr = get_pipe_num_packets(p); > + // CHECK: call i32 @__get_pipe_max_packets(%opencl.pipe_t* %{{.*}}) > + *ptr = get_pipe_max_packets(p); > +} > > Added: cfe/trunk/test/SemaOpenCL/invalid-pipe-builtin-cl2.0.cl > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaOpenCL/invalid- > pipe-builtin-cl2.0.cl?rev=258782&view=auto > ====================================================================== > ======== > --- cfe/trunk/test/SemaOpenCL/invalid-pipe-builtin-cl2.0.cl (added) > +++ cfe/trunk/test/SemaOpenCL/invalid-pipe-builtin-cl2.0.cl Mon Jan 25 > +++ 22:03:48 2016 > @@ -0,0 +1,55 @@ > +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0 > + > +void test1(read_only pipe int p, global int* ptr){ > + int tmp; > + reserve_id_t rid; > + > + // read/write_pipe > + read_pipe(tmp, p); // expected-error {{first argument to read_pipe must > be a pipe type}} > + read_pipe(p); // expected-error {{invalid number of arguments to > function: read_pipe}} > + read_pipe(p, tmp, tmp, ptr); // expected-error {{invalid argument type > to function read_pipe (expecting 'reserve_id_t')}} > + read_pipe(p, rid, rid, ptr); // expected-error {{invalid argument type > to function read_pipe (expecting 'unsigned int')}} > + read_pipe(p, tmp); // expected-error {{invalid argument type to function > read_pipe (expecting 'int *')}} > + write_pipe(p, ptr); // expected-error {{invalid pipe access modifier > (expecting write_only)}} > + write_pipe(p, rid, tmp, ptr); // expected-error {{invalid pipe access > modifier (expecting write_only)}} > + > + // reserve_read/write_pipe > + reserve_read_pipe(p, ptr); // expected-error{{invalid argument type to > function reserve_read_pipe (expecting 'unsigned int')}} > + work_group_reserve_read_pipe(tmp, tmp); // expected-error{{first > argument to work_group_reserve_read_pipe must be a pipe type}} > + sub_group_reserve_write_pipe(p, tmp); // expected-error{{invalid pipe > access modifier (expecting write_only)}} > + > + // commit_read/write_pipe > + commit_read_pipe(tmp, rid); // expected-error{{first argument to > commit_read_pipe must be a pipe type}} > + work_group_commit_read_pipe(p, tmp); // expected-error{{invalid > argument type to function work_group_commit_read_pipe (expecting > 'reserve_id_t')}} > + sub_group_commit_write_pipe(p, tmp); // expected-error{{nvalid pipe > access modifier (expecting write_only)}} > +} > + > +void test2(write_only pipe int p, global int* ptr){ > + int tmp; > + reserve_id_t rid; > + > + // read/write_pipe > + write_pipe(tmp, p); // expected-error {{first argument to write_pipe > must be a pipe type}} > + write_pipe(p); // expected-error {{invalid number of arguments to > function: write_pipe}} > + write_pipe(p, tmp, tmp, ptr); // expected-error {{invalid argument type > to function write_pipe (expecting 'reserve_id_t')}} > + write_pipe(p, rid, rid, ptr); // expected-error {{invalid argument type > to function write_pipe (expecting 'unsigned int')}} > + write_pipe(p, tmp); // expected-error {{invalid argument type to > function write_pipe (expecting 'int *')}} > + read_pipe(p, ptr); // expected-error {{invalid pipe access modifier > (expecting read_only)}} > + read_pipe(p, rid, tmp, ptr); // expected-error {{invalid pipe access > modifier (expecting read_only)}} > + > + // reserve_read/write_pipe > + reserve_write_pipe(p, ptr); // expected-error{{invalid argument type to > function reserve_write_pipe (expecting 'unsigned int')}} > + work_group_reserve_write_pipe(tmp, tmp); // expected-error{{first > argument to work_group_reserve_write_pipe must be a pipe type}} > + sub_group_reserve_read_pipe(p, tmp); // expected-error{{invalid pipe > access modifier (expecting read_only)}} > + > + // commit_read/write_pipe > + commit_write_pipe(tmp, rid); // expected-error{{first argument to > commit_write_pipe must be a pipe type}} > + work_group_commit_write_pipe(p, tmp); // expected-error{{invalid > argument type to function work_group_commit_write_pipe (expecting > 'reserve_id_t')}} > + sub_group_commit_read_pipe(p, tmp); // expected-error{{nvalid pipe > access modifier (expecting read_only)}} > +} > + > +void test3(){ > + int tmp; > + get_pipe_num_packets(tmp); // expected-error {{first argument to > get_pipe_num_packets must be a pipe type}} > + get_pipe_max_packets(tmp); // expected-error {{first argument to > get_pipe_max_packets must be a pipe type}} > +} > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits