From: Anastasia Stulova Date: Wed, 26 Nov 2014 14:10:06 +0000 (+0000) Subject: [OpenCL] Generic address space has been added in OpenCL v2.0. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2c8dcfbae60319053cc2e65388f294e8aaf52fc1;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/clang/include/clang/Basic/AddressSpaces.h b/clang/include/clang/Basic/AddressSpaces.h index 4b1cea5..8dd7566 100644 --- a/clang/include/clang/Basic/AddressSpaces.h +++ b/clang/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/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 5ab73e6..a152c54 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/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/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index cf8b662..253869a 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/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/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 6bf1910..7a9d8dd 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/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/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index c63dea0..c98e8d3 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/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/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 1804c00..a0b8017 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/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/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index f36e799..e36fc17 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/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/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index f83eea5..b2178dc 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/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/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index fbf3337..5af7b69 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/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/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 7b2e7ff..7bf3e51 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/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/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index fcb9c72..f442743 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/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();