Anastasia created this revision.
Anastasia added a reviewer: pekka.jaaskelainen.
Anastasia added a subscriber: cfe-commits.

If address space (AS) of a variable/parameter declaration is not set, OpenCL2.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

Files:
  lib/Sema/SemaType.cpp
  test/CodeGenOpenCL/address-spaces.cl
  test/SemaOpenCL/storageclass-cl20.cl

Index: test/SemaOpenCL/storageclass-cl20.cl
===================================================================
--- test/SemaOpenCL/storageclass-cl20.cl
+++ test/SemaOpenCL/storageclass-cl20.cl
@@ -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}}
 
Index: test/CodeGenOpenCL/address-spaces.cl
===================================================================
--- test/CodeGenOpenCL/address-spaces.cl
+++ test/CodeGenOpenCL/address-spaces.cl
@@ -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
+}
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -1545,8 +1545,7 @@
   // 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()) {
@@ -2580,8 +2579,8 @@
     // 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:
@@ -4071,8 +4070,8 @@
     }
 
     // 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");
@@ -4165,8 +4164,7 @@
   }
 
   // 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);
@@ -6102,10 +6100,11 @@
   // 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())
@@ -6164,6 +6163,7 @@
     case AttributeList::AT_AddressSpace:
       HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
       attr.setUsedAsTypeAttr();
+      hasOpenCLAddressSpace = true;
       break;
     OBJC_POINTER_TYPE_ATTRS_CASELIST:
       if (!handleObjCPointerTypeAttr(state, attr, type))
@@ -6258,7 +6258,39 @@
         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.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to