r258782 - Recommit: R258773 [OpenCL] Pipe builtin functions
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 1 13:53:53 PST 2016
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/Builtins.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/Builtins.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/DiagnosticSemaKinds.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.cpp?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.cpp?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* @__reserve_read_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}})
>> + reserve_id_t rid = reserve_read_pipe(p, 2);
>> + // CHECK: call i32 @__read_pipe_4(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}}, i32 {{.*}}, i8* %{{.*}})
>> + read_pipe(p, rid, 2, ptr);
>> + // CHECK: call void @__commit_read_pipe(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}})
>> + commit_read_pipe(p, rid);
>> +}
>> +
>> +void test2(write_only pipe int p, global int *ptr) {
>> + // CHECK: call i32 @__write_pipe_2(%opencl.pipe_t* %{{.*}}, i8* %{{.*}})
>> + write_pipe(p, ptr);
>> + // CHECK: call %opencl.reserve_id_t* @__reserve_write_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}})
>> + reserve_id_t rid = reserve_write_pipe(p, 2);
>> + // CHECK: call i32 @__write_pipe_4(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}}, i32 {{.*}}, i8* %{{.*}})
>> + write_pipe(p, rid, 2, ptr);
>> + // CHECK: call void @__commit_write_pipe(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}})
>> + commit_write_pipe(p, rid);
>> +}
>> +
>> +void test3(read_only pipe int p, global int *ptr) {
>> + // CHECK: call %opencl.reserve_id_t* @__work_group_reserve_read_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}})
>> + reserve_id_t rid = work_group_reserve_read_pipe(p, 2);
>> + // CHECK: call void @__work_group_commit_read_pipe(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}})
>> + work_group_commit_read_pipe(p, rid);
>> +}
>> +
>> +void test4(write_only pipe int p, global int *ptr) {
>> + // CHECK: call %opencl.reserve_id_t* @__work_group_reserve_write_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}})
>> + reserve_id_t rid = work_group_reserve_write_pipe(p, 2);
>> + // CHECK: call void @__work_group_commit_write_pipe(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}})
>> + work_group_commit_write_pipe(p, rid);
>> +}
>> +
>> +void test5(read_only pipe int p, global int *ptr) {
>> + // CHECK: call %opencl.reserve_id_t* @__sub_group_reserve_read_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}})
>> + reserve_id_t rid = sub_group_reserve_read_pipe(p, 2);
>> + // CHECK: call void @__sub_group_commit_read_pipe(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}})
>> + sub_group_commit_read_pipe(p, rid);
>> +}
>> +
>> +void test6(write_only pipe int p, global int *ptr) {
>> + // CHECK: call %opencl.reserve_id_t* @__sub_group_reserve_write_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}})
>> + reserve_id_t rid = sub_group_reserve_write_pipe(p, 2);
>> + // CHECK: call void @__sub_group_commit_write_pipe(%opencl.pipe_t* %{{.*}}, %opencl.reserve_id_t* %{{.*}})
>> + sub_group_commit_write_pipe(p, rid);
>> +}
>> +
>> +void test7(write_only pipe int p, global int *ptr) {
>> + // CHECK: call i32 @__get_pipe_num_packets(%opencl.pipe_t* %{{.*}})
>> + *ptr = get_pipe_num_packets(p);
>> + // CHECK: call i32 @__get_pipe_max_packets(%opencl.pipe_t* %{{.*}})
>> + *ptr = get_pipe_max_packets(p);
>> +}
>>
>> Added: cfe/trunk/test/SemaOpenCL/invalid-pipe-builtin-cl2.0.cl
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaOpenCL/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