mirror of
https://github.com/intel/llvm.git
synced 2026-02-07 07:39:11 +08:00
[OpenCL] Refine pipe builtin support
Summary: Refine the type builtin support as the request with http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20160201/148637.html Reviewers: pekka.jaaskelainen, Anastasia, yaxunl Subscribers: rsmith, cfe-commits Differential Revision: http://reviews.llvm.org/D16876 llvm-svn: 262692
This commit is contained in:
@@ -31,12 +31,12 @@ class QualType;
|
||||
class LangOptions;
|
||||
|
||||
enum LanguageID {
|
||||
GNU_LANG = 0x1, // builtin requires GNU mode.
|
||||
C_LANG = 0x2, // builtin for c only.
|
||||
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.
|
||||
GNU_LANG = 0x1, // builtin requires GNU mode.
|
||||
C_LANG = 0x2, // builtin for c only.
|
||||
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.
|
||||
|
||||
@@ -7746,7 +7746,7 @@ def err_opencl_type_can_only_be_used_as_function_parameter : Error <
|
||||
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">;
|
||||
"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<
|
||||
|
||||
@@ -259,16 +259,9 @@ static bool SemaBuiltinSEHScopeCheck(Sema &SemaRef, CallExpr *TheCall,
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Returns readable name for a call.
|
||||
static StringRef getFunctionName(CallExpr *Call) {
|
||||
return cast<FunctionDecl>(Call->getCalleeDecl())->getName();
|
||||
}
|
||||
|
||||
/// Returns OpenCL access qual.
|
||||
static OpenCLAccessAttr *getOpenCLArgAccess(const Decl *D) {
|
||||
if (D->hasAttr<OpenCLAccessAttr>())
|
||||
return D->getAttr<OpenCLAccessAttr>();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Returns true if pipe element type is different from the pointer.
|
||||
@@ -277,7 +270,7 @@ static bool checkOpenCLPipeArg(Sema &S, CallExpr *Call) {
|
||||
// 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();
|
||||
<< Call->getDirectCallee() << Arg0->getSourceRange();
|
||||
return true;
|
||||
}
|
||||
OpenCLAccessAttr *AccessQual =
|
||||
@@ -286,20 +279,38 @@ static bool checkOpenCLPipeArg(Sema &S, CallExpr *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;
|
||||
switch (Call->getDirectCallee()->getBuiltinID()) {
|
||||
case Builtin::BIread_pipe:
|
||||
case Builtin::BIreserve_read_pipe:
|
||||
case Builtin::BIcommit_read_pipe:
|
||||
case Builtin::BIwork_group_reserve_read_pipe:
|
||||
case Builtin::BIsub_group_reserve_read_pipe:
|
||||
case Builtin::BIwork_group_commit_read_pipe:
|
||||
case Builtin::BIsub_group_commit_read_pipe:
|
||||
if (!(!AccessQual || AccessQual->isReadOnly())) {
|
||||
S.Diag(Arg0->getLocStart(),
|
||||
diag::err_opencl_builtin_pipe_invalid_access_modifier)
|
||||
<< "read_only" << Arg0->getSourceRange();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case Builtin::BIwrite_pipe:
|
||||
case Builtin::BIreserve_write_pipe:
|
||||
case Builtin::BIcommit_write_pipe:
|
||||
case Builtin::BIwork_group_reserve_write_pipe:
|
||||
case Builtin::BIsub_group_reserve_write_pipe:
|
||||
case Builtin::BIwork_group_commit_write_pipe:
|
||||
case Builtin::BIsub_group_commit_write_pipe:
|
||||
if (!(AccessQual && AccessQual->isWriteOnly())) {
|
||||
S.Diag(Arg0->getLocStart(),
|
||||
diag::err_opencl_builtin_pipe_invalid_access_modifier)
|
||||
<< "write_only" << Arg0->getSourceRange();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -308,15 +319,13 @@ 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());
|
||||
const QualType EltTy = PipeTy->getElementType();
|
||||
const PointerType *ArgTy = ArgIdx->getType()->getAs<PointerType>();
|
||||
// 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()) {
|
||||
if (!ArgTy || S.Context.hasSameType(EltTy, ArgTy->getPointeeType())) {
|
||||
S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg)
|
||||
<< getFunctionName(Call)
|
||||
<< S.Context.getPointerType(PipeTy->getElementType())
|
||||
<< Call->getDirectCallee() << S.Context.getPointerType(EltTy)
|
||||
<< ArgIdx->getSourceRange();
|
||||
return true;
|
||||
}
|
||||
@@ -328,16 +337,15 @@ static bool checkOpenCLPipePacketType(Sema &S, CallExpr *Call, unsigned Idx) {
|
||||
// \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.
|
||||
// OpenCL v2.0 s6.13.16.2 - The built-in read/write
|
||||
// functions have two 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
|
||||
// read/write_pipe(pipe T, T*).
|
||||
// Check packet type T.
|
||||
if (checkOpenCLPipePacketType(S, Call, 1))
|
||||
return true;
|
||||
} break;
|
||||
@@ -346,32 +354,32 @@ static bool SemaBuiltinRWPipe(Sema &S, CallExpr *Call) {
|
||||
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
|
||||
// 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->getDirectCallee() << S.Context.OCLReserveIDTy
|
||||
<< Call->getArg(1)->getSourceRange();
|
||||
return true;
|
||||
}
|
||||
|
||||
// check the index
|
||||
// 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
|
||||
<< Call->getDirectCallee() << S.Context.UnsignedIntTy
|
||||
<< Arg2->getSourceRange();
|
||||
return true;
|
||||
}
|
||||
|
||||
// check packet type T
|
||||
// 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();
|
||||
<< Call->getDirectCallee() << Call->getSourceRange();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -390,11 +398,11 @@ static bool SemaBuiltinReserveRWPipe(Sema &S, CallExpr *Call) {
|
||||
if (checkOpenCLPipeArg(S, Call))
|
||||
return true;
|
||||
|
||||
// check the reserve size
|
||||
// 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->getDirectCallee() << S.Context.UnsignedIntTy
|
||||
<< Call->getArg(1)->getSourceRange();
|
||||
return true;
|
||||
}
|
||||
@@ -414,10 +422,10 @@ static bool SemaBuiltinCommitRWPipe(Sema &S, CallExpr *Call) {
|
||||
if (checkOpenCLPipeArg(S, Call))
|
||||
return true;
|
||||
|
||||
// check reserve_id_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->getDirectCallee() << S.Context.OCLReserveIDTy
|
||||
<< Call->getArg(1)->getSourceRange();
|
||||
return true;
|
||||
}
|
||||
@@ -436,7 +444,7 @@ static bool SemaBuiltinPipePackets(Sema &S, CallExpr *Call) {
|
||||
|
||||
if (!Call->getArg(0)->getType()->isPipeType()) {
|
||||
S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_first_arg)
|
||||
<< getFunctionName(Call) << Call->getArg(0)->getSourceRange();
|
||||
<< Call->getDirectCallee() << Call->getArg(0)->getSourceRange();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,22 +5,22 @@ void test1(read_only pipe int p, global int* ptr){
|
||||
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 *')}}
|
||||
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}}
|
||||
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')}}
|
||||
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{{invalid pipe access modifier (expecting write_only)}}
|
||||
}
|
||||
|
||||
@@ -29,27 +29,27 @@ void test2(write_only pipe int p, global int* ptr){
|
||||
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 *')}}
|
||||
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}}
|
||||
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')}}
|
||||
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{{invalid 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}}
|
||||
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}}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user