I don't think we have a specific code owner for OpenCL in Clang, which means Richard is the owner.
Richard, what do you think? On Wed, Jan 27, 2016 at 10:08 PM, xiuli pan <xiuli...@outlook.com> wrote: > Hi hans, > > Request to merge it to release 38 > > It adds Pipe BIFs to be used along with Pipe type committed earlier (in > r257254). > > Thanks > Xiuli > > -----Original Message----- > From: cfe-commits [mailto:cfe-commits-boun...@lists.llvm.org] On Behalf Of > Xiuli Pan via cfe-commits > Sent: Tuesday, January 26, 2016 12:04 PM > To: cfe-commits@lists.llvm.org > Subject: r258782 - Recommit: R258773 [OpenCL] Pipe builtin functions > > 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/Builtins.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/Builtins.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. > 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/DiagnosticSemaKinds.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">; > +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?rev=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.cpp?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); > + 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.cpp?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(); > +} > + > +/// 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; > +} > + > +/// 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; > + 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()); > + // 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()) { > + 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()) { > + 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 > + 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