pxli168 created this revision.
pxli168 added reviewers: pekka.jaaskelainen, Anastasia.
pxli168 added subscribers: cfe-commits, bader.

Support for the pipe built-in functions.
The pipe packet type can be user defined structure, we need to handle this in 
clang frontend.
This version is based on bader's opencl support patches. It transform all kinds 
of pipe type in anonymous pipe and identify the actual type by packet size in 
byte, and bitcast pointers to void* to get one function definition.
We may discuss how to handle these pipe built-in functions, I have tried few 
ways and none of them seems to be a perfect solution.

http://reviews.llvm.org/D15914

Files:
  include/clang/Basic/Builtins.def
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/CodeGen/CGBuiltin.cpp
  lib/CodeGen/CGOpenCLRuntime.cpp
  lib/CodeGen/CGOpenCLRuntime.h
  lib/Sema/SemaChecking.cpp

Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -258,6 +258,194 @@
   return false;
 }
 
+/// Returns readable name for a call.
+static StringRef getFunctionName(CallExpr *call) {
+  return cast<FunctionDecl>(call->getCalleeDecl())->getName();
+}
+
+/// Returns OpenCL access qual.
+static OpenCLImageAccessAttr *getOpenCLImageAcces(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_builtin_pipe_first_arg)
+        << getFunctionName(call) << Arg0->getSourceRange();
+    return true;
+  }
+  OpenCLImageAccessAttr *AccessQual =
+      getOpenCLImageAcces(cast<DeclRefExpr>(Arg0)->getDecl());
+  // Validates the access modifier is compatible with the call.
+  // From OpenCL C Specification 6.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;
+  // TODO: For all pipe built-in read is for read_only?
+  if (getFunctionName(call).find("read") != StringRef::npos)
+    // if (getFunctionName(call).startswith("read"))
+    isValid = AccessQual == nullptr || AccessQual->isReadOnly();
+  else
+    isValid = AccessQual != nullptr && AccessQual->isWriteOnly();
+  if (!isValid) {
+    bool ReadOnly = getFunctionName(call).startswith("read");
+    const char *AM = ReadOnly ? "read_only" : "write_only";
+    S.Diag(Arg0->getLocStart(), diag::err_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 (!Argidx->getType()->isPointerType() || !ArgTy ||
+      EltTy != ArgTy->getPointeeType().getTypePtr()) {
+    S.Diag(call->getLocStart(), diag::err_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) {
+
+  if (checkOpenCLPipeArg(S, call))
+    return true;
+
+  // 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: {
+    // 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: {
+    // 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_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_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_builtin_pipe_args_num_mismatch)
+        << getFunctionName(call) << call->getSourceRange();
+    return true;
+  }
+  call->setType(S.getASTContext().IntTy);
+  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 reverse size
+  if (!call->getArg(1)->getType()->isIntegerType() &&
+      !call->getArg(1)->getType()->isUnsignedIntegerType()) {
+    S.Diag(call->getLocStart(), diag::err_builtin_pipe_invalid_arg)
+        << getFunctionName(call) << S.Context.UnsignedIntTy
+        << call->getArg(1)->getSourceRange();
+    return true;
+  }
+
+  call->setType(S.getASTContext().IntTy);
+  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_builtin_pipe_invalid_arg)
+        << getFunctionName(call) << S.Context.OCLReserveIDTy
+        << call->getArg(1)->getSourceRange();
+    return true;
+  }
+
+  call->setType(S.getASTContext().VoidTy);
+  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 SemaBuiltinPipePacketes(Sema &S, CallExpr *call) {
+  if (checkArgCount(S, call, 1))
+    return true;
+
+  if (!call->getArg(0)->getType()->isPipeType()) {
+    S.Diag(call->getLocStart(), diag::err_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 +751,38 @@
 
     TheCall->setType(Context.VoidPtrTy);
     break;
+  case Builtin::BIread_pipe:
+  case Builtin::BIwrite_pipe:
+    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:
+    // Since those two functions are declared with var args, therefore we need
+    // a semantic check for the argument.
+    if (SemaBuiltinReserveRWPipe(*this, TheCall))
+      return ExprError();
+    // We need to override the return type of the call expression.
+    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 (SemaBuiltinPipePacketes(*this, TheCall))
+      return ExprError();
+    break;
 
   }
 
Index: lib/CodeGen/CGOpenCLRuntime.h
===================================================================
--- lib/CodeGen/CGOpenCLRuntime.h
+++ lib/CodeGen/CGOpenCLRuntime.h
@@ -47,8 +47,50 @@
   virtual llvm::Type *convertOpenCLSpecificType(const Type *T);
 
   virtual llvm::Type *getPipeType();
+
+  // \brief Returnes a value which indicates the size in bytes of the pipe
+  // element.
+  virtual llvm::Value *getPipeElemSize(const Expr *PipeArg);
 };
+class Ocl20Mangler {
+public:
+  Ocl20Mangler(llvm::SmallVectorImpl<char> &);
+
+  // \brief Appends the mangled representation of reserve_id_t parameter to the
+  //  mangled string.
+  Ocl20Mangler &appendReservedId();
+
+  // \brief Appends the mangled representation of pipe_t parameter to the
+  //  mangled string.
+  Ocl20Mangler &appendPipe();
+
+  // \brief Appends the mangled representation of 'int' parameter to the
+  //  mangled string.
+  Ocl20Mangler &appendInt();
+
+  // \brief Appends the mangled representation of 'unsigned int' parameter to
+  // the
+  // mangled string.
+  Ocl20Mangler &appendUint();
 
+  // \brief Appends the mangled representation of a pointer.
+  Ocl20Mangler &appendPointer();
+
+  // \brief Appends the mangled representation of void.
+  Ocl20Mangler &appendVoid();
+
+  // \brief Appends the mangled representation of a pointer with a given address
+  // space.
+  // \param addressSapace The address space of the pointer. Valid values are
+  // [0,4].
+  Ocl20Mangler &appendPointer(int addressSapace);
+
+private:
+  // \brief Appends the given string to the mangled prototype.
+  Ocl20Mangler &appendString(llvm::StringRef);
+
+  llvm::SmallVectorImpl<char> *MangledString;
+};
 }
 }
 
Index: lib/CodeGen/CGOpenCLRuntime.cpp
===================================================================
--- lib/CodeGen/CGOpenCLRuntime.cpp
+++ lib/CodeGen/CGOpenCLRuntime.cpp
@@ -110,3 +110,65 @@
 
   return PipeTy;
 }
+
+llvm::Value *CGOpenCLRuntime::getPipeElemSize(const Expr *PipeArg) {
+  const PipeType *PipeTy = PipeArg->getType()->getAs<PipeType>();
+  // The type of the last (implicit) argument to be passed.
+  llvm::Type *Int32Ty = llvm::IntegerType::getInt32Ty(CGM.getLLVMContext());
+  unsigned TypeSizeInBits =
+      CGM.getContext().getTypeSize(PipeTy->getElementType());
+  return llvm::ConstantInt::get(Int32Ty,
+                                TypeSizeInBits / 8, // Size in bytes.
+                                false);
+}
+
+// Ocl20Mangler
+// TODO:Some explation or new name?
+Ocl20Mangler::Ocl20Mangler(llvm::SmallVectorImpl<char> &SS)
+    : MangledString(&SS) {}
+
+Ocl20Mangler &Ocl20Mangler::appendReservedId() {
+  this->appendString("16ocl_reserve_id_t");
+  return *this;
+}
+
+Ocl20Mangler &Ocl20Mangler::appendPipe() {
+  this->appendString("10ocl_pipe_t");
+  return *this;
+}
+
+Ocl20Mangler &Ocl20Mangler::appendInt() {
+  MangledString->push_back('i');
+  return *this;
+}
+
+Ocl20Mangler &Ocl20Mangler::appendUint() {
+  MangledString->push_back('j');
+  return *this;
+}
+
+Ocl20Mangler &Ocl20Mangler::appendVoid() {
+  MangledString->push_back('v');
+  return *this;
+}
+
+Ocl20Mangler &Ocl20Mangler::appendPointer() {
+  this->appendString("P");
+  return *this;
+}
+
+Ocl20Mangler &Ocl20Mangler::appendPointer(int addressSpace) {
+  assert(addressSpace >= 0 && addressSpace <= 4 &&
+         "Illegal address space for OpenCL");
+  if (!addressSpace)
+    return appendPointer();
+
+  this->appendString("PU3AS");
+  MangledString->push_back('0' + addressSpace);
+  return *this;
+}
+
+Ocl20Mangler &Ocl20Mangler::appendString(llvm::StringRef S) {
+  MangledString->append(S.begin(), S.end());
+  return *this;
+}
Index: lib/CodeGen/CGBuiltin.cpp
===================================================================
--- lib/CodeGen/CGBuiltin.cpp
+++ lib/CodeGen/CGBuiltin.cpp
@@ -14,6 +14,7 @@
 #include "CodeGenFunction.h"
 #include "CGCXXABI.h"
 #include "CGObjCRuntime.h"
+#include "CGOpenCLRuntime.h"
 #include "CodeGenModule.h"
 #include "TargetInfo.h"
 #include "clang/AST/ASTContext.h"
@@ -1963,6 +1964,194 @@
       return RValue::get(llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy));
     break;
   }
+
+  case Builtin::BIread_pipe:
+  case Builtin::BIwrite_pipe: {
+    const char *NamePrefix =
+        (BuiltinID == Builtin::BIread_pipe) ? "_Z9read_pipe" : "_Z10write_pipe";
+    llvm::LLVMContext &Ctxt = getLLVMContext();
+    Value *Arg0 = EmitScalarExpr(E->getArg(0)),
+          *Arg1 = EmitScalarExpr(E->getArg(1));
+    Value *PacketSize = CGOpenCLRuntime(CGM).getPipeElemSize(E->getArg(0));
+    llvm::SmallString<128> Out;
+
+    // Type of the packet parameter.
+    llvm::Type *I8PTy = llvm::PointerType::get(llvm::Type::getInt8Ty(Ctxt), 4U);
+
+    // Testing which overloaded version we should generate the call for.
+    if (2U == E->getNumArgs()) {
+      // The name is mangled with hard-coded, since we would like to avoid the
+      // AST rewrite.
+      SmallString<64> SS;
+      Ocl20Mangler Mangler(SS);
+      Mangler.appendPointer(1)
+          .appendPipe()
+          .appendPointer(4)
+          .appendVoid()
+          .appendInt();
+
+      llvm::StringRef ManglerRef = SS.str();
+      Twine NameTwine(NamePrefix, ManglerRef);
+      StringRef Name = NameTwine.toStringRef(Out);
+      // Re-Creating the function type for this call, since the original type
+      // is variadic, which we convert to a specific type to match this call.
+      llvm::Type *ArgTys[] = {Arg0->getType(), I8PTy, Int32Ty};
+      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, PacketSize}));
+    } else {
+      assert(4 == E->getNumArgs() &&
+             "Illegal number of parameters to pipe function");
+
+      SmallString<64> SS;
+      Ocl20Mangler Mangler(SS);
+      Mangler.appendPointer(1)
+          .appendPipe()
+          .appendReservedId()
+          .appendUint()
+          .appendPointer(4)
+          .appendVoid()
+          .appendInt();
+
+      llvm::StringRef ManglerRef = SS.str();
+      Twine NameTwine(NamePrefix, ManglerRef);
+      StringRef Name = NameTwine.toStringRef(Out);
+      llvm::Type *ArgTys[] = {Arg0->getType(), Arg1->getType(), Int32Ty, I8PTy,
+                              Int32Ty};
+      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 (Verified by Sema, but
+      // we may need to cast it.
+      if (Arg2->getType() != Int32Ty)
+        Arg2 = Builder.CreateZExtOrTrunc(Arg2, Int32Ty);
+      return RValue::get(
+          Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name),
+                             {Arg0, Arg1, Arg2, BCast, PacketSize}));
+    }
+  }
+  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 *NamePrefix;
+    if (BuiltinID == Builtin::BIreserve_read_pipe)
+      NamePrefix = "_Z17reserve_read_pipe";
+    else if (BuiltinID == Builtin::BIreserve_write_pipe)
+      NamePrefix = "_Z18reserve_write_pipe";
+    else if (BuiltinID == Builtin::BIwork_group_reserve_read_pipe)
+      NamePrefix = "_Z28work_group_reserve_read_pipe";
+    else if (BuiltinID == Builtin::BIwork_group_reserve_write_pipe)
+      NamePrefix = "_Z29work_group_reserve_write_pipe";
+    else if (BuiltinID == Builtin::BIsub_group_reserve_read_pipe)
+      NamePrefix = "_Z27sub_group_reserve_read_pipe";
+    else
+      NamePrefix = "_Z28sub_group_reserve_write_pipe";
+
+    SmallString<64> SS;
+    Ocl20Mangler Mangler(SS);
+    Mangler.appendPointer(1).appendPipe().appendUint().appendInt();
+    llvm::StringRef ManglerRef = SS.str();
+    llvm::Twine NameTwine(NamePrefix, ManglerRef);
+
+    llvm::SmallString<128> Out;
+    llvm::StringRef Name = NameTwine.toStringRef(Out);
+    CGOpenCLRuntime CGOcl(CGM);
+
+    Value *PacketSize = CGOcl.getPipeElemSize(E->getArg(0));
+    Value *Arg0 = EmitScalarExpr(E->getArg(0)),
+          *Arg1 = EmitScalarExpr(E->getArg(1));
+    llvm::Type *ReservedIDTy = ConvertType(getContext().OCLReserveIDTy);
+
+    // Building the fucntion's prototype.
+    llvm::Type *ArgTys[] = {Arg0->getType(), Int32Ty, Int32Ty};
+    llvm::FunctionType *FTy = llvm::FunctionType::get(
+        ReservedIDTy, llvm::ArrayRef<llvm::Type *>(ArgTys), false);
+    // We know the third argument is an integer type (Verified by Sema, but
+    // we may need to cast it.
+    if (Arg1->getType() != Int32Ty)
+      Arg1 = Builder.CreateZExtOrTrunc(Arg1, Int32Ty);
+    return RValue::get(Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name),
+                                          {Arg0, Arg1, PacketSize}));
+  }
+  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: {
+    // Composing the mangled name for the function.
+    const char *NamePrefix;
+    if (BuiltinID == Builtin::BIcommit_read_pipe)
+      NamePrefix = "_Z16commit_read_pipe";
+    else if (BuiltinID == Builtin::BIcommit_write_pipe)
+      NamePrefix = "_Z17commit_write_pipe";
+    else if (BuiltinID == Builtin::BIwork_group_commit_read_pipe)
+      NamePrefix = "_Z27work_group_commit_read_pipe";
+    else if (BuiltinID == Builtin::BIwork_group_commit_write_pipe)
+      NamePrefix = "_Z28work_group_commit_write_pipe";
+    else if (BuiltinID == Builtin::BIsub_group_commit_read_pipe)
+      NamePrefix = "_Z26sub_group_commit_read_pipe";
+    else
+      NamePrefix = "_Z27sub_group_commit_write_pipe";
+
+    SmallString<64> SS;
+    Ocl20Mangler Mangler(SS);
+    Mangler.appendPointer(1).appendPipe().appendReservedId().appendInt();
+    llvm::StringRef ManglerRef = SS.str();
+    llvm::Twine NameTwine(NamePrefix, ManglerRef);
+
+    llvm::SmallString<128> Out;
+    llvm::StringRef Name = NameTwine.toStringRef(Out);
+    CGOpenCLRuntime CGOcl(CGM);
+
+    Value *PacketSize = CGOcl.getPipeElemSize(E->getArg(0));
+    Value *Arg0 = EmitScalarExpr(E->getArg(0)),
+          *Arg1 = EmitScalarExpr(E->getArg(1));
+
+    // Building the function's prototype.
+    llvm::Type *ArgTys[] = {Arg0->getType(), Arg1->getType(), Int32Ty};
+    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, PacketSize}));
+  }
+  case Builtin::BIget_pipe_num_packets:
+  case Builtin::BIget_pipe_max_packets: {
+    // Composing the builtin's name.
+    const char *NamePrefix;
+    if (BuiltinID == Builtin::BIget_pipe_num_packets)
+      NamePrefix = "_Z20get_pipe_num_packets";
+    else
+      NamePrefix = "_Z20get_pipe_max_packets";
+    SmallString<64> SS;
+    Ocl20Mangler Mangler(SS);
+    Mangler.appendPointer(1).appendPipe().appendInt();
+    llvm::StringRef ManglerRef = SS.str();
+    llvm::Twine NameTwine(NamePrefix, ManglerRef);
+    llvm::SmallString<128> Out;
+    llvm::StringRef Name = NameTwine.toStringRef(Out);
+
+    // Building the function's prototype.
+    CGOpenCLRuntime CGOcl(CGM);
+    Value *PacketSize = CGOcl.getPipeElemSize(E->getArg(0));
+    Value *Arg0 = EmitScalarExpr(E->getArg(0));
+    llvm::Type *ArgTys[] = {Arg0->getType(), Int32Ty};
+    llvm::FunctionType *FTy = llvm::FunctionType::get(
+        Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false);
+
+    return RValue::get(Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name),
+                                          {Arg0, PacketSize}));
+  }
   }
 
   // If this is an alias for a lib function (e.g. __builtin_sin), emit
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -7640,6 +7640,17 @@
   "missing actual type specifier for pipe">;
 def err_reference_pipe_type : Error <
   "pipes packet types cannot be of reference type">;
+// Builtin pipe
+def err_builtin_pipe_first_arg : Error<
+  "first argument to %0 must be a pipe type">;
+def err_builtin_pipe_argument_type_mismatch : Error<
+  "argument type doesn't match pipe type">;
+def err_builtin_pipe_args_num_mismatch : Error<
+  "invalid number of arguments to function: %0">;
+def err_builtin_pipe_invalid_arg : Error<
+  "invalid argument type to function %0 (expecting: %1)">;
+def err_builtin_pipe_invalid_access_modifier : Error<
+  "invalid pipe access modifier (expecting %0)">;
 def err_opencl_no_main : Error<"%select{function|kernel}0 cannot be called 'main'">;
 def err_opencl_kernel_attr :
   Error<"attribute %0 can only be applied to a kernel function">;
Index: include/clang/Basic/Builtins.def
===================================================================
--- include/clang/Basic/Builtins.def
+++ include/clang/Basic/Builtins.def
@@ -1252,6 +1252,32 @@
 BUILTIN(__builtin_nontemporal_store, "v.", "t")
 BUILTIN(__builtin_nontemporal_load, "v.", "t")
 
+// OpenCL 2.0 Pipe functions.
+// We need the variadic prototype, since the packet type could be anything.
+BUILTIN(read_pipe, "i.", "tn")
+BUILTIN(write_pipe, "i.", "tn")
+
+BUILTIN(reserve_read_pipe, "i.", "tn")
+BUILTIN(reserve_write_pipe, "i.", "tn")
+
+BUILTIN(commit_write_pipe, "v.", "tn")
+BUILTIN(commit_read_pipe, "v.", "tn")
+
+BUILTIN(sub_group_reserve_read_pipe, "i.", "tn")
+BUILTIN(sub_group_reserve_write_pipe, "i.", "tn")
+
+BUILTIN(sub_group_commit_read_pipe, "v.", "tn")
+BUILTIN(sub_group_commit_write_pipe, "v.", "tn")
+
+BUILTIN(work_group_reserve_read_pipe, "i.", "tn")
+BUILTIN(work_group_reserve_write_pipe, "i.", "tn")
+
+BUILTIN(work_group_commit_read_pipe, "v.", "tn")
+BUILTIN(work_group_commit_write_pipe, "v.", "tn")
+
+BUILTIN(get_pipe_num_packets, "Ui.", "tn")
+BUILTIN(get_pipe_max_packets, "Ui.", "tn")
+
 #undef BUILTIN
 #undef LIBBUILTIN
 #undef LANGBUILTIN
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to