scott.linder created this revision.
scott.linder added reviewers: Anastasia, tra, yaxunl, rjmccall.
Herald added subscribers: cfe-commits, tpr.
Herald added a project: clang.

For AMDGPU the visibility of these symbols (OpenCL kernels, CUDA `__global__` 
functions, and CUDA `__device__` variables) must not be hidden, as we rely on 
them being available in the dynamic symbol table in the final DSO.

This patch implements this by considering language attributes as a source of 
explicit visibility, but rather than attributing any one visibility to them 
they are simply coerced to be a non-hidden visibility. This allows for the 
optimization of using protected visibility when these symbols are known to be 
`dso_local`.

This patch also adds diagnostics for explicitly setting a hidden visibility on 
these symbols.

I imagine there are a number of issues with the patch in its current state, but 
I wanted to get something implemented before reaching out to OpenCL/CUDA 
maintainers to see if this is a reasonable change. @Anastasia and @tra I wasn't 
certain if you would be good candidates to discuss this change, so please let 
me know if I need to keep looking.


Repository:
  rC Clang

https://reviews.llvm.org/D61274

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Basic/Visibility.h
  lib/AST/Decl.cpp
  lib/CodeGen/TargetInfo.cpp
  lib/Sema/SemaDeclAttr.cpp
  test/SemaCUDA/visibility-diagnostics.cu
  test/SemaOpenCL/visibility-diagnostics.cl

Index: test/SemaOpenCL/visibility-diagnostics.cl
===================================================================
--- /dev/null
+++ test/SemaOpenCL/visibility-diagnostics.cl
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -std=cl2.0 -verify -pedantic -fsyntax-only %s
+
+__attribute__((visibility("hidden"))) kernel void kern_hidden() {} // expected-warning {{'hidden' visibility on function with incompatible language attribute will be ignored}}
+__attribute__((visibility("protected"))) kernel void kern_protected();
+__attribute__((visibility("default"))) kernel void kern_default();
+kernel void kern();
+
+__attribute__((visibility("hidden"))) extern kernel void ext_kern_hidden(); // expected-warning {{'hidden' visibility on function with incompatible language attribute will be ignored}}
+__attribute__((visibility("protected"))) extern kernel void ext_kern_protected();
+__attribute__((visibility("default"))) extern kernel void ext_kern_default();
+extern kernel void ext_kern();
Index: test/SemaCUDA/visibility-diagnostics.cu
===================================================================
--- /dev/null
+++ test/SemaCUDA/visibility-diagnostics.cu
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+#include "Inputs/cuda.h"
+
+__attribute__((visibility("hidden"))) __global__ void global_func_hidden() {} // expected-warning {{'hidden' visibility on function with incompatible language attribute will be ignored}}
+__attribute__((visibility("protected"))) __global__ void global_func_protected() {}
+__attribute__((visibility("default"))) __global__ void global_func_default() {}
+__global__ void global_func() {}
+
+__attribute__((visibility("hidden"))) __device__ int device_var_hidden; // expected-warning {{'hidden' visibility on variable with incompatible language attribute will be ignored}}
+__attribute__((visibility("protected"))) __device__ int device_var_protected;
+__attribute__((visibility("default"))) __device__ int device_var_default;
+__device__ int device_var;
Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -7375,6 +7375,16 @@
     Diag(D->getLocation(), diag::err_designated_init_attr_non_init);
     D->dropAttr<ObjCDesignatedInitializerAttr>();
   }
+
+  if ((D->hasAttr<VisibilityAttr>() &&
+       D->getAttr<VisibilityAttr>()->getVisibility() ==
+           VisibilityAttr::Hidden) &&
+      (D->hasAttr<OpenCLKernelAttr>() ||
+       (isa<FunctionDecl>(D) && D->hasAttr<CUDAGlobalAttr>()) ||
+       (isa<VarDecl>(D) && D->hasAttr<CUDADeviceAttr>()))) {
+    Diag(D->getLocation(), diag::warn_attribute_hidden_visibility)
+        << (isa<FunctionDecl>(D) ? 0 : 1);
+  }
 }
 
 // Helper for delayed processing TransparentUnion attribute.
Index: lib/CodeGen/TargetInfo.cpp
===================================================================
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -7840,23 +7840,8 @@
 };
 }
 
-static bool requiresAMDGPUProtectedVisibility(const Decl *D,
-                                              llvm::GlobalValue *GV) {
-  if (GV->getVisibility() != llvm::GlobalValue::HiddenVisibility)
-    return false;
-
-  return D->hasAttr<OpenCLKernelAttr>() ||
-         (isa<FunctionDecl>(D) && D->hasAttr<CUDAGlobalAttr>()) ||
-         (isa<VarDecl>(D) && D->hasAttr<CUDADeviceAttr>());
-}
-
 void AMDGPUTargetCodeGenInfo::setTargetAttributes(
     const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const {
-  if (requiresAMDGPUProtectedVisibility(D, GV)) {
-    GV->setVisibility(llvm::GlobalValue::ProtectedVisibility);
-    GV->setDSOLocal(true);
-  }
-
   if (GV->isDeclaration())
     return;
   const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
Index: lib/AST/Decl.cpp
===================================================================
--- lib/AST/Decl.cpp
+++ lib/AST/Decl.cpp
@@ -731,6 +731,19 @@
     }
   }
 
+  // We consider OpenCL kernels, __global__ Cuda functions, and __device__ Cuda
+  // variables to have explicit visibility of "non-hidden".
+  if (D->hasAttr<OpenCLKernelAttr>() ||
+      (isa<FunctionDecl>(D) && D->hasAttr<CUDAGlobalAttr>()) ||
+      (isa<VarDecl>(D) && D->hasAttr<CUDADeviceAttr>())) {
+    Visibility Vis = LV.getVisibility();
+    if (LV.getVisibility() == HiddenVisibility)
+      Vis = Context.getTargetInfo().hasProtectedVisibility()
+                ? ProtectedVisibility
+                : DefaultVisibility;
+    LV.setVisibility(Vis, true);
+  }
+
   // C++ [basic.link]p4:
 
   //   A name having namespace scope has external linkage if it is the
Index: include/clang/Basic/Visibility.h
===================================================================
--- include/clang/Basic/Visibility.h
+++ include/clang/Basic/Visibility.h
@@ -53,8 +53,6 @@
   uint8_t linkage_    : 3;
   uint8_t visibility_ : 2;
   uint8_t explicit_   : 1;
-
-  void setVisibility(Visibility V, bool E) { visibility_ = V; explicit_ = E; }
 public:
   LinkageInfo() : linkage_(ExternalLinkage), visibility_(DefaultVisibility),
                   explicit_(false) {}
@@ -86,6 +84,8 @@
 
   void setLinkage(Linkage L) { linkage_ = L; }
 
+  void setVisibility(Visibility V, bool E) { visibility_ = V; explicit_ = E; }
+
   void mergeLinkage(Linkage L) {
     setLinkage(minLinkage(getLinkage(), L));
   }
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -3362,6 +3362,9 @@
   InGroup<IgnoredAttributes>;
 def warn_attribute_unknown_visibility : Warning<"unknown visibility %0">,
   InGroup<IgnoredAttributes>;
+def warn_attribute_hidden_visibility :
+  Warning<"'hidden' visibility on %select{function|variable}0 with incompatible language attribute will be ignored">,
+  InGroup<IgnoredAttributes>;
 def warn_attribute_protected_visibility :
   Warning<"target does not support 'protected' visibility; using 'default'">,
   InGroup<DiagGroup<"unsupported-visibility">>;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to