<div dir="ltr">Reverted in r258775, it broke the build bots: <a href="http://bb.pgr.jp/builders/cmake-clang-x86_64-linux/builds/43853">http://bb.pgr.jp/builders/cmake-clang-x86_64-linux/builds/43853</a><br></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jan 25, 2016 at 6:06 PM, Xiuli Pan via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: pxl<br>
Date: Mon Jan 25 20:06:04 2016<br>
New Revision: 258773<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=258773&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=258773&view=rev</a><br>
Log:<br>
[OpenCL] Pipe builtin functions<br>
<br>
Summary:<br>
Support for the pipe built-in functions for OpenCL 2.0.<br>
The pipe builtin functions may have infinite kinds of element types, one approach<br>
would be to just generate calls that would always use generic types such as void*.<br>
This patch is based on bader's opencl support patch on SPIR-V branch.<br>
<br>
Reviewers: Anastasia, pekka.jaaskelainen<br>
<br>
Subscribers: keryell, bader, cfe-commits<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D15914" rel="noreferrer" target="_blank">http://reviews.llvm.org/D15914</a><br>
<br>
Added:<br>
cfe/trunk/test/CodeGenOpenCL/<a href="http://pipe_builtin.cl" rel="noreferrer" target="_blank">pipe_builtin.cl</a><br>
cfe/trunk/test/SemaOpenCL/<a href="http://invalid-pipe-builtin-cl2.0.cl" rel="noreferrer" target="_blank">invalid-pipe-builtin-cl2.0.cl</a><br>
Modified:<br>
cfe/trunk/include/clang/Basic/Builtins.def<br>
cfe/trunk/include/clang/Basic/Builtins.h<br>
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
cfe/trunk/lib/Basic/Builtins.cpp<br>
cfe/trunk/lib/CodeGen/CGBuiltin.cpp<br>
cfe/trunk/lib/Sema/SemaChecking.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Basic/Builtins.def<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.def?rev=258773&r1=258772&r2=258773&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.def?rev=258773&r1=258772&r2=258773&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Basic/Builtins.def (original)<br>
+++ cfe/trunk/include/clang/Basic/Builtins.def Mon Jan 25 20:06:04 2016<br>
@@ -1252,6 +1252,32 @@ BUILTIN(__builtin___get_unsafe_stack_ptr<br>
BUILTIN(__builtin_nontemporal_store, "v.", "t")<br>
BUILTIN(__builtin_nontemporal_load, "v.", "t")<br>
<br>
+// OpenCL v2.0 s6.13.16, s9.17.3.5 - Pipe functions.<br>
+// We need the generic prototype, since the packet type could be anything.<br>
+LANGBUILTIN(read_pipe, "i.", "tn", OCLC_LANG)<br>
+LANGBUILTIN(write_pipe, "i.", "tn", OCLC_LANG)<br>
+<br>
+LANGBUILTIN(reserve_read_pipe, "i.", "tn", OCLC_LANG)<br>
+LANGBUILTIN(reserve_write_pipe, "i.", "tn", OCLC_LANG)<br>
+<br>
+LANGBUILTIN(commit_write_pipe, "v.", "tn", OCLC_LANG)<br>
+LANGBUILTIN(commit_read_pipe, "v.", "tn", OCLC_LANG)<br>
+<br>
+LANGBUILTIN(sub_group_reserve_read_pipe, "i.", "tn", OCLC_LANG)<br>
+LANGBUILTIN(sub_group_reserve_write_pipe, "i.", "tn", OCLC_LANG)<br>
+<br>
+LANGBUILTIN(sub_group_commit_read_pipe, "v.", "tn", OCLC_LANG)<br>
+LANGBUILTIN(sub_group_commit_write_pipe, "v.", "tn", OCLC_LANG)<br>
+<br>
+LANGBUILTIN(work_group_reserve_read_pipe, "i.", "tn", OCLC_LANG)<br>
+LANGBUILTIN(work_group_reserve_write_pipe, "i.", "tn", OCLC_LANG)<br>
+<br>
+LANGBUILTIN(work_group_commit_read_pipe, "v.", "tn", OCLC_LANG)<br>
+LANGBUILTIN(work_group_commit_write_pipe, "v.", "tn", OCLC_LANG)<br>
+<br>
+LANGBUILTIN(get_pipe_num_packets, "Ui.", "tn", OCLC_LANG)<br>
+LANGBUILTIN(get_pipe_max_packets, "Ui.", "tn", OCLC_LANG)<br>
+<br>
#undef BUILTIN<br>
#undef LIBBUILTIN<br>
#undef LANGBUILTIN<br>
<br>
Modified: cfe/trunk/include/clang/Basic/Builtins.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.h?rev=258773&r1=258772&r2=258773&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.h?rev=258773&r1=258772&r2=258773&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Basic/Builtins.h (original)<br>
+++ cfe/trunk/include/clang/Basic/Builtins.h Mon Jan 25 20:06:04 2016<br>
@@ -36,6 +36,7 @@ enum LanguageID {<br>
CXX_LANG = 0x4, // builtin for cplusplus only.<br>
OBJC_LANG = 0x8, // builtin for objective-c and objective-c++<br>
MS_LANG = 0x10, // builtin requires MS mode.<br>
+ OCLC_LANG = 0x20,// builtin for OpenCL C only.<br>
ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages.<br>
ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU mode.<br>
ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG // builtin requires MS mode.<br>
<br>
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=258773&r1=258772&r2=258773&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=258773&r1=258772&r2=258773&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Jan 25 20:06:04 2016<br>
@@ -7680,6 +7680,16 @@ def err_atomic_init_constant : Error<<br>
def err_opencl_implicit_vector_conversion : Error<<br>
"implicit conversions between vector types (%0 and %1) are not permitted">;<br>
<br>
+// OpenCL v2.0 s6.13.6 -- Builtin Pipe Functions<br>
+def err_opencl_builtin_pipe_first_arg : Error<<br>
+ "first argument to %0 must be a pipe type">;<br>
+def err_opencl_builtin_pipe_arg_num : Error<<br>
+ "invalid number of arguments to function: %0">;<br>
+def err_opencl_builtin_pipe_invalid_arg : Error<<br>
+ "invalid argument type to function %0 (expecting %1)">;<br>
+def err_opencl_builtin_pipe_invalid_access_modifier : Error<<br>
+ "invalid pipe access modifier (expecting %0)">;<br>
+<br>
// OpenCL Section 6.8.g<br>
def err_opencl_unknown_type_specifier : Error<<br>
"OpenCL does not support the '%0' %select{type qualifier|storage class specifier}1">;<br>
<br>
Modified: cfe/trunk/lib/Basic/Builtins.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Builtins.cpp?rev=258773&r1=258772&r2=258773&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Builtins.cpp?rev=258773&r1=258772&r2=258773&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Basic/Builtins.cpp (original)<br>
+++ cfe/trunk/lib/Basic/Builtins.cpp Mon Jan 25 20:06:04 2016<br>
@@ -69,7 +69,8 @@ bool Builtin::Context::builtinIsSupporte<br>
bool MSModeUnsupported =<br>
!LangOpts.MicrosoftExt && (BuiltinInfo.Langs & MS_LANG);<br>
bool ObjCUnsupported = !LangOpts.ObjC1 && BuiltinInfo.Langs == OBJC_LANG;<br>
- return !BuiltinsUnsupported && !MathBuiltinsUnsupported &&<br>
+ bool OclCUnsupported = !LangOpts.OpenCL && BuiltinInfo.Langs == OCLC_LANG;<br>
+ return !BuiltinsUnsupported && !MathBuiltinsUnsupported && !OclCUnsupported &&<br>
!GnuModeUnsupported && !MSModeUnsupported && !ObjCUnsupported;<br>
}<br>
<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=258773&r1=258772&r2=258773&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=258773&r1=258772&r2=258773&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Mon Jan 25 20:06:04 2016<br>
@@ -3341,6 +3341,141 @@ Value *CodeGenFunction::EmitCommonNeonBu<br>
}<br>
return SV;<br>
}<br>
+<br>
+ // OpenCL v2.0 s6.13.16.2, Built-in pipe read and write functions<br>
+ case Builtin::BIread_pipe:<br>
+ case Builtin::BIwrite_pipe: {<br>
+ Value *Arg0 = EmitScalarExpr(E->getArg(0)),<br>
+ *Arg1 = EmitScalarExpr(E->getArg(1));<br>
+<br>
+ // Type of the generic packet parameter.<br>
+ unsigned GenericAS =<br>
+ getContext().getTargetAddressSpace(LangAS::opencl_generic);<br>
+ llvm::Type *I8PTy = llvm::PointerType::get(<br>
+ llvm::Type::getInt8Ty(getLLVMContext()), GenericAS);<br>
+<br>
+ // Testing which overloaded version we should generate the call for.<br>
+ if (2U == E->getNumArgs()) {<br>
+ const char *Name = (BuiltinID == Builtin::BIread_pipe) ? "__read_pipe_2"<br>
+ : "__write_pipe_2";<br>
+ // Creating a generic function type to be able to call with any builtin or<br>
+ // user defined type.<br>
+ llvm::Type *ArgTys[] = {Arg0->getType(), I8PTy};<br>
+ llvm::FunctionType *FTy = llvm::FunctionType::get(<br>
+ Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false);<br>
+ Value *BCast = Builder.CreatePointerCast(Arg1, I8PTy);<br>
+ return RValue::get(Builder.CreateCall(<br>
+ CGM.CreateRuntimeFunction(FTy, Name), {Arg0, BCast}));<br>
+ } else {<br>
+ assert(4 == E->getNumArgs() &&<br>
+ "Illegal number of parameters to pipe function");<br>
+ const char *Name = (BuiltinID == Builtin::BIread_pipe) ? "__read_pipe_4"<br>
+ : "__write_pipe_4";<br>
+<br>
+ llvm::Type *ArgTys[] = {Arg0->getType(), Arg1->getType(), Int32Ty, I8PTy};<br>
+ Value *Arg2 = EmitScalarExpr(E->getArg(2)),<br>
+ *Arg3 = EmitScalarExpr(E->getArg(3));<br>
+ llvm::FunctionType *FTy = llvm::FunctionType::get(<br>
+ Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false);<br>
+ Value *BCast = Builder.CreatePointerCast(Arg3, I8PTy);<br>
+ // We know the third argument is an integer type, but we may need to cast<br>
+ // it to i32.<br>
+ if (Arg2->getType() != Int32Ty)<br>
+ Arg2 = Builder.CreateZExtOrTrunc(Arg2, Int32Ty);<br>
+ return RValue::get(Builder.CreateCall(<br>
+ CGM.CreateRuntimeFunction(FTy, Name), {Arg0, Arg1, Arg2, BCast}));<br>
+ }<br>
+ }<br>
+ // OpenCL v2.0 s6.13.16 ,s9.17.3.5 - Built-in pipe reserve read and write<br>
+ // functions<br>
+ case Builtin::BIreserve_read_pipe:<br>
+ case Builtin::BIreserve_write_pipe:<br>
+ case Builtin::BIwork_group_reserve_read_pipe:<br>
+ case Builtin::BIwork_group_reserve_write_pipe:<br>
+ case Builtin::BIsub_group_reserve_read_pipe:<br>
+ case Builtin::BIsub_group_reserve_write_pipe: {<br>
+ // Composing the mangled name for the function.<br>
+ const char *Name;<br>
+ if (BuiltinID == Builtin::BIreserve_read_pipe)<br>
+ Name = "__reserve_read_pipe";<br>
+ else if (BuiltinID == Builtin::BIreserve_write_pipe)<br>
+ Name = "__reserve_write_pipe";<br>
+ else if (BuiltinID == Builtin::BIwork_group_reserve_read_pipe)<br>
+ Name = "__work_group_reserve_read_pipe";<br>
+ else if (BuiltinID == Builtin::BIwork_group_reserve_write_pipe)<br>
+ Name = "__work_group_reserve_write_pipe";<br>
+ else if (BuiltinID == Builtin::BIsub_group_reserve_read_pipe)<br>
+ Name = "__sub_group_reserve_read_pipe";<br>
+ else<br>
+ Name = "__sub_group_reserve_write_pipe";<br>
+<br>
+ Value *Arg0 = EmitScalarExpr(E->getArg(0)),<br>
+ *Arg1 = EmitScalarExpr(E->getArg(1));<br>
+ llvm::Type *ReservedIDTy = ConvertType(getContext().OCLReserveIDTy);<br>
+<br>
+ // Building the generic function prototype.<br>
+ llvm::Type *ArgTys[] = {Arg0->getType(), Int32Ty};<br>
+ llvm::FunctionType *FTy = llvm::FunctionType::get(<br>
+ ReservedIDTy, llvm::ArrayRef<llvm::Type *>(ArgTys), false);<br>
+ // We know the second argument is an integer type, but we may need to cast<br>
+ // it to i32.<br>
+ if (Arg1->getType() != Int32Ty)<br>
+ Arg1 = Builder.CreateZExtOrTrunc(Arg1, Int32Ty);<br>
+ return RValue::get(<br>
+ Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), {Arg0, Arg1}));<br>
+ }<br>
+ // OpenCL v2.0 s6.13.16 ,s9.17.3.5 - Built-in pipe commit read and write<br>
+ // functions<br>
+ case Builtin::BIcommit_read_pipe:<br>
+ case Builtin::BIcommit_write_pipe:<br>
+ case Builtin::BIwork_group_commit_read_pipe:<br>
+ case Builtin::BIwork_group_commit_write_pipe:<br>
+ case Builtin::BIsub_group_commit_read_pipe:<br>
+ case Builtin::BIsub_group_commit_write_pipe: {<br>
+ const char *Name;<br>
+ if (BuiltinID == Builtin::BIcommit_read_pipe)<br>
+ Name = "__commit_read_pipe";<br>
+ else if (BuiltinID == Builtin::BIcommit_write_pipe)<br>
+ Name = "__commit_write_pipe";<br>
+ else if (BuiltinID == Builtin::BIwork_group_commit_read_pipe)<br>
+ Name = "__work_group_commit_read_pipe";<br>
+ else if (BuiltinID == Builtin::BIwork_group_commit_write_pipe)<br>
+ Name = "__work_group_commit_write_pipe";<br>
+ else if (BuiltinID == Builtin::BIsub_group_commit_read_pipe)<br>
+ Name = "__sub_group_commit_read_pipe";<br>
+ else<br>
+ Name = "__sub_group_commit_write_pipe";<br>
+<br>
+ Value *Arg0 = EmitScalarExpr(E->getArg(0)),<br>
+ *Arg1 = EmitScalarExpr(E->getArg(1));<br>
+<br>
+ // Building the generic function prototype.<br>
+ llvm::Type *ArgTys[] = {Arg0->getType(), Arg1->getType()};<br>
+ llvm::FunctionType *FTy =<br>
+ llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()),<br>
+ llvm::ArrayRef<llvm::Type *>(ArgTys), false);<br>
+<br>
+ return RValue::get(<br>
+ Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), {Arg0, Arg1}));<br>
+ }<br>
+ // OpenCL v2.0 s6.13.16.4 Built-in pipe query functions<br>
+ case Builtin::BIget_pipe_num_packets:<br>
+ case Builtin::BIget_pipe_max_packets: {<br>
+ const char *Name;<br>
+ if (BuiltinID == Builtin::BIget_pipe_num_packets)<br>
+ Name = "__get_pipe_num_packets";<br>
+ else<br>
+ Name = "__get_pipe_max_packets";<br>
+<br>
+ // Building the generic function prototype.<br>
+ Value *Arg0 = EmitScalarExpr(E->getArg(0));<br>
+ llvm::Type *ArgTys[] = {Arg0->getType()};<br>
+ llvm::FunctionType *FTy = llvm::FunctionType::get(<br>
+ Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false);<br>
+<br>
+ return RValue::get(<br>
+ Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), {Arg0}));<br>
+ }<br>
}<br>
<br>
assert(Int && "Expected valid intrinsic number");<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=258773&r1=258772&r2=258773&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=258773&r1=258772&r2=258773&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Mon Jan 25 20:06:04 2016<br>
@@ -258,6 +258,192 @@ static bool SemaBuiltinSEHScopeCheck(Sem<br>
return false;<br>
}<br>
<br>
+/// Returns readable name for a call.<br>
+static StringRef getFunctionName(CallExpr *Call) {<br>
+ return cast<FunctionDecl>(Call->getCalleeDecl())->getName();<br>
+}<br>
+<br>
+/// Returns OpenCL access qual.<br>
+// TODO: Refine OpenCLImageAccessAttr to OpenCLAccessAttr since pipe can use<br>
+// it too<br>
+static OpenCLImageAccessAttr *getOpenCLArgAccess(const Decl *D) {<br>
+ if (D->hasAttr<OpenCLImageAccessAttr>())<br>
+ return D->getAttr<OpenCLImageAccessAttr>();<br>
+ return nullptr;<br>
+}<br>
+<br>
+/// Returns true if pipe element type is different from the pointer.<br>
+static bool checkOpenCLPipeArg(Sema &S, CallExpr *Call) {<br>
+ const Expr *Arg0 = Call->getArg(0);<br>
+ // First argument type should always be pipe.<br>
+ if (!Arg0->getType()->isPipeType()) {<br>
+ S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_first_arg)<br>
+ << getFunctionName(Call) << Arg0->getSourceRange();<br>
+ return true;<br>
+ }<br>
+ OpenCLImageAccessAttr *AccessQual =<br>
+ getOpenCLArgAccess(cast<DeclRefExpr>(Arg0)->getDecl());<br>
+ // Validates the access qualifier is compatible with the call.<br>
+ // OpenCL v2.0 s6.13.16 - The access qualifiers for pipe should only be<br>
+ // read_only and write_only, and assumed to be read_only if no qualifier is<br>
+ // specified.<br>
+ bool isValid = true;<br>
+ bool ReadOnly = getFunctionName(Call).find("read") != StringRef::npos;<br>
+ if (ReadOnly)<br>
+ isValid = AccessQual == nullptr || AccessQual->isReadOnly();<br>
+ else<br>
+ isValid = AccessQual != nullptr && AccessQual->isWriteOnly();<br>
+ if (!isValid) {<br>
+ const char *AM = ReadOnly ? "read_only" : "write_only";<br>
+ S.Diag(Arg0->getLocStart(),<br>
+ diag::err_opencl_builtin_pipe_invalid_access_modifier)<br>
+ << AM << Arg0->getSourceRange();<br>
+ return true;<br>
+ }<br>
+<br>
+ return false;<br>
+}<br>
+<br>
+/// Returns true if pipe element type is different from the pointer.<br>
+static bool checkOpenCLPipePacketType(Sema &S, CallExpr *Call, unsigned Idx) {<br>
+ const Expr *Arg0 = Call->getArg(0);<br>
+ const Expr *ArgIdx = Call->getArg(Idx);<br>
+ const PipeType *PipeTy = cast<PipeType>(Arg0->getType());<br>
+ const Type *EltTy = PipeTy->getElementType().getTypePtr();<br>
+ const PointerType *ArgTy =<br>
+ dyn_cast<PointerType>(ArgIdx->getType().getTypePtr());<br>
+ // The Idx argument should be a pointer and the type of the pointer and<br>
+ // the type of pipe element should also be the same.<br>
+ if (!ArgTy || EltTy != ArgTy->getPointeeType().getTypePtr()) {<br>
+ S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg)<br>
+ << getFunctionName(Call)<br>
+ << S.Context.getPointerType(PipeTy->getElementType())<br>
+ << ArgIdx->getSourceRange();<br>
+ return true;<br>
+ }<br>
+ return false;<br>
+}<br>
+<br>
+// \brief Performs semantic analysis for the read/write_pipe call.<br>
+// \param S Reference to the semantic analyzer.<br>
+// \param Call A pointer to the builtin call.<br>
+// \return True if a semantic error has been found, false otherwise.<br>
+static bool SemaBuiltinRWPipe(Sema &S, CallExpr *Call) {<br>
+ // Two kinds of read/write pipe<br>
+ // From OpenCL C Specification 6.13.16.2 the built-in read/write<br>
+ // functions have following forms.<br>
+ switch (Call->getNumArgs()) {<br>
+ case 2: {<br>
+ if (checkOpenCLPipeArg(S, Call))<br>
+ return true;<br>
+ // The call with 2 arguments should be<br>
+ // read/write_pipe(pipe T, T*)<br>
+ // check packet type T<br>
+ if (checkOpenCLPipePacketType(S, Call, 1))<br>
+ return true;<br>
+ } break;<br>
+<br>
+ case 4: {<br>
+ if (checkOpenCLPipeArg(S, Call))<br>
+ return true;<br>
+ // The call with 4 arguments should be<br>
+ // read/write_pipe(pipe T, reserve_id_t, uint, T*)<br>
+ // check reserve_id_t<br>
+ if (!Call->getArg(1)->getType()->isReserveIDT()) {<br>
+ S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg)<br>
+ << getFunctionName(Call) << S.Context.OCLReserveIDTy<br>
+ << Call->getArg(1)->getSourceRange();<br>
+ return true;<br>
+ }<br>
+<br>
+ // check the index<br>
+ const Expr *Arg2 = Call->getArg(2);<br>
+ if (!Arg2->getType()->isIntegerType() &&<br>
+ !Arg2->getType()->isUnsignedIntegerType()) {<br>
+ S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg)<br>
+ << getFunctionName(Call) << S.Context.UnsignedIntTy<br>
+ << Arg2->getSourceRange();<br>
+ return true;<br>
+ }<br>
+<br>
+ // check packet type T<br>
+ if (checkOpenCLPipePacketType(S, Call, 3))<br>
+ return true;<br>
+ } break;<br>
+ default:<br>
+ S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_arg_num)<br>
+ << getFunctionName(Call) << Call->getSourceRange();<br>
+ return true;<br>
+ }<br>
+<br>
+ return false;<br>
+}<br>
+<br>
+// \brief Performs a semantic analysis on the {work_group_/sub_group_<br>
+// /_}reserve_{read/write}_pipe<br>
+// \param S Reference to the semantic analyzer.<br>
+// \param Call The call to the builtin function to be analyzed.<br>
+// \return True if a semantic error was found, false otherwise.<br>
+static bool SemaBuiltinReserveRWPipe(Sema &S, CallExpr *Call) {<br>
+ if (checkArgCount(S, Call, 2))<br>
+ return true;<br>
+<br>
+ if (checkOpenCLPipeArg(S, Call))<br>
+ return true;<br>
+<br>
+ // check the reserve size<br>
+ if (!Call->getArg(1)->getType()->isIntegerType() &&<br>
+ !Call->getArg(1)->getType()->isUnsignedIntegerType()) {<br>
+ S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg)<br>
+ << getFunctionName(Call) << S.Context.UnsignedIntTy<br>
+ << Call->getArg(1)->getSourceRange();<br>
+ return true;<br>
+ }<br>
+<br>
+ return false;<br>
+}<br>
+<br>
+// \brief Performs a semantic analysis on {work_group_/sub_group_<br>
+// /_}commit_{read/write}_pipe<br>
+// \param S Reference to the semantic analyzer.<br>
+// \param Call The call to the builtin function to be analyzed.<br>
+// \return True if a semantic error was found, false otherwise.<br>
+static bool SemaBuiltinCommitRWPipe(Sema &S, CallExpr *Call) {<br>
+ if (checkArgCount(S, Call, 2))<br>
+ return true;<br>
+<br>
+ if (checkOpenCLPipeArg(S, Call))<br>
+ return true;<br>
+<br>
+ // check reserve_id_t<br>
+ if (!Call->getArg(1)->getType()->isReserveIDT()) {<br>
+ S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg)<br>
+ << getFunctionName(Call) << S.Context.OCLReserveIDTy<br>
+ << Call->getArg(1)->getSourceRange();<br>
+ return true;<br>
+ }<br>
+<br>
+ return false;<br>
+}<br>
+<br>
+// \brief Performs a semantic analysis on the call to built-in Pipe<br>
+// Query Functions.<br>
+// \param S Reference to the semantic analyzer.<br>
+// \param Call The call to the builtin function to be analyzed.<br>
+// \return True if a semantic error was found, false otherwise.<br>
+static bool SemaBuiltinPipePackets(Sema &S, CallExpr *Call) {<br>
+ if (checkArgCount(S, Call, 1))<br>
+ return true;<br>
+<br>
+ if (!Call->getArg(0)->getType()->isPipeType()) {<br>
+ S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_first_arg)<br>
+ << getFunctionName(Call) << Call->getArg(0)->getSourceRange();<br>
+ return true;<br>
+ }<br>
+<br>
+ return false;<br>
+}<br>
+<br>
ExprResult<br>
Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,<br>
CallExpr *TheCall) {<br>
@@ -563,6 +749,40 @@ Sema::CheckBuiltinFunctionCall(FunctionD<br>
<br>
TheCall->setType(Context.VoidPtrTy);<br>
break;<br>
+ case Builtin::BIread_pipe:<br>
+ case Builtin::BIwrite_pipe:<br>
+ // Since those two functions are declared with var args, we need a semantic<br>
+ // check for the argument.<br>
+ if (SemaBuiltinRWPipe(*this, TheCall))<br>
+ return ExprError();<br>
+ break;<br>
+ case Builtin::BIreserve_read_pipe:<br>
+ case Builtin::BIreserve_write_pipe:<br>
+ case Builtin::BIwork_group_reserve_read_pipe:<br>
+ case Builtin::BIwork_group_reserve_write_pipe:<br>
+ case Builtin::BIsub_group_reserve_read_pipe:<br>
+ case Builtin::BIsub_group_reserve_write_pipe:<br>
+ if (SemaBuiltinReserveRWPipe(*this, TheCall))<br>
+ return ExprError();<br>
+ // Since return type of reserve_read/write_pipe built-in function is<br>
+ // reserve_id_t, which is not defined in the builtin def file , we used int<br>
+ // as return type and need to override the return type of these functions.<br>
+ TheCall->setType(Context.OCLReserveIDTy);<br>
+ break;<br>
+ case Builtin::BIcommit_read_pipe:<br>
+ case Builtin::BIcommit_write_pipe:<br>
+ case Builtin::BIwork_group_commit_read_pipe:<br>
+ case Builtin::BIwork_group_commit_write_pipe:<br>
+ case Builtin::BIsub_group_commit_read_pipe:<br>
+ case Builtin::BIsub_group_commit_write_pipe:<br>
+ if (SemaBuiltinCommitRWPipe(*this, TheCall))<br>
+ return ExprError();<br>
+ break;<br>
+ case Builtin::BIget_pipe_num_packets:<br>
+ case Builtin::BIget_pipe_max_packets:<br>
+ if (SemaBuiltinPipePackets(*this, TheCall))<br>
+ return ExprError();<br>
+ break;<br>
<br>
}<br>
<br>
<br>
Added: cfe/trunk/test/CodeGenOpenCL/<a href="http://pipe_builtin.cl" rel="noreferrer" target="_blank">pipe_builtin.cl</a><br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenOpenCL/pipe_builtin.cl?rev=258773&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenOpenCL/pipe_builtin.cl?rev=258773&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGenOpenCL/<a href="http://pipe_builtin.cl" rel="noreferrer" target="_blank">pipe_builtin.cl</a> (added)<br>
+++ cfe/trunk/test/CodeGenOpenCL/<a href="http://pipe_builtin.cl" rel="noreferrer" target="_blank">pipe_builtin.cl</a> Mon Jan 25 20:06:04 2016<br>
@@ -0,0 +1,61 @@<br>
+// RUN: %clang_cc1 -emit-llvm -O0 -cl-std=CL2.0 -o - %s | FileCheck %s<br>
+<br>
+// CHECK: %opencl.pipe_t = type opaque<br>
+// CHECK: %opencl.reserve_id_t = type opaque<br>
+<br>
+void test1(read_only pipe int p, global int *ptr) {<br>
+ // CHECK: call i32 @__read_pipe_2(%opencl.pipe_t* %{{.*}}, i8* %{{.*}})<br>
+ read_pipe(p, ptr);<br>
+ // CHECK: call %opencl.reserve_id_t* @__reserve_read_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}})<br>
+ reserve_id_t rid = reserve_read_pipe(p, 2);<br>
+ // CHECK: call i32 @__read_pipe_4(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}}, i32 {{.*}}, i8* %{{.*}})<br>
+ read_pipe(p, rid, 2, ptr);<br>
+ // CHECK: call void @__commit_read_pipe(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}})<br>
+ commit_read_pipe(p, rid);<br>
+}<br>
+<br>
+void test2(write_only pipe int p, global int *ptr) {<br>
+ // CHECK: call i32 @__write_pipe_2(%opencl.pipe_t* %{{.*}}, i8* %{{.*}})<br>
+ write_pipe(p, ptr);<br>
+ // CHECK: call %opencl.reserve_id_t* @__reserve_write_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}})<br>
+ reserve_id_t rid = reserve_write_pipe(p, 2);<br>
+ // CHECK: call i32 @__write_pipe_4(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}}, i32 {{.*}}, i8* %{{.*}})<br>
+ write_pipe(p, rid, 2, ptr);<br>
+ // CHECK: call void @__commit_write_pipe(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}})<br>
+ commit_write_pipe(p, rid);<br>
+}<br>
+<br>
+void test3(read_only pipe int p, global int *ptr) {<br>
+ // CHECK: call %opencl.reserve_id_t* @__work_group_reserve_read_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}})<br>
+ reserve_id_t rid = work_group_reserve_read_pipe(p, 2);<br>
+ // CHECK: call void @__work_group_commit_read_pipe(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}})<br>
+ work_group_commit_read_pipe(p, rid);<br>
+}<br>
+<br>
+void test4(write_only pipe int p, global int *ptr) {<br>
+ // CHECK: call %opencl.reserve_id_t* @__work_group_reserve_write_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}})<br>
+ reserve_id_t rid = work_group_reserve_write_pipe(p, 2);<br>
+ // CHECK: call void @__work_group_commit_write_pipe(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}})<br>
+ work_group_commit_write_pipe(p, rid);<br>
+}<br>
+<br>
+void test5(read_only pipe int p, global int *ptr) {<br>
+ // CHECK: call %opencl.reserve_id_t* @__sub_group_reserve_read_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}})<br>
+ reserve_id_t rid = sub_group_reserve_read_pipe(p, 2);<br>
+ // CHECK: call void @__sub_group_commit_read_pipe(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}})<br>
+ sub_group_commit_read_pipe(p, rid);<br>
+}<br>
+<br>
+void test6(write_only pipe int p, global int *ptr) {<br>
+ // CHECK: call %opencl.reserve_id_t* @__sub_group_reserve_write_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}})<br>
+ reserve_id_t rid = sub_group_reserve_write_pipe(p, 2);<br>
+ // CHECK: call void @__sub_group_commit_write_pipe(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}})<br>
+ sub_group_commit_write_pipe(p, rid);<br>
+}<br>
+<br>
+void test7(write_only pipe int p, global int *ptr) {<br>
+ // CHECK: call i32 @__get_pipe_num_packets(%opencl.pipe_t* %{{.*}})<br>
+ *ptr = get_pipe_num_packets(p);<br>
+ // CHECK: call i32 @__get_pipe_max_packets(%opencl.pipe_t* %{{.*}})<br>
+ *ptr = get_pipe_max_packets(p);<br>
+}<br>
<br>
Added: cfe/trunk/test/SemaOpenCL/<a href="http://invalid-pipe-builtin-cl2.0.cl" rel="noreferrer" target="_blank">invalid-pipe-builtin-cl2.0.cl</a><br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaOpenCL/invalid-pipe-builtin-cl2.0.cl?rev=258773&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaOpenCL/invalid-pipe-builtin-cl2.0.cl?rev=258773&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaOpenCL/<a href="http://invalid-pipe-builtin-cl2.0.cl" rel="noreferrer" target="_blank">invalid-pipe-builtin-cl2.0.cl</a> (added)<br>
+++ cfe/trunk/test/SemaOpenCL/<a href="http://invalid-pipe-builtin-cl2.0.cl" rel="noreferrer" target="_blank">invalid-pipe-builtin-cl2.0.cl</a> Mon Jan 25 20:06:04 2016<br>
@@ -0,0 +1,55 @@<br>
+// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0<br>
+<br>
+void test1(read_only pipe int p, global int* ptr){<br>
+ int tmp;<br>
+ reserve_id_t rid;<br>
+<br>
+ // read/write_pipe<br>
+ read_pipe(tmp, p); // expected-error {{first argument to read_pipe must be a pipe type}}<br>
+ read_pipe(p); // expected-error {{invalid number of arguments to function: read_pipe}}<br>
+ read_pipe(p, tmp, tmp, ptr); // expected-error {{invalid argument type to function read_pipe (expecting 'reserve_id_t')}}<br>
+ read_pipe(p, rid, rid, ptr); // expected-error {{invalid argument type to function read_pipe (expecting 'unsigned int')}}<br>
+ read_pipe(p, tmp); // expected-error {{invalid argument type to function read_pipe (expecting 'int *')}}<br>
+ write_pipe(p, ptr); // expected-error {{invalid pipe access modifier (expecting write_only)}}<br>
+ write_pipe(p, rid, tmp, ptr); // expected-error {{invalid pipe access modifier (expecting write_only)}}<br>
+<br>
+ // reserve_read/write_pipe<br>
+ reserve_read_pipe(p, ptr); // expected-error{{invalid argument type to function reserve_read_pipe (expecting 'unsigned int')}}<br>
+ work_group_reserve_read_pipe(tmp, tmp); // expected-error{{first argument to work_group_reserve_read_pipe must be a pipe type}}<br>
+ sub_group_reserve_write_pipe(p, tmp); // expected-error{{invalid pipe access modifier (expecting write_only)}}<br>
+<br>
+ // commit_read/write_pipe<br>
+ commit_read_pipe(tmp, rid); // expected-error{{first argument to commit_read_pipe must be a pipe type}}<br>
+ work_group_commit_read_pipe(p, tmp); // expected-error{{invalid argument type to function work_group_commit_read_pipe (expecting 'reserve_id_t')}}<br>
+ sub_group_commit_write_pipe(p, tmp); // expected-error{{nvalid pipe access modifier (expecting write_only)}}<br>
+}<br>
+<br>
+void test2(write_only pipe int p, global int* ptr){<br>
+ int tmp;<br>
+ reserve_id_t rid;<br>
+<br>
+ // read/write_pipe<br>
+ write_pipe(tmp, p); // expected-error {{first argument to write_pipe must be a pipe type}}<br>
+ write_pipe(p); // expected-error {{invalid number of arguments to function: write_pipe}}<br>
+ write_pipe(p, tmp, tmp, ptr); // expected-error {{invalid argument type to function write_pipe (expecting 'reserve_id_t')}}<br>
+ write_pipe(p, rid, rid, ptr); // expected-error {{invalid argument type to function write_pipe (expecting 'unsigned int')}}<br>
+ write_pipe(p, tmp); // expected-error {{invalid argument type to function write_pipe (expecting 'int *')}}<br>
+ read_pipe(p, ptr); // expected-error {{invalid pipe access modifier (expecting read_only)}}<br>
+ read_pipe(p, rid, tmp, ptr); // expected-error {{invalid pipe access modifier (expecting read_only)}}<br>
+<br>
+ // reserve_read/write_pipe<br>
+ reserve_write_pipe(p, ptr); // expected-error{{invalid argument type to function reserve_write_pipe (expecting 'unsigned int')}}<br>
+ work_group_reserve_write_pipe(tmp, tmp); // expected-error{{first argument to work_group_reserve_write_pipe must be a pipe type}}<br>
+ sub_group_reserve_read_pipe(p, tmp); // expected-error{{invalid pipe access modifier (expecting read_only)}}<br>
+<br>
+ // commit_read/write_pipe<br>
+ commit_write_pipe(tmp, rid); // expected-error{{first argument to commit_write_pipe must be a pipe type}}<br>
+ work_group_commit_write_pipe(p, tmp); // expected-error{{invalid argument type to function work_group_commit_write_pipe (expecting 'reserve_id_t')}}<br>
+ sub_group_commit_read_pipe(p, tmp); // expected-error{{nvalid pipe access modifier (expecting read_only)}}<br>
+}<br>
+<br>
+void test3(){<br>
+ int tmp;<br>
+ get_pipe_num_packets(tmp); // expected-error {{first argument to get_pipe_num_packets must be a pipe type}}<br>
+ get_pipe_max_packets(tmp); // expected-error {{first argument to get_pipe_max_packets must be a pipe type}}<br>
+}<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>