[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 // Apply any type attributes from the decl spec. This may cause the
// list of type attributes to be temporarily saved while the type // list of type attributes to be temporarily saved while the type
// attributes are pushed around. // attributes are pushed around.
if (AttributeList *attrs = DS.getAttributes().getList()) processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes().getList());
processTypeAttrs(state, Result, TAL_DeclSpec, attrs);
// Apply const/volatile/restrict qualifiers to T. // Apply const/volatile/restrict qualifiers to T.
if (unsigned TypeQuals = DS.getTypeQualifiers()) { if (unsigned TypeQuals = DS.getTypeQualifiers()) {
@ -2596,8 +2595,8 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// Constructors and destructors don't have return types. Use // Constructors and destructors don't have return types. Use
// "void" instead. // "void" instead.
T = SemaRef.Context.VoidTy; T = SemaRef.Context.VoidTy;
if (AttributeList *attrs = D.getDeclSpec().getAttributes().getList()) processTypeAttrs(state, T, TAL_DeclSpec,
processTypeAttrs(state, T, TAL_DeclSpec, attrs); D.getDeclSpec().getAttributes().getList());
break; break;
case UnqualifiedId::IK_ConversionFunctionId: case UnqualifiedId::IK_ConversionFunctionId:
@ -4112,8 +4111,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
} }
// See if there are any attributes on this declarator chunk. // See if there are any attributes on this declarator chunk.
if (AttributeList *attrs = const_cast<AttributeList*>(DeclType.getAttrs())) processTypeAttrs(state, T, TAL_DeclChunk,
processTypeAttrs(state, T, TAL_DeclChunk, attrs); const_cast<AttributeList *>(DeclType.getAttrs()));
} }
assert(!T.isNull() && "T must not be null after this point"); 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. // Apply any undistributed attributes from the declarator.
if (AttributeList *attrs = D.getAttributes()) processTypeAttrs(state, T, TAL_DeclName, D.getAttributes());
processTypeAttrs(state, T, TAL_DeclName, attrs);
// Diagnose any ignored type attributes. // Diagnose any ignored type attributes.
state.diagnoseIgnoredTypeAttrs(T); 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 // 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. // apply to the decl. Here we apply type attributes and ignore the rest.
AttributeList *next; bool hasOpenCLAddressSpace = false;
do { while (attrs) {
AttributeList &attr = *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. // Skip attributes that were marked to be invalid.
if (attr.isInvalid()) if (attr.isInvalid())
@ -6238,6 +6237,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
case AttributeList::AT_AddressSpace: case AttributeList::AT_AddressSpace:
HandleAddressSpaceTypeAttribute(type, attr, state.getSema()); HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
attr.setUsedAsTypeAttr(); attr.setUsedAsTypeAttr();
hasOpenCLAddressSpace = true;
break; break;
OBJC_POINTER_TYPE_ATTRS_CASELIST: OBJC_POINTER_TYPE_ATTRS_CASELIST:
if (!handleObjCPointerTypeAttr(state, attr, type)) if (!handleObjCPointerTypeAttr(state, attr, type))
@ -6332,7 +6332,39 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
distributeFunctionTypeAttr(state, attr, type); distributeFunctionTypeAttr(state, attr, type);
break; 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. /// \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* %arg
// CHECK: i32* nocapture %arg void f__p(__private int *arg) {}
void f__g(__global int *arg) { } // CHECK: i32 addrspace(1)* %arg
// CHECK: i32 addrspace(1)* nocapture %arg void f__g(__global int *arg) {}
void f__l(__local int *arg) { } // CHECK: i32 addrspace(2)* %arg
// CHECK: i32 addrspace(2)* nocapture %arg void f__l(__local int *arg) {}
void f__c(__constant int *arg) { } // CHECK: i32 addrspace(3)* %arg
// CHECK: i32 addrspace(3)* nocapture %arg void f__c(__constant int *arg) {}
// CHECK: i32* %arg
void fp(private int *arg) {}
void fp(private int *arg) { } // CHECK: i32 addrspace(1)* %arg
// CHECK: i32* nocapture %arg void fg(global int *arg) {}
void fg(global int *arg) { } // CHECK: i32 addrspace(2)* %arg
// CHECK: i32 addrspace(1)* nocapture %arg void fl(local int *arg) {}
void fl(local int *arg) { } // CHECK: i32 addrspace(3)* %arg
// CHECK: i32 addrspace(2)* nocapture %arg void fc(constant int *arg) {}
void fc(constant int *arg) { } #ifdef CL20
// CHECK: i32 addrspace(3)* nocapture %arg 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 // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -DCL20 -cl-std=CL2.0
static constant int G1 = 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; global int G3 = 0;
local int G4 = 0;// expected-error{{program scope variable must reside in global or constant address space}} local int G4 = 0;// expected-error{{program scope variable must reside in global or constant address space}}
void kernel foo() { 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 global int S2 = 5;
static private int S3 = 5;// expected-error{{program scope variable must reside in global or constant address space}} static private int S3 = 5;// expected-error{{program scope variable must reside in global or constant address space}}