Thanks for clarifications and feedback. I think there is enough time to improve the patch before the release date.
But I believe Hans has more experience to evaluate potential issues here. I think I am fine to complete this work for the next release instead. I hope Xiuli and others agree too. Anastasia -----Original Message----- From: Hans Wennborg [mailto:hwennb...@google.com] Sent: 03 February 2016 21:42 To: Richard Smith Cc: Anastasia Stulova; cfe-commits; xiuli pan; Pekka Jääskeläinen; nd Subject: Re: r258782 - Recommit: R258773 [OpenCL] Pipe builtin functions On Wed, Feb 3, 2016 at 1:00 PM, Richard Smith <rich...@metafoo.co.uk> wrote: > On Wed, Feb 3, 2016 at 11:08 AM, Anastasia Stulova > <anastasia.stul...@arm.com> wrote: >> >> I think the main reason is that we have committed pipe type before >> the release branch was taken. It appears to have no use without the >> pipe builtin functions. >> >> Are there any risks of adding this now? > > > Based on my post-commit review of the patch, I don't think this is yet > mature enough for 3.8 (in particular, it improperly handles type > sugar, and should be performing argument conversions in SemaChecking > rather than in CGBuiltin). If you're confident that this can be > cleaned up in time, and Hans is prepared to take those cleanup patches > onto the branch too, then I think this is fine to go into 3.8 to finish off > the OpenCL pipe work. I wouldn't be keen on taking those patches. We've already tagged RC2, and I want bugfixes only going forward. I think the reality is that this landed a little too late to make it into the release, and will have to wait until 3.9. - Hans >> -----Original Message----- >> From: meta...@gmail.com [mailto:meta...@gmail.com] On Behalf Of >> Richard Smith >> Sent: 01 February 2016 21:54 >> To: Hans Wennborg >> Cc: xiuli pan; cfe-commits; Pekka Jääskeläinen; Anastasia Stulova >> Subject: Re: r258782 - Recommit: R258773 [OpenCL] Pipe builtin >> functions >> >> On Thu, Jan 28, 2016 at 11:25 AM, Hans Wennborg >> <hwennb...@google.com> >> wrote: >> > 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? >> >> Is there a reason we want to push this new feature into 3.8 rather >> than waiting for the next release? >> >> > 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/ >> >> Bui ltins.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/ >> >> Bui ltins.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/ >> >> Dia gnosticSemaKinds.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/CGBuilti >> >> n.c pp?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/SemaCheckin >> >> g.c pp?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/p >> >> ipe >> >> _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/inva >> >> lid -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