summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnastasia Stulova <anastasia.stulova@arm.com>2014-11-26 14:10:06 +0000
committerAnastasia Stulova <anastasia.stulova@arm.com>2014-11-26 14:10:06 +0000
commit08c258670c7e3fdeea8e46f0759f65c65c85d115 (patch)
treed8a9eb6eb48f0a869204f19acc298d503debfddf
parent572143c0e038397c63b32e39d4e1975c281bd27c (diff)
[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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@222831 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/AddressSpaces.h1
-rw-r--r--include/clang/Basic/Attr.td13
-rw-r--r--include/clang/Basic/AttrDocs.td85
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td4
-rw-r--r--include/clang/Basic/TokenKinds.def2
-rw-r--r--lib/AST/ASTContext.cpp7
-rw-r--r--lib/AST/TypePrinter.cpp3
-rw-r--r--lib/Basic/Targets.cpp7
-rw-r--r--lib/Parse/ParseDecl.cpp25
-rw-r--r--lib/Sema/DeclSpec.cpp4
-rw-r--r--lib/Sema/SemaType.cpp3
11 files changed, 143 insertions, 11 deletions
diff --git a/include/clang/Basic/AddressSpaces.h b/include/clang/Basic/AddressSpaces.h
index 4b1cea50f8..8dd75660c6 100644
--- a/include/clang/Basic/AddressSpaces.h
+++ b/include/clang/Basic/AddressSpaces.h
@@ -30,6 +30,7 @@ enum ID {
opencl_global = Offset,
opencl_local,
opencl_constant,
+ opencl_generic,
cuda_device,
cuda_constant,
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index 5ab73e64de..a152c547c5 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -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 {
diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td
index cf8b662357..253869a19c 100644
--- a/include/clang/Basic/AttrDocs.td
+++ b/include/clang/Basic/AttrDocs.td
@@ -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.
+ }];
+}
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 6bf19108b1..7a9d8dd56d 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -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<
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index c63dea0fa5..c98e8d37f8 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -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)
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 1804c00647..a0b8017488 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -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 {
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index f36e79950d..e36fc175c4 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -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;
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index f83eea5de0..b2178dc4a1 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -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
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index fbf3337731..5af7b69999 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -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:
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index 7b2e7ffbaa..7bf3e51999 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -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:
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index fcb9c723cb..f442743bee 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -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();