Skip to content

Commit

Permalink
[OpenCL] Generic address space has been added in OpenCL v2.0.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Anastasia Stulova committed Nov 26, 2014
1 parent c53ead0 commit 2c8dcfb
Show file tree
Hide file tree
Showing 11 changed files with 143 additions and 11 deletions.
1 change: 1 addition & 0 deletions clang/include/clang/Basic/AddressSpaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ enum ID {
opencl_global = Offset,
opencl_local,
opencl_constant,
opencl_generic,

cuda_device,
cuda_constant,
Expand Down
13 changes: 9 additions & 4 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
85 changes: 85 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -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.
}];
}
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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<
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/TokenKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
7 changes: 4 additions & 3 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/AST/TypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/Basic/Targets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
25 changes: 25 additions & 0 deletions clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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) {
Expand All @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Sema/DeclSpec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit 2c8dcfb

Please sign in to comment.