mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-06 21:51:08 +00:00
[OpenCL] Generic address space has been added in OpenCL v2.0.
To support it in the frontend, the following has been added: - generic address space type attribute; - documentation for the OpenCL address space attributes; - parsing of __generic(generic) keyword; - test code for the parser and diagnostics. llvm-svn: 222831
This commit is contained in:
parent
c53ead03ce
commit
2c8dcfbae6
@ -30,6 +30,7 @@ enum ID {
|
||||
opencl_global = Offset,
|
||||
opencl_local,
|
||||
opencl_constant,
|
||||
opencl_generic,
|
||||
|
||||
cuda_device,
|
||||
cuda_constant,
|
||||
|
@ -624,22 +624,27 @@ def OpenCLImageAccess : Attr {
|
||||
|
||||
def OpenCLPrivateAddressSpace : TypeAttr {
|
||||
let Spellings = [Keyword<"__private">, Keyword<"private">];
|
||||
let Documentation = [Undocumented];
|
||||
let Documentation = [OpenCLAddressSpacePrivateDocs];
|
||||
}
|
||||
|
||||
def OpenCLGlobalAddressSpace : TypeAttr {
|
||||
let Spellings = [Keyword<"__global">, Keyword<"global">];
|
||||
let Documentation = [Undocumented];
|
||||
let Documentation = [OpenCLAddressSpaceGlobalDocs];
|
||||
}
|
||||
|
||||
def OpenCLLocalAddressSpace : TypeAttr {
|
||||
let Spellings = [Keyword<"__local">, Keyword<"local">];
|
||||
let Documentation = [Undocumented];
|
||||
let Documentation = [OpenCLAddressSpaceLocalDocs];
|
||||
}
|
||||
|
||||
def OpenCLConstantAddressSpace : TypeAttr {
|
||||
let Spellings = [Keyword<"__constant">, Keyword<"constant">];
|
||||
let Documentation = [Undocumented];
|
||||
let Documentation = [OpenCLAddressSpaceConstantDocs];
|
||||
}
|
||||
|
||||
def OpenCLGenericAddressSpace : TypeAttr {
|
||||
let Spellings = [Keyword<"__generic">, Keyword<"generic">];
|
||||
let Documentation = [OpenCLAddressSpaceGenericDocs];
|
||||
}
|
||||
|
||||
def Deprecated : InheritableAttr {
|
||||
|
@ -1265,3 +1265,88 @@ for further details including limitations of the unroll hints.
|
||||
}];
|
||||
}
|
||||
|
||||
def DocOpenCLAddressSpaces : DocumentationCategory<"OpenCL Address Spaces"> {
|
||||
let Content = [{
|
||||
The address space qualifier may be used to specify the region of memory that is
|
||||
used to allocate the object. OpenCL supports the following address spaces:
|
||||
__generic(generic), __global(global), __local(local), __private(private),
|
||||
__constant(constant).
|
||||
|
||||
.. code-block:: opencl
|
||||
|
||||
__constant int c = ...;
|
||||
|
||||
__generic int* foo(global int* g) {
|
||||
__local int* l;
|
||||
private int p;
|
||||
...
|
||||
return l;
|
||||
}
|
||||
|
||||
More details can be found in the OpenCL C language Spec v2.0, Section 6.5.
|
||||
}];
|
||||
}
|
||||
|
||||
def OpenCLAddressSpaceGenericDocs : Documentation {
|
||||
let Category = DocOpenCLAddressSpaces;
|
||||
let Heading = "__generic(generic)";
|
||||
let Content = [{
|
||||
The generic address space attribute is only available with OpenCL v2.0 and later.
|
||||
It can be used with pointer types. Variables in global and local scope and
|
||||
function parameters in non-kernel functions can have the generic address space
|
||||
type attribute. It is intended to be a placeholder for any other address space
|
||||
except for '__constant' in OpenCL code which can be used with multiple address
|
||||
spaces.
|
||||
}];
|
||||
}
|
||||
|
||||
def OpenCLAddressSpaceConstantDocs : Documentation {
|
||||
let Category = DocOpenCLAddressSpaces;
|
||||
let Heading = "__constant(constant)";
|
||||
let Content = [{
|
||||
The constant address space attribute signals that an object is located in
|
||||
a constant (non-modifiable) memory region. It is available to all work items.
|
||||
Any type can be annotated with the constant address space attribute. Objects
|
||||
with the constant address space qualifier can be declared in any scope and must
|
||||
have an initializer.
|
||||
}];
|
||||
}
|
||||
|
||||
def OpenCLAddressSpaceGlobalDocs : Documentation {
|
||||
let Category = DocOpenCLAddressSpaces;
|
||||
let Heading = "__global(global)";
|
||||
let Content = [{
|
||||
The global address space attribute specifies that an object is allocated in
|
||||
global memory, which is accessible by all work items. The content stored in this
|
||||
memory area persists between kernel executions. Pointer types to the global
|
||||
address space are allowed as function parameters or local variables. Starting
|
||||
with OpenCL v2.0, the global address space can be used with global (program
|
||||
scope) variables and static local variable as well.
|
||||
}];
|
||||
}
|
||||
|
||||
def OpenCLAddressSpaceLocalDocs : Documentation {
|
||||
let Category = DocOpenCLAddressSpaces;
|
||||
let Heading = "__local(local)";
|
||||
let Content = [{
|
||||
The local address space specifies that an object is allocated in the local (work
|
||||
group) memory area, which is accessible to all work items in the same work
|
||||
group. The content stored in this memory region is not accessible after
|
||||
the kernel execution ends. In a kernel function scope, any variable can be in
|
||||
the local address space. In other scopes, only pointer types to the local address
|
||||
space are allowed. Local address space variables cannot have an initializer.
|
||||
}];
|
||||
}
|
||||
|
||||
def OpenCLAddressSpacePrivateDocs : Documentation {
|
||||
let Category = DocOpenCLAddressSpaces;
|
||||
let Heading = "__private(private)";
|
||||
let Content = [{
|
||||
The private address space specifies that an object is allocated in the private
|
||||
(work item) memory. Other work items cannot access the same memory area and its
|
||||
content is destroyed after work item execution ends. Local variables can be
|
||||
declared in the private address space. Function arguments are always in the
|
||||
private address space. Kernel function arguments of a pointer or an array type
|
||||
cannot point to the private address space.
|
||||
}];
|
||||
}
|
||||
|
@ -934,8 +934,8 @@ def err_pragma_optimize_extra_argument : Error<
|
||||
"unexpected extra argument '%0' to '#pragma clang optimize'">;
|
||||
|
||||
// OpenCL Section 6.8.g
|
||||
def err_not_opencl_storage_class_specifier : Error<
|
||||
"OpenCL does not support the '%0' storage class specifier">;
|
||||
def err_opencl_unknown_type_specifier : Error<
|
||||
"OpenCL does not support the '%0' %select{type qualifier|storage class specifier}1">;
|
||||
|
||||
// OpenCL EXTENSION pragma (OpenCL 1.1 [9.1])
|
||||
def warn_pragma_expected_colon : Warning<
|
||||
|
@ -471,10 +471,12 @@ KEYWORD(__global , KEYOPENCL)
|
||||
KEYWORD(__local , KEYOPENCL)
|
||||
KEYWORD(__constant , KEYOPENCL)
|
||||
KEYWORD(__private , KEYOPENCL)
|
||||
KEYWORD(__generic , KEYOPENCL)
|
||||
ALIAS("global", __global , KEYOPENCL)
|
||||
ALIAS("local", __local , KEYOPENCL)
|
||||
ALIAS("constant", __constant , KEYOPENCL)
|
||||
ALIAS("private", __private , KEYOPENCL)
|
||||
ALIAS("generic", __generic , KEYOPENCL)
|
||||
// OpenCL function qualifiers
|
||||
KEYWORD(__kernel , KEYOPENCL)
|
||||
ALIAS("kernel", __kernel , KEYOPENCL)
|
||||
|
@ -699,9 +699,10 @@ static const LangAS::Map *getAddressSpaceMap(const TargetInfo &T,
|
||||
1, // opencl_global
|
||||
2, // opencl_local
|
||||
3, // opencl_constant
|
||||
4, // cuda_device
|
||||
5, // cuda_constant
|
||||
6 // cuda_shared
|
||||
4, // opencl_generic
|
||||
5, // cuda_device
|
||||
6, // cuda_constant
|
||||
7 // cuda_shared
|
||||
};
|
||||
return &FakeAddrSpaceMap;
|
||||
} else {
|
||||
|
@ -1490,6 +1490,9 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,
|
||||
case LangAS::opencl_constant:
|
||||
OS << "__constant";
|
||||
break;
|
||||
case LangAS::opencl_generic:
|
||||
OS << "__generic";
|
||||
break;
|
||||
default:
|
||||
OS << "__attribute__((address_space(";
|
||||
OS << addrspace;
|
||||
|
@ -1368,6 +1368,8 @@ namespace {
|
||||
1, // opencl_global
|
||||
3, // opencl_local
|
||||
4, // opencl_constant
|
||||
// FIXME: generic has to be added to the target
|
||||
0, // opencl_generic
|
||||
1, // cuda_device
|
||||
4, // cuda_constant
|
||||
3, // cuda_shared
|
||||
@ -1487,6 +1489,8 @@ static const unsigned R600AddrSpaceMap[] = {
|
||||
1, // opencl_global
|
||||
3, // opencl_local
|
||||
2, // opencl_constant
|
||||
// FIXME: generic has to be added to the target
|
||||
0, // opencl_generic
|
||||
1, // cuda_device
|
||||
2, // cuda_constant
|
||||
3 // cuda_shared
|
||||
@ -5381,6 +5385,8 @@ namespace {
|
||||
3, // opencl_global
|
||||
4, // opencl_local
|
||||
5, // opencl_constant
|
||||
// FIXME: generic has to be added to the target
|
||||
0, // opencl_generic
|
||||
0, // cuda_device
|
||||
0, // cuda_constant
|
||||
0 // cuda_shared
|
||||
@ -6104,6 +6110,7 @@ namespace {
|
||||
1, // opencl_global
|
||||
3, // opencl_local
|
||||
2, // opencl_constant
|
||||
4, // opencl_generic
|
||||
0, // cuda_device
|
||||
0, // cuda_constant
|
||||
0 // cuda_shared
|
||||
|
@ -2520,6 +2520,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
|
||||
while (1) {
|
||||
bool isInvalid = false;
|
||||
bool isStorageClass = false;
|
||||
const char *PrevSpec = nullptr;
|
||||
unsigned DiagID = 0;
|
||||
|
||||
@ -2943,22 +2944,26 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
case tok::kw_typedef:
|
||||
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_typedef, Loc,
|
||||
PrevSpec, DiagID, Policy);
|
||||
isStorageClass = true;
|
||||
break;
|
||||
case tok::kw_extern:
|
||||
if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread)
|
||||
Diag(Tok, diag::ext_thread_before) << "extern";
|
||||
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_extern, Loc,
|
||||
PrevSpec, DiagID, Policy);
|
||||
isStorageClass = true;
|
||||
break;
|
||||
case tok::kw___private_extern__:
|
||||
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_private_extern,
|
||||
Loc, PrevSpec, DiagID, Policy);
|
||||
isStorageClass = true;
|
||||
break;
|
||||
case tok::kw_static:
|
||||
if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread)
|
||||
Diag(Tok, diag::ext_thread_before) << "static";
|
||||
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_static, Loc,
|
||||
PrevSpec, DiagID, Policy);
|
||||
isStorageClass = true;
|
||||
break;
|
||||
case tok::kw_auto:
|
||||
if (getLangOpts().CPlusPlus11) {
|
||||
@ -2974,18 +2979,22 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
} else
|
||||
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
|
||||
PrevSpec, DiagID, Policy);
|
||||
isStorageClass = true;
|
||||
break;
|
||||
case tok::kw_register:
|
||||
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_register, Loc,
|
||||
PrevSpec, DiagID, Policy);
|
||||
isStorageClass = true;
|
||||
break;
|
||||
case tok::kw_mutable:
|
||||
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_mutable, Loc,
|
||||
PrevSpec, DiagID, Policy);
|
||||
isStorageClass = true;
|
||||
break;
|
||||
case tok::kw___thread:
|
||||
isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS___thread, Loc,
|
||||
PrevSpec, DiagID);
|
||||
isStorageClass = true;
|
||||
break;
|
||||
case tok::kw_thread_local:
|
||||
isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS_thread_local, Loc,
|
||||
@ -2994,6 +3003,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
case tok::kw__Thread_local:
|
||||
isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS__Thread_local,
|
||||
Loc, PrevSpec, DiagID);
|
||||
isStorageClass = true;
|
||||
break;
|
||||
|
||||
// function-specifier
|
||||
@ -3232,6 +3242,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
break;
|
||||
|
||||
// OpenCL qualifiers:
|
||||
case tok::kw___generic:
|
||||
// generic address space is introduced only in OpenCL v2.0
|
||||
// see OpenCL C Spec v2.0 s6.5.5
|
||||
if (Actions.getLangOpts().OpenCLVersion < 200) {
|
||||
DiagID = diag::err_opencl_unknown_type_specifier;
|
||||
PrevSpec = Tok.getIdentifierInfo()->getNameStart();
|
||||
isInvalid = true;
|
||||
break;
|
||||
};
|
||||
case tok::kw___private:
|
||||
case tok::kw___global:
|
||||
case tok::kw___local:
|
||||
@ -3266,6 +3285,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
if (DiagID == diag::ext_duplicate_declspec)
|
||||
Diag(Tok, DiagID)
|
||||
<< PrevSpec << FixItHint::CreateRemoval(Tok.getLocation());
|
||||
else if (DiagID == diag::err_opencl_unknown_type_specifier)
|
||||
Diag(Tok, DiagID) << PrevSpec << isStorageClass;
|
||||
else
|
||||
Diag(Tok, DiagID) << PrevSpec;
|
||||
}
|
||||
@ -3982,6 +4003,7 @@ bool Parser::isTypeQualifier() const {
|
||||
case tok::kw___local:
|
||||
case tok::kw___global:
|
||||
case tok::kw___constant:
|
||||
case tok::kw___generic:
|
||||
case tok::kw___read_only:
|
||||
case tok::kw___read_write:
|
||||
case tok::kw___write_only:
|
||||
@ -4131,6 +4153,7 @@ bool Parser::isTypeSpecifierQualifier() {
|
||||
case tok::kw___local:
|
||||
case tok::kw___global:
|
||||
case tok::kw___constant:
|
||||
case tok::kw___generic:
|
||||
case tok::kw___read_only:
|
||||
case tok::kw___read_write:
|
||||
case tok::kw___write_only:
|
||||
@ -4303,6 +4326,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
|
||||
case tok::kw___local:
|
||||
case tok::kw___global:
|
||||
case tok::kw___constant:
|
||||
case tok::kw___generic:
|
||||
case tok::kw___read_only:
|
||||
case tok::kw___read_write:
|
||||
case tok::kw___write_only:
|
||||
@ -4491,6 +4515,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs,
|
||||
case tok::kw___global:
|
||||
case tok::kw___local:
|
||||
case tok::kw___constant:
|
||||
case tok::kw___generic:
|
||||
case tok::kw___read_only:
|
||||
case tok::kw___write_only:
|
||||
case tok::kw___read_write:
|
||||
|
@ -508,14 +508,14 @@ bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc,
|
||||
case SCS_private_extern:
|
||||
case SCS_static:
|
||||
if (S.getLangOpts().OpenCLVersion < 120) {
|
||||
DiagID = diag::err_not_opencl_storage_class_specifier;
|
||||
DiagID = diag::err_opencl_unknown_type_specifier;
|
||||
PrevSpec = getSpecifierName(SC);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SCS_auto:
|
||||
case SCS_register:
|
||||
DiagID = diag::err_not_opencl_storage_class_specifier;
|
||||
DiagID = diag::err_opencl_unknown_type_specifier;
|
||||
PrevSpec = getSpecifierName(SC);
|
||||
return true;
|
||||
default:
|
||||
|
@ -3981,6 +3981,8 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
|
||||
ASIdx = LangAS::opencl_local; break;
|
||||
case AttributeList::AT_OpenCLConstantAddressSpace:
|
||||
ASIdx = LangAS::opencl_constant; break;
|
||||
case AttributeList::AT_OpenCLGenericAddressSpace:
|
||||
ASIdx = LangAS::opencl_generic; break;
|
||||
default:
|
||||
assert(Attr.getKind() == AttributeList::AT_OpenCLPrivateAddressSpace);
|
||||
ASIdx = 0; break;
|
||||
@ -4892,6 +4894,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
|
||||
case AttributeList::AT_OpenCLGlobalAddressSpace:
|
||||
case AttributeList::AT_OpenCLLocalAddressSpace:
|
||||
case AttributeList::AT_OpenCLConstantAddressSpace:
|
||||
case AttributeList::AT_OpenCLGenericAddressSpace:
|
||||
case AttributeList::AT_AddressSpace:
|
||||
HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
|
||||
attr.setUsedAsTypeAttr();
|
||||
|
Loading…
Reference in New Issue
Block a user