<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=utf-8"><meta name=Generator content="Microsoft Word 15 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
        {font-family:SimSun;
        panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:"\@SimSun";
        panose-1:2 1 6 0 3 1 1 1 1 1;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:12.0pt;
        font-family:"Times New Roman",serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
span.EmailStyle17
        {mso-style-type:personal-reply;
        font-family:"Calibri",sans-serif;
        color:#1F497D;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri",sans-serif;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]--></head><body lang=EN-US link=blue vlink=purple><div class=WordSection1><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D'>Sorry about this broken commit. The arc tool patch fuzz seems to have something wrong and I am re-patching it by hand.<o:p></o:p></span></p><p class=MsoNormal><a name="_MailEndCompose"><span style='font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D'><o:p> </o:p></span></a></p><p class=MsoNormal><a name="_____replyseparator"></a><b><span style='font-size:11.0pt;font-family:"Calibri",sans-serif'>From:</span></b><span style='font-size:11.0pt;font-family:"Calibri",sans-serif'> David Majnemer [mailto:david.majnemer@gmail.com] <br><b>Sent:</b> Tuesday, January 26, 2016 10:27 AM<br><b>To:</b> Xiuli Pan <xiulipan@outlook.com><br><b>Cc:</b> cfe-commits <cfe-commits@lists.llvm.org><br><b>Subject:</b> Re: r258773 - [OpenCL] Pipe builtin functions<o:p></o:p></span></p><p class=MsoNormal><o:p> </o:p></p><div><p class=MsoNormal>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><o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p><div><p class=MsoNormal>On Mon, Jan 25, 2016 at 6:06 PM, Xiuli Pan via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>> wrote:<o:p></o:p></p><blockquote style='border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in'><p class=MsoNormal>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" 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" target="_blank">http://reviews.llvm.org/D15914</a><br><br>Added:<br>    cfe/trunk/test/CodeGenOpenCL/<a href="http://pipe_builtin.cl" target="_blank">pipe_builtin.cl</a><br>    cfe/trunk/test/SemaOpenCL/<a href="http://invalid-pipe-builtin-cl2.0.cl" 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" 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" 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" 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" 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" 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" 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" 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" 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" target="_blank">pipe_builtin.cl</a> (added)<br>+++ cfe/trunk/test/CodeGenOpenCL/<a href="http://pipe_builtin.cl" 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" 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" 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" target="_blank">invalid-pipe-builtin-cl2.0.cl</a> (added)<br>+++ cfe/trunk/test/SemaOpenCL/<a href="http://invalid-pipe-builtin-cl2.0.cl" 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" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><o:p></o:p></p></blockquote></div><p class=MsoNormal><o:p> </o:p></p></div></div></body></html>