r253405 - Produce a better diagnostic for global register variables.

Akira Hatanaka via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 17 16:15:29 PST 2015


Author: ahatanak
Date: Tue Nov 17 18:15:28 2015
New Revision: 253405

URL: http://llvm.org/viewvc/llvm-project?rev=253405&view=rev
Log:
Produce a better diagnostic for global register variables.

Currently, when there is a global register variable in a program that
is bound to an invalid register, clang/llvm prints an error message that
is not very user-friendly.

This commit improves the diagnostic and moves the check that used to be
in the backend to Sema. In addition, it makes changes to error out if
the size of the register doesn't match the declared variable size.

e.g., volatile register int B asm ("rbp");

rdar://problem/23084219

Differential Revision: http://reviews.llvm.org/D13834

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/TargetInfo.h
    cfe/trunk/lib/Basic/Targets.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/CodeGen/named_reg_global.c
    cfe/trunk/test/OpenMP/atomic_capture_codegen.cpp
    cfe/trunk/test/OpenMP/atomic_read_codegen.c
    cfe/trunk/test/OpenMP/atomic_update_codegen.cpp
    cfe/trunk/test/OpenMP/atomic_write_codegen.c
    cfe/trunk/test/OpenMP/for_loop_messages.cpp
    cfe/trunk/test/OpenMP/threadprivate_messages.cpp
    cfe/trunk/test/Sema/asm.c
    cfe/trunk/test/SemaCUDA/asm-constraints-mixed.cu

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=253405&r1=253404&r2=253405&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Nov 17 18:15:28 2015
@@ -6543,6 +6543,10 @@ let CategoryName = "Inline Assembly Issu
     "asm constraint has an unexpected number of alternatives: %0 vs %1">;
   def err_asm_incomplete_type : Error<"asm operand has incomplete type %0">;
   def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">;
+  def err_asm_invalid_global_var_reg : Error<"register '%0' unsuitable for "
+    "global register variables on this target">;
+  def err_asm_register_size_mismatch : Error<"size of register '%0' does not "
+    "match variable size">;
   def err_asm_bad_register_type : Error<"bad type for named register variable">;
   def err_asm_invalid_input_size : Error<
     "invalid input size for constraint '%0'">;

Modified: cfe/trunk/include/clang/Basic/TargetInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TargetInfo.h?rev=253405&r1=253404&r2=253405&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TargetInfo.h (original)
+++ cfe/trunk/include/clang/Basic/TargetInfo.h Tue Nov 17 18:15:28 2015
@@ -644,6 +644,19 @@ public:
     }
   };
 
+  /// \brief Validate register name used for global register variables.
+  ///
+  /// This function returns true if the register passed in RegName can be used
+  /// for global register variables on this target. In addition, it returns
+  /// true in HasSizeMismatch if the size of the register doesn't match the
+  /// variable size passed in RegSize.
+  virtual bool validateGlobalRegisterVariable(StringRef RegName,
+                                              unsigned RegSize,
+                                              bool &HasSizeMismatch) const {
+    HasSizeMismatch = false;
+    return true;
+  }
+
   // validateOutputConstraint, validateInputConstraint - Checks that
   // a constraint is valid and provides information about it.
   // FIXME: These should return a real error instead of just true/false.

Modified: cfe/trunk/lib/Basic/Targets.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets.cpp?rev=253405&r1=253404&r2=253405&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Targets.cpp (original)
+++ cfe/trunk/lib/Basic/Targets.cpp Tue Nov 17 18:15:28 2015
@@ -2358,6 +2358,20 @@ public:
   bool validateAsmConstraint(const char *&Name,
                              TargetInfo::ConstraintInfo &info) const override;
 
+  bool validateGlobalRegisterVariable(StringRef RegName,
+                                      unsigned RegSize,
+                                      bool &HasSizeMismatch) const override {
+    // esp and ebp are the only 32-bit registers the x86 backend can currently
+    // handle.
+    if (RegName.equals("esp") || RegName.equals("ebp")) {
+      // Check that the register size is 32-bit.
+      HasSizeMismatch = RegSize != 32;
+      return true;
+    }
+
+    return false;
+  }
+
   bool validateOutputSize(StringRef Constraint, unsigned Size) const override;
 
   bool validateInputSize(StringRef Constraint, unsigned Size) const override;
@@ -3974,6 +3988,22 @@ public:
 
   // for x32 we need it here explicitly
   bool hasInt128Type() const override { return true; }
+
+  bool validateGlobalRegisterVariable(StringRef RegName,
+                                      unsigned RegSize,
+                                      bool &HasSizeMismatch) const override {
+    // rsp and rbp are the only 64-bit registers the x86 backend can currently
+    // handle.
+    if (RegName.equals("rsp") || RegName.equals("rbp")) {
+      // Check that the register size is 64-bit.
+      HasSizeMismatch = RegSize != 64;
+      return true;
+    }
+
+    // Check if the register is a 32-bit register the backend can handle.
+    return X86TargetInfo::validateGlobalRegisterVariable(RegName, RegSize,
+                                                         HasSizeMismatch);
+  }
 };
 
 // x86-64 Windows target

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=253405&r1=253404&r2=253405&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Nov 17 18:15:28 2015
@@ -6079,9 +6079,20 @@ Sema::ActOnVariableDeclarator(Scope *S,
       }
     } else if (SC == SC_Register) {
       // Global Named register
-      if (!Context.getTargetInfo().isValidGCCRegisterName(Label) &&
-          DeclAttrsMatchCUDAMode(getLangOpts(), NewVD))
-        Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label;
+      if (DeclAttrsMatchCUDAMode(getLangOpts(), NewVD)) {
+        const auto &TI = Context.getTargetInfo();
+        bool HasSizeMismatch;
+
+        if (!TI.isValidGCCRegisterName(Label))
+          Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label;
+        else if (!TI.validateGlobalRegisterVariable(Label,
+                                                    Context.getTypeSize(R),
+                                                    HasSizeMismatch))
+          Diag(E->getExprLoc(), diag::err_asm_invalid_global_var_reg) << Label;
+        else if (HasSizeMismatch)
+          Diag(E->getExprLoc(), diag::err_asm_register_size_mismatch) << Label;
+      }
+
       if (!R->isIntegralType(Context) && !R->isPointerType()) {
         Diag(D.getLocStart(), diag::err_asm_bad_register_type);
         NewVD->setInvalidDecl(true);

Modified: cfe/trunk/test/CodeGen/named_reg_global.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/named_reg_global.c?rev=253405&r1=253404&r2=253405&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/named_reg_global.c (original)
+++ cfe/trunk/test/CodeGen/named_reg_global.c Tue Nov 17 18:15:28 2015
@@ -1,16 +1,26 @@
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -S -emit-llvm %s -o - | FileCheck %s
-// RUN: %clang_cc1 -triple arm64-linux-gnu -S -emit-llvm %s -o - | FileCheck %s
-// RUN: %clang_cc1 -triple armv7-linux-gnu -S -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-X86-64
+// RUN: %clang_cc1 -triple arm64-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ARM
+// RUN: %clang_cc1 -triple armv7-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ARM
 
 // CHECK-NOT: @sp = common global
+
+#if defined(__x86_64__)
+register unsigned long current_stack_pointer asm("rsp");
+#else
 register unsigned long current_stack_pointer asm("sp");
+#endif
+
 struct p4_Thread {
   struct {
     int len;
   } word;
 };
 // Testing pointer types as well
+#if defined(__x86_64__)
+register struct p4_Thread *p4TH asm("rsp");
+#else
 register struct p4_Thread *p4TH asm("sp");
+#endif
 
 // CHECK: define{{.*}} i[[bits:[0-9]+]] @get_stack_pointer_addr()
 // CHECK: [[ret:%[0-9]+]] = call i[[bits]] @llvm.read_register.i[[bits]](metadata !0)
@@ -43,5 +53,7 @@ void fn2(struct p4_Thread *val) {
 // CHECK: %[[regw:[0-9]+]] = ptrtoint %struct.p4_Thread* %{{.*}} to i[[bits]]
 // CHECK: call void @llvm.write_register.i[[bits]](metadata !0, i[[bits]] %[[regw]])
 
-// CHECK: !llvm.named.register.sp = !{!0}
-// CHECK: !0 = !{!"sp"}
+// CHECK-X86-64: !llvm.named.register.rsp = !{!0}
+// CHECK-X86-64: !0 = !{!"rsp"}
+// CHECK-ARM: !llvm.named.register.sp = !{!0}
+// CHECK-ARM: !0 = !{!"sp"}

Modified: cfe/trunk/test/OpenMP/atomic_capture_codegen.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/atomic_capture_codegen.cpp?rev=253405&r1=253404&r2=253405&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/atomic_capture_codegen.cpp (original)
+++ cfe/trunk/test/OpenMP/atomic_capture_codegen.cpp Tue Nov 17 18:15:28 2015
@@ -72,7 +72,10 @@ struct BitFields4_packed {
 typedef float float2 __attribute__((ext_vector_type(2)));
 float2 float2x;
 
-register int rix __asm__("0");
+// Register "0" is currently an invalid register for global register variables.
+// Use "esp" instead of "0".
+// register int rix __asm__("0");
+register int rix __asm__("esp");
 
 int main() {
 // CHECK: [[PREV:%.+]] = atomicrmw add i8* @{{.+}}, i8 1 monotonic

Modified: cfe/trunk/test/OpenMP/atomic_read_codegen.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/atomic_read_codegen.c?rev=253405&r1=253404&r2=253405&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/atomic_read_codegen.c (original)
+++ cfe/trunk/test/OpenMP/atomic_read_codegen.c Tue Nov 17 18:15:28 2015
@@ -72,7 +72,10 @@ struct BitFields4_packed {
 typedef float float2 __attribute__((ext_vector_type(2)));
 float2 float2x;
 
-register int rix __asm__("0");
+// Register "0" is currently an invalid register for global register variables.
+// Use "esp" instead of "0".
+// register int rix __asm__("0");
+register int rix __asm__("esp");
 
 int main() {
 // CHECK: load atomic i8, i8*

Modified: cfe/trunk/test/OpenMP/atomic_update_codegen.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/atomic_update_codegen.cpp?rev=253405&r1=253404&r2=253405&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/atomic_update_codegen.cpp (original)
+++ cfe/trunk/test/OpenMP/atomic_update_codegen.cpp Tue Nov 17 18:15:28 2015
@@ -72,7 +72,10 @@ struct BitFields4_packed {
 typedef float float2 __attribute__((ext_vector_type(2)));
 float2 float2x;
 
-register int rix __asm__("0");
+// Register "0" is currently an invalid register for global register variables.
+// Use "esp" instead of "0".
+// register int rix __asm__("0");
+register int rix __asm__("esp");
 
 int main() {
 // CHECK-NOT: atomicrmw

Modified: cfe/trunk/test/OpenMP/atomic_write_codegen.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/atomic_write_codegen.c?rev=253405&r1=253404&r2=253405&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/atomic_write_codegen.c (original)
+++ cfe/trunk/test/OpenMP/atomic_write_codegen.c Tue Nov 17 18:15:28 2015
@@ -72,7 +72,10 @@ struct BitFields4_packed {
 typedef float float2 __attribute__((ext_vector_type(2)));
 float2 float2x;
 
-register int rix __asm__("0");
+// Register "0" is currently an invalid register for global register variables.
+// Use "esp" instead of "0".
+// register int rix __asm__("0");
+register int rix __asm__("esp");
 
 int main() {
 // CHECK: load i8, i8*

Modified: cfe/trunk/test/OpenMP/for_loop_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_loop_messages.cpp?rev=253405&r1=253404&r2=253405&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_loop_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/for_loop_messages.cpp Tue Nov 17 18:15:28 2015
@@ -13,7 +13,9 @@ static int sii;
 #pragma omp threadprivate(sii)
 static int globalii;
 
-register int reg0 __asm__("0");
+// Currently, we cannot use "0" for global register variables.
+// register int reg0 __asm__("0");
+int reg0;
 
 int test_iteration_spaces() {
   const int N = 100;

Modified: cfe/trunk/test/OpenMP/threadprivate_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/threadprivate_messages.cpp?rev=253405&r1=253404&r2=253405&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/threadprivate_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/threadprivate_messages.cpp Tue Nov 17 18:15:28 2015
@@ -96,7 +96,10 @@ class TempClass {
 static __thread int t; // expected-note {{'t' defined here}}
 #pragma omp threadprivate (t) // expected-error {{variable 't' cannot be threadprivate because it is thread-local}}
 
-register int reg0 __asm__("0"); // expected-note {{'reg0' defined here}}
+// Register "0" is currently an invalid register for global register variables.
+// Use "esp" instead of "0".
+// register int reg0 __asm__("0");
+register int reg0 __asm__("esp"); // expected-note {{'reg0' defined here}}
 #pragma omp threadprivate (reg0) // expected-error {{variable 'reg0' cannot be threadprivate because it is a global named register variable}}
 
 int o; // expected-note {{candidate found by name lookup is 'o'}}

Modified: cfe/trunk/test/Sema/asm.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/asm.c?rev=253405&r1=253404&r2=253405&view=diff
==============================================================================
--- cfe/trunk/test/Sema/asm.c (original)
+++ cfe/trunk/test/Sema/asm.c Tue Nov 17 18:15:28 2015
@@ -1,7 +1,6 @@
 // RUN: %clang_cc1 %s -Wno-private-extern -triple i386-pc-linux-gnu -verify -fsyntax-only
 
 
-
 void f() {
   int i;
 
@@ -154,10 +153,13 @@ double test15() {
 // PR19837
 struct foo {
   int a;
-  char b;
 };
-register struct foo bar asm("sp"); // expected-error {{bad type for named register variable}}
-register float baz asm("sp"); // expected-error {{bad type for named register variable}}
+register struct foo bar asm("esp"); // expected-error {{bad type for named register variable}}
+register float baz asm("esp"); // expected-error {{bad type for named register variable}}
+
+register int r0 asm ("edi"); // expected-error {{register 'edi' unsuitable for global register variables on this target}}
+register long long r1 asm ("esp"); // expected-error {{size of register 'esp' does not match variable size}}
+register int r2 asm ("esp");
 
 double f_output_constraint(void) {
   double result;
@@ -212,7 +214,7 @@ typedef struct test16_foo {
   unsigned int field3 : 3;
 } test16_foo;
 typedef __attribute__((vector_size(16))) int test16_bar;
-register int test16_baz asm("rbx");
+register int test16_baz asm("esp");
 
 void test16()
 {

Modified: cfe/trunk/test/SemaCUDA/asm-constraints-mixed.cu
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCUDA/asm-constraints-mixed.cu?rev=253405&r1=253404&r2=253405&view=diff
==============================================================================
--- cfe/trunk/test/SemaCUDA/asm-constraints-mixed.cu (original)
+++ cfe/trunk/test/SemaCUDA/asm-constraints-mixed.cu Tue Nov 17 18:15:28 2015
@@ -5,14 +5,14 @@
 
 __attribute__((device)) register long global_dev_reg asm("r0");
 __attribute__((device)) register long
-    global_dev_hreg asm("rax"); // device-side error
+    global_dev_hreg asm("rsp"); // device-side error
 
-register long global_host_reg asm("rax");
+register long global_host_reg asm("rsp");
 register long global_host_dreg asm("r0"); // host-side error
 
 __attribute__((device)) void df() {
   register long local_dev_reg asm("r0");
-  register long local_host_reg asm("rax"); // device-side error
+  register long local_host_reg asm("rsp"); // device-side error
   short h;
   // asm with PTX constraints. Some of them are PTX-specific.
   __asm__("dont care" : "=h"(h) : "f"(0.0), "d"(0.0), "h"(0), "r"(0), "l"(0));
@@ -20,7 +20,7 @@ __attribute__((device)) void df() {
 
 void hf() {
   register long local_dev_reg asm("r0"); // host-side error
-  register long local_host_reg asm("rax");
+  register long local_host_reg asm("rsp");
   int a;
   // Asm with x86 constraints and registers that are not supported by PTX.
   __asm__("dont care" : "=a"(a) : "a"(0), "b"(0), "c"(0) : "flags");
@@ -30,8 +30,8 @@ void hf() {
 // We should only see errors relevant to current compilation mode.
 #if defined(__CUDA_ARCH__)
 // Device-side compilation:
-// expected-error at 8 {{unknown register name 'rax' in asm}}
-// expected-error at 15 {{unknown register name 'rax' in asm}}
+// expected-error at 8 {{unknown register name 'rsp' in asm}}
+// expected-error at 15 {{unknown register name 'rsp' in asm}}
 #else
 // Host-side compilation:
 // expected-error at 11 {{unknown register name 'r0' in asm}}




More information about the cfe-commits mailing list