r258782 - Recommit: R258773 [OpenCL] Pipe builtin functions

Anastasia Stulova via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 3 11:08:19 PST 2016


I think the main reason is that we have committed pipe type before the release branch was taken. It appears to have no use without the pipe builtin functions.

Are there any risks of adding this now?

Btw, @Richard, I have just updated CODE_OWNERS.TXT putting myself as a code owner of OpenCL (approved by Chris Lattner via cfe-dev). I hope you have no objections to that.

Thanks,
Anastasia

-----Original Message-----
From: metafoo at gmail.com [mailto:metafoo at gmail.com] On Behalf Of Richard Smith
Sent: 01 February 2016 21:54
To: Hans Wennborg
Cc: xiuli pan; cfe-commits; Pekka Jääskeläinen; Anastasia Stulova
Subject: Re: r258782 - Recommit: R258773 [OpenCL] Pipe builtin functions

On Thu, Jan 28, 2016 at 11:25 AM, Hans Wennborg <hwennborg at google.com> wrote:
> I don't think we have a specific code owner for OpenCL in Clang, which 
> means Richard is the owner.
>
> Richard, what do you think?

Is there a reason we want to push this new feature into 3.8 rather than waiting for the next release?

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



More information about the cfe-commits mailing list