[OpenCL 2.0] Apply default address space (AS).

If AS of a variable/parameter declaration is not set by the source,
OpenCL v2.0 s6.5 defines explicit rules for default ASes:

- The AS of global and local static variables defaults to global;
- All pointers point to generic AS.

http://reviews.llvm.org/D13168

llvm-svn: 253863
This commit is contained in:
Anastasia Stulova 2015-11-23 11:14:44 +00:00
parent 5ef2bc316d
commit 784fb78274
3 changed files with 83 additions and 31 deletions

View File

@ -1564,8 +1564,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// Apply any type attributes from the decl spec. This may cause the
// list of type attributes to be temporarily saved while the type
// attributes are pushed around.
if (AttributeList *attrs = DS.getAttributes().getList())
processTypeAttrs(state, Result, TAL_DeclSpec, attrs);
processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes().getList());
// Apply const/volatile/restrict qualifiers to T.
if (unsigned TypeQuals = DS.getTypeQualifiers()) {
@ -2596,8 +2595,8 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// Constructors and destructors don't have return types. Use
// "void" instead.
T = SemaRef.Context.VoidTy;
if (AttributeList *attrs = D.getDeclSpec().getAttributes().getList())
processTypeAttrs(state, T, TAL_DeclSpec, attrs);
processTypeAttrs(state, T, TAL_DeclSpec,
D.getDeclSpec().getAttributes().getList());
break;
case UnqualifiedId::IK_ConversionFunctionId:
@ -4112,8 +4111,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
// See if there are any attributes on this declarator chunk.
if (AttributeList *attrs = const_cast<AttributeList*>(DeclType.getAttrs()))
processTypeAttrs(state, T, TAL_DeclChunk, attrs);
processTypeAttrs(state, T, TAL_DeclChunk,
const_cast<AttributeList *>(DeclType.getAttrs()));
}
assert(!T.isNull() && "T must not be null after this point");
@ -4206,8 +4205,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
// Apply any undistributed attributes from the declarator.
if (AttributeList *attrs = D.getAttributes())
processTypeAttrs(state, T, TAL_DeclName, attrs);
processTypeAttrs(state, T, TAL_DeclName, D.getAttributes());
// Diagnose any ignored type attributes.
state.diagnoseIgnoredTypeAttrs(T);
@ -6176,10 +6174,11 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
// type, but others can be present in the type specifiers even though they
// apply to the decl. Here we apply type attributes and ignore the rest.
AttributeList *next;
do {
bool hasOpenCLAddressSpace = false;
while (attrs) {
AttributeList &attr = *attrs;
next = attr.getNext();
attrs = attr.getNext(); // reset to the next here due to early loop continue
// stmts
// Skip attributes that were marked to be invalid.
if (attr.isInvalid())
@ -6238,6 +6237,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
case AttributeList::AT_AddressSpace:
HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
hasOpenCLAddressSpace = true;
break;
OBJC_POINTER_TYPE_ATTRS_CASELIST:
if (!handleObjCPointerTypeAttr(state, attr, type))
@ -6332,7 +6332,39 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
distributeFunctionTypeAttr(state, attr, type);
break;
}
} while ((attrs = next));
}
// If address space is not set, OpenCL 2.0 defines non private default
// address spaces for some cases:
// OpenCL 2.0, section 6.5:
// The address space for a variable at program scope or a static variable
// inside a function can either be __global or __constant, but defaults to
// __global if not specified.
// (...)
// Pointers that are declared without pointing to a named address space point
// to the generic address space.
if (state.getSema().getLangOpts().OpenCLVersion >= 200 &&
!hasOpenCLAddressSpace && type.getAddressSpace() == 0 &&
(TAL == TAL_DeclSpec || TAL == TAL_DeclChunk)) {
Declarator &D = state.getDeclarator();
if (state.getCurrentChunkIndex() > 0 &&
D.getTypeObject(state.getCurrentChunkIndex() - 1).Kind ==
DeclaratorChunk::Pointer) {
type = state.getSema().Context.getAddrSpaceQualType(
type, LangAS::opencl_generic);
} else if (state.getCurrentChunkIndex() == 0 &&
D.getContext() == Declarator::FileContext &&
!D.isFunctionDeclarator() && !D.isFunctionDefinition() &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
!type->isSamplerT())
type = state.getSema().Context.getAddrSpaceQualType(
type, LangAS::opencl_global);
else if (state.getCurrentChunkIndex() == 0 &&
D.getContext() == Declarator::BlockContext &&
D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)
type = state.getSema().Context.getAddrSpaceQualType(
type, LangAS::opencl_global);
}
}
/// \brief Ensure that the type of the given expression is complete.

View File

@ -1,27 +1,47 @@
// RUN: %clang_cc1 %s -ffake-address-space-map -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 %s -O0 -ffake-address-space-map -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 %s -O0 -DCL20 -cl-std=CL2.0 -ffake-address-space-map -emit-llvm -o - | FileCheck %s --check-prefix=CL20
void f__p(__private int *arg) { }
// CHECK: i32* nocapture %arg
// CHECK: i32* %arg
void f__p(__private int *arg) {}
void f__g(__global int *arg) { }
// CHECK: i32 addrspace(1)* nocapture %arg
// CHECK: i32 addrspace(1)* %arg
void f__g(__global int *arg) {}
void f__l(__local int *arg) { }
// CHECK: i32 addrspace(2)* nocapture %arg
// CHECK: i32 addrspace(2)* %arg
void f__l(__local int *arg) {}
void f__c(__constant int *arg) { }
// CHECK: i32 addrspace(3)* nocapture %arg
// CHECK: i32 addrspace(3)* %arg
void f__c(__constant int *arg) {}
// CHECK: i32* %arg
void fp(private int *arg) {}
void fp(private int *arg) { }
// CHECK: i32* nocapture %arg
// CHECK: i32 addrspace(1)* %arg
void fg(global int *arg) {}
void fg(global int *arg) { }
// CHECK: i32 addrspace(1)* nocapture %arg
// CHECK: i32 addrspace(2)* %arg
void fl(local int *arg) {}
void fl(local int *arg) { }
// CHECK: i32 addrspace(2)* nocapture %arg
// CHECK: i32 addrspace(3)* %arg
void fc(constant int *arg) {}
void fc(constant int *arg) { }
// CHECK: i32 addrspace(3)* nocapture %arg
#ifdef CL20
int i;
// CL20-DAG: @i = common addrspace(1) global i32 0
int *ptr;
// CL20-DAG: @ptr = common addrspace(1) global i32 addrspace(4)* null
#endif
// CHECK: i32* %arg
// CL20-DAG: i32 addrspace(4)* %arg
void f(int *arg) {
int i;
// CHECK: %i = alloca i32,
// CL20-DAG: %i = alloca i32,
#ifdef CL20
static int ii;
// CL20-DAG: @f.ii = internal addrspace(1) global i32 0
#endif
}

View File

@ -1,12 +1,12 @@
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -DCL20 -cl-std=CL2.0
static constant int G1 = 0;
int G2 = 0;// expected-error{{program scope variable must reside in global or constant address space}}
int G2 = 0;
global int G3 = 0;
local int G4 = 0;// expected-error{{program scope variable must reside in global or constant address space}}
void kernel foo() {
static int S1 = 5;// expected-error{{program scope variable must reside in global or constant address space}}
static int S1 = 5;
static global int S2 = 5;
static private int S3 = 5;// expected-error{{program scope variable must reside in global or constant address space}}