yaxunl updated this revision to Diff 56194.
yaxunl added a comment.

Update the test.


http://reviews.llvm.org/D19932

Files:
  include/clang/Basic/Builtins.def
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/AST/Decl.cpp
  lib/CodeGen/CGBuiltin.cpp
  lib/Sema/SemaChecking.cpp
  lib/Sema/SemaExpr.cpp
  test/CodeGenOpenCL/to_addr_builtin.cl
  test/SemaOpenCL/to_addr_builtin.cl

Index: test/SemaOpenCL/to_addr_builtin.cl
===================================================================
--- /dev/null
+++ test/SemaOpenCL/to_addr_builtin.cl
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -verify -fsyntax-only %s
+// RUN: %clang_cc1 -verify -fsyntax-only -cl-std=CL2.0 %s
+
+void test(void) {
+  global int *glob;
+  local int *loc;
+  constant int *con;
+
+  glob = to_global(glob, loc);
+#if __OPENCL_C_VERSION__ < CL_VERSION_2_0
+  // expected-error@-2{{'to_global' needs OpenCL version 2.0 or above}}
+#else
+  // expected-error@-4{{invalid number of arguments to function: 'to_global'}}
+#endif
+
+  int x;
+  glob = to_global(x);
+#if __OPENCL_C_VERSION__ < CL_VERSION_2_0
+  // expected-error@-2{{'to_global' needs OpenCL version 2.0 or above}}
+#else
+  // expected-error@-4{{invalid argument x to function: 'to_global'}}
+#endif
+
+  glob = to_global(con);
+#if __OPENCL_C_VERSION__ < CL_VERSION_2_0
+  // expected-error@-2{{'to_global' needs OpenCL version 2.0 or above}}
+#else
+  // expected-error@-4{{invalid argument con to function: 'to_global'}}
+#endif
+
+  loc = to_global(glob);
+#if __OPENCL_C_VERSION__ < CL_VERSION_2_0
+  // expected-error@-2{{'to_global' needs OpenCL version 2.0 or above}}
+#else
+  // expected-error@-4{{assigning '__global int *' to '__local int *' changes address space of pointer}}
+#endif
+
+}
Index: test/CodeGenOpenCL/to_addr_builtin.cl
===================================================================
--- /dev/null
+++ test/CodeGenOpenCL/to_addr_builtin.cl
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -triple spir-unknown-unknown -emit-llvm -O0 -cl-std=CL2.0 -o - %s | FileCheck %s
+
+// CHECK: %[[A:.*]] = type { float, float, float }
+typedef struct {
+  float x,y,z;
+} A;
+typedef private A *PA;
+typedef global A *GA;
+
+void test(void) {
+  global int *glob;
+  local int *loc;
+  private int *priv;
+  generic int *gen;
+
+  //CHECK: call i32 addrspace(1)* @_Z9to_globalPU3AS1i(i32 addrspace(1)* %{{.*}})
+  glob = to_global(glob);
+  
+  //CHECK: call i32 addrspace(1)* @_Z9to_globalPU3AS3i(i32 addrspace(3)* %{{.*}})
+  glob = to_global(loc);
+ 
+   //CHECK: call i32 addrspace(1)* @_Z9to_globalPi(i32* %{{.*}})
+  glob = to_global(priv);
+ 
+   //CHECK: call i32 addrspace(1)* @_Z9to_globalPU3AS4i(i32 addrspace(4)* %{{.*}})
+  glob = to_global(gen);
+  
+  //CHECK: call i32 addrspace(3)* @_Z8to_localPU3AS1i(i32 addrspace(1)* %{{.*}})
+  loc = to_local(glob);
+
+  //CHECK: call i32 addrspace(3)* @_Z8to_localPU3AS3i(i32 addrspace(3)* %{{.*}})
+  loc = to_local(loc);
+
+  //CHECK: call i32 addrspace(3)* @_Z8to_localPi(i32* %{{.*}})
+  loc = to_local(priv);
+
+  //CHECK: call i32 addrspace(3)* @_Z8to_localPU3AS4i(i32 addrspace(4)* %{{.*}})
+  loc = to_local(gen);
+
+  //CHECK: call i32* @_Z10to_privatePU3AS1i(i32 addrspace(1)* %{{.*}})
+  priv = to_private(glob);
+
+  //CHECK: call i32* @_Z10to_privatePU3AS3i(i32 addrspace(3)* %{{.*}})
+  priv = to_private(loc);
+
+  //CHECK: call i32* @_Z10to_privatePi(i32* %{{.*}})
+  priv = to_private(priv);
+
+  //CHECK: call i32* @_Z10to_privatePU3AS4i(i32 addrspace(4)* %{{.*}})
+  priv = to_private(gen);
+
+  //CHECK; call %[[A]] addrspace(1)* @_Z9to_globalP1A(%[[A]]* %{{.*}})
+  PA pA;
+  GA gA = to_global(pA);
+}
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -5055,6 +5055,61 @@
   return Callee->getMinRequiredArguments() <= NumArgs;
 }
 
+/// OpenCL to_addr function accepts pointers to arbitrary type as argument.
+/// This function change the original declaration to match the argument.
+/// \return nullptr if this builtin is not OpenCL to_addr builtin function or
+///         there is no need to change the function declaration.
+static FunctionDecl *
+rewriteBuiltinFunctionDeclForOpenCLToAddr(Sema *Sema, ASTContext &Context,
+                                          const FunctionDecl *FDecl,
+                                          MultiExprArg ArgExprs) {
+  auto ID = FDecl->getBuiltinID();
+  if (ID != Builtin::BIto_global &&
+      ID != Builtin::BIto_local &&
+      ID != Builtin::BIto_private)
+    return nullptr;
+
+  auto ArgT = ArgExprs[0]->getType();
+  if (!ArgT->isPointerType())
+    return nullptr;
+
+  auto RT = ArgT->getPointeeType().getCanonicalType();
+  auto Qual = RT.getQualifiers();
+  switch (ID) {
+  case Builtin::BIto_global:
+    Qual.setAddressSpace(LangAS::opencl_global);
+    break;
+  case Builtin::BIto_local:
+    Qual.setAddressSpace(LangAS::opencl_local);
+    break;
+  default:
+    Qual.removeAddressSpace();
+  }
+  RT = Sema->Context.getPointerType(
+         Sema->Context.getQualifiedType(RT.getUnqualifiedType(), Qual));
+
+  QualType ParmTy[] = {ArgT};
+  FunctionProtoType::ExtProtoInfo EPI;
+  QualType OverloadTy = Context.getFunctionType(RT, ParmTy, EPI);
+  DeclContext *Parent = Context.getTranslationUnitDecl();
+  FunctionDecl *OverloadDecl = FunctionDecl::Create(Context, Parent,
+                                                    FDecl->getLocation(),
+                                                    FDecl->getLocation(),
+                                                    FDecl->getIdentifier(),
+                                                    OverloadTy,
+                                                    /*TInfo=*/nullptr,
+                                                    SC_Extern, false,
+                                                    /*hasPrototype=*/true);
+  ParmVarDecl *Parm[] = {
+    ParmVarDecl::Create(Context, OverloadDecl, SourceLocation(),
+                        SourceLocation(), nullptr, ArgT,
+                        /*TInfo=*/nullptr, SC_None, nullptr)};
+  Parm[0]->setScopeInfo(0, 0);
+  OverloadDecl->setParams(Parm);
+  OverloadDecl->addAttr(OverloadableAttr::CreateImplicit(Sema->Context));
+  return OverloadDecl;
+}
+
 /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
 /// This provides the location of the left/right parens and a list of comma
 /// locations.
@@ -5164,10 +5219,17 @@
 
     FunctionDecl *FDecl = dyn_cast<FunctionDecl>(NDecl);
     if (FDecl && FDecl->getBuiltinID()) {
-      // Rewrite the function decl for this builtin by replacing parameters
-      // with no explicit address space with the address space of the arguments
-      // in ArgExprs.
-      if ((FDecl = rewriteBuiltinFunctionDecl(this, Context, FDecl, ArgExprs))) {
+      // Rewrite the function decl for OpenCL to_addr builtin.
+      if (FunctionDecl *NFDecl = rewriteBuiltinFunctionDeclForOpenCLToAddr(
+        this, Context, FDecl, ArgExprs))
+        FDecl = NFDecl;
+      else {
+        // Rewrite the function decl for this builtin by replacing parameters
+        // with no explicit address space with the address space of the arguments
+        // in ArgExprs.
+        FDecl = rewriteBuiltinFunctionDecl(this, Context, FDecl, ArgExprs);
+      }
+      if (FDecl) {
         NDecl = FDecl;
         Fn = DeclRefExpr::Create(Context, FDecl->getQualifierLoc(),
                            SourceLocation(), FDecl, false,
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -455,6 +455,40 @@
   return false;
 }
 
+// \brief Performs semantic analysis for the to_global/local/private call.
+// \param S Reference to the semantic analyzer.
+// \param BuiltinID ID of the builtin function.
+// \param Call A pointer to the builtin call.
+// \return True if a semantic error has been found, false otherwise.
+static bool SemaBuiltinToAddr(Sema &S, unsigned BuiltinID, CallExpr *Call) {
+  // OpenCL v2.0 s6.13.9 - Address space qualifier functions.
+  if (S.getLangOpts().OpenCLVersion < 200) {
+    S.Diag(Call->getLocStart(), diag::err_builtin_needs_opencl_version)
+        << Call->getDirectCallee() << "2.0" << 1 << Call->getSourceRange();
+    return true;
+  }
+
+  if (Call->getNumArgs() != 1) {
+    S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_arg_num)
+        << Call->getDirectCallee() << Call->getSourceRange();
+    return true;
+  }
+
+  auto RT = Call->getArg(0)->getType();
+  if (!RT->isPointerType() || RT->getPointeeType().getCanonicalType()
+      .getQualifiers().getAddressSpace() == LangAS::opencl_constant) {
+    S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_invalid_arg)
+        << Call->getArg(0) << Call->getDirectCallee() << Call->getSourceRange();
+    return true;
+  }
+
+  // Builtin functions with custom check need to set the correct type of call
+  // expression by themselves since Sema::BuildResolvedCallExpr does not do that.
+  Call->setType(cast<FunctionDecl>(Call->getCalleeDecl())->getReturnType());
+
+  return false;
+}
+
 ExprResult
 Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
                                CallExpr *TheCall) {
@@ -789,6 +823,12 @@
     if (SemaBuiltinPipePackets(*this, TheCall))
       return ExprError();
     break;
+  case Builtin::BIto_global:
+  case Builtin::BIto_local:
+  case Builtin::BIto_private:
+    if (SemaBuiltinToAddr(*this, BuiltinID, TheCall))
+      return ExprError();
+    break;
   }
 
   // Since the target specific builtins for each arch overlap, only check those
Index: lib/CodeGen/CGBuiltin.cpp
===================================================================
--- lib/CodeGen/CGBuiltin.cpp
+++ lib/CodeGen/CGBuiltin.cpp
@@ -2124,6 +2124,20 @@
         Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), {Arg0}));
   }
 
+  // OpenCL v2.0 s6.13.9 Address space qualifier functions.
+  case Builtin::BIto_global:
+  case Builtin::BIto_local:
+  case Builtin::BIto_private: {
+    Value *Arg0 = EmitScalarExpr(E->getArg(0));
+    llvm::Type *ArgTys[] = {Arg0->getType()};
+    llvm::FunctionType *FTy = llvm::FunctionType::get(
+        ConvertType(E->getType()), llvm::ArrayRef<llvm::Type *>(ArgTys),
+        false);
+    return RValue::get(
+        Builder.CreateCall(CGM.CreateRuntimeFunction(FTy,
+          CGM.getMangledName(E->getDirectCallee())), {Arg0}));
+  }
+
   case Builtin::BIprintf:
     if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice)
       return EmitCUDADevicePrintfCallExpr(E, ReturnValue);
Index: lib/AST/Decl.cpp
===================================================================
--- lib/AST/Decl.cpp
+++ lib/AST/Decl.cpp
@@ -2719,7 +2719,8 @@
 
   // If the function is marked "overloadable", it has a different mangled name
   // and is not the C library function.
-  if (hasAttr<OverloadableAttr>())
+  // OpenCL builtin functions can be overloaded.
+  if (hasAttr<OverloadableAttr>() && !Context.getLangOpts().OpenCL)
     return 0;
 
   if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -498,6 +498,8 @@
 def err_arm_invalid_specialreg : Error<"invalid special register for builtin">;
 def err_invalid_cpu_supports : Error<"invalid cpu feature string for builtin">;
 def err_builtin_needs_feature : Error<"%0 needs target feature %1">;
+def err_builtin_needs_opencl_version
+    : Error<"%0 needs OpenCL version %1%select{| or above}2">;
 def err_function_needs_feature
     : Error<"always_inline function %1 requires target feature '%2', but would "
             "be inlined into function %0 that is compiled without support for "
@@ -7860,6 +7862,11 @@
 def err_opencl_extern_block_declaration : Error<
   "invalid block variable declaration - using 'extern' storage class is disallowed">;
 
+// OpenCL v2.0 s6.13.9 - Address space qualifier functions. 
+def err_opencl_builtin_to_addr_arg_num : Error<
+  "invalid number of arguments to function: %0">;
+def err_opencl_builtin_to_addr_invalid_arg : Error<
+  "invalid argument %0 to function: %1">;
 } // end of sema category
 
 let CategoryName = "OpenMP Issue" in {
Index: include/clang/Basic/Builtins.def
===================================================================
--- include/clang/Basic/Builtins.def
+++ include/clang/Basic/Builtins.def
@@ -1288,6 +1288,11 @@
 LANGBUILTIN(get_pipe_num_packets, "Ui.", "tn", OCLC_LANG)
 LANGBUILTIN(get_pipe_max_packets, "Ui.", "tn", OCLC_LANG)
 
+// OpenCL v2.0 s6.13.9 - Address space qualifier functions.
+LANGBUILTIN(to_global, "v*v*", "tn", OCLC_LANG)
+LANGBUILTIN(to_local, "v*v*", "tn", OCLC_LANG)
+LANGBUILTIN(to_private, "v*v*", "tn", OCLC_LANG)
+
 #undef BUILTIN
 #undef LIBBUILTIN
 #undef LANGBUILTIN
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to