[clang] [clang][AArch64] Avoid a crash when a non-reserved register is used (PR #117419)

Igor Kudrin via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 5 20:24:54 PST 2024


https://github.com/igorkudrin updated https://github.com/llvm/llvm-project/pull/117419

>From 54fc788cca22b1b30313f4349d9ef2ba8cf58079 Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Fri, 22 Nov 2024 21:36:54 -0800
Subject: [PATCH 1/3] [clang][AArch64] Avoid a crash when a non-reserved
 register is used

Fixes #76426

The previous patch for this issue, #94271, generated an error message if
a register and a global variable did not have the same size. This patch
checks if the register is actually reserved.
---
 clang/lib/Basic/Targets/AArch64.cpp            | 18 ++++++++++++++----
 .../test/Sema/aarch64-fixed-global-register.c  |  4 +++-
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp
index eb8a3ada034482..7500c7bb045e54 100644
--- a/clang/lib/Basic/Targets/AArch64.cpp
+++ b/clang/lib/Basic/Targets/AArch64.cpp
@@ -232,13 +232,23 @@ bool AArch64TargetInfo::validateTarget(DiagnosticsEngine &Diags) const {
 
 bool AArch64TargetInfo::validateGlobalRegisterVariable(
     StringRef RegName, unsigned RegSize, bool &HasSizeMismatch) const {
-  if ((RegName == "sp") || RegName.starts_with("x")) {
-    HasSizeMismatch = RegSize != 64;
-    return true;
-  } else if (RegName.starts_with("w")) {
+  if (RegName.starts_with("w")) {
     HasSizeMismatch = RegSize != 32;
     return true;
   }
+  if (RegName == "sp") {
+    HasSizeMismatch = RegSize != 64;
+    return true;
+  }
+  if (RegName.starts_with("x")) {
+    HasSizeMismatch = RegSize != 64;
+    // Check if the register is reserved. See also
+    // AArch64TargetLowering::getRegisterByName().
+    return RegName == "x0" ||
+           (RegName == "x18" &&
+            llvm::AArch64::isX18ReservedByDefault(getTriple())) ||
+           getTargetOpts().FeatureMap.lookup(("reserve-" + RegName).str());
+  }
   return false;
 }
 
diff --git a/clang/test/Sema/aarch64-fixed-global-register.c b/clang/test/Sema/aarch64-fixed-global-register.c
index 9b4a422d8c1b2c..2b7d39dbcdd6f8 100644
--- a/clang/test/Sema/aarch64-fixed-global-register.c
+++ b/clang/test/Sema/aarch64-fixed-global-register.c
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -triple aarch64-unknown-none-gnu %s -verify -fsyntax-only
+// RUN: %clang_cc1 -triple aarch64-unknown-none-gnu %s -target-feature +reserve-x4 -target-feature +reserve-x15 -verify -fsyntax-only
 
 register char i1 __asm__ ("x15"); // expected-error {{size of register 'x15' does not match variable size}}
 register long long l2 __asm__ ("w14"); // expected-error {{size of register 'w14' does not match variable size}}
+register long x3 __asm__ ("x3"); // expected-error {{register 'x3' unsuitable for global register variables on this target}}
+register long x4 __asm__ ("x4");

>From 1f1fe3df8db0e7cc1a50aa49a061c857ecdc11a4 Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Mon, 25 Nov 2024 20:47:06 -0800
Subject: [PATCH 2/3] fixup: Improve tests

---
 .../CodeGen/AArch64/fixed-register-global.c   | 22 +++++++++++++++++++
 .../Driver/aarch64-fixed-register-global.c    | 12 ----------
 .../test/Sema/aarch64-fixed-global-register.c |  5 ++++-
 3 files changed, 26 insertions(+), 13 deletions(-)
 create mode 100644 clang/test/CodeGen/AArch64/fixed-register-global.c
 delete mode 100644 clang/test/Driver/aarch64-fixed-register-global.c

diff --git a/clang/test/CodeGen/AArch64/fixed-register-global.c b/clang/test/CodeGen/AArch64/fixed-register-global.c
new file mode 100644
index 00000000000000..afaddc1f3f1128
--- /dev/null
+++ b/clang/test/CodeGen/AArch64/fixed-register-global.c
@@ -0,0 +1,22 @@
+/// Check that -ffixed register handled for globals.
+/// Regression test for #76426, #109778
+
+// RUN: %clang -c --target=aarch64-none-gnu -ffixed-x15 %s 2>&1 | count 0
+
+// RUN: not %clang -c --target=aarch64-none-gnu %s 2>&1 | \
+// RUN:   FileCheck %s --check-prefix=ERR_INVREG
+// ERR_INVREG: error: register 'x15' unsuitable for global register variables on this target
+
+// RUN: not %clang -c --target=aarch64-none-gnu -ffixed-x15 -DTYPE=short %s 2>&1 | \
+// RUN:   FileCheck %s --check-prefix=ERR_SIZE
+// ERR_SIZE: error: size of register 'x15' does not match variable size
+
+#ifndef TYPE
+#define TYPE long
+#endif
+
+register TYPE x15 __asm__("x15");
+
+TYPE foo() {
+  return x15;
+}
diff --git a/clang/test/Driver/aarch64-fixed-register-global.c b/clang/test/Driver/aarch64-fixed-register-global.c
deleted file mode 100644
index 7b1fb118fcdf71..00000000000000
--- a/clang/test/Driver/aarch64-fixed-register-global.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// Check that -ffixed register handled for globals.
-// Regression test for #76426
-// RUN: %clang --target=aarch64-none-gnu -ffixed-x15 -### %s 2>&1 | FileCheck %s
-// CHECK-NOT: fatal error: error in backend: Invalid register name "x15".
-register int i1 __asm__("x15");
-
-int foo() {
-  return i1;
-}
-int main() {
-  return foo();
-}
diff --git a/clang/test/Sema/aarch64-fixed-global-register.c b/clang/test/Sema/aarch64-fixed-global-register.c
index 2b7d39dbcdd6f8..9515f5ec7fbe82 100644
--- a/clang/test/Sema/aarch64-fixed-global-register.c
+++ b/clang/test/Sema/aarch64-fixed-global-register.c
@@ -1,6 +1,9 @@
-// RUN: %clang_cc1 -triple aarch64-unknown-none-gnu %s -target-feature +reserve-x4 -target-feature +reserve-x15 -verify -fsyntax-only
+// RUN: %clang_cc1 -triple aarch64-unknown-none-gnu %s -target-feature +reserve-x4 -target-feature +reserve-x15 -verify -verify=no_x18 -fsyntax-only
+// RUN: %clang_cc1 -triple aarch64-unknown-android %s -target-feature +reserve-x4 -target-feature +reserve-x15 -verify -fsyntax-only
 
+register long x0 __asm__ ("x0");
 register char i1 __asm__ ("x15"); // expected-error {{size of register 'x15' does not match variable size}}
 register long long l2 __asm__ ("w14"); // expected-error {{size of register 'w14' does not match variable size}}
 register long x3 __asm__ ("x3"); // expected-error {{register 'x3' unsuitable for global register variables on this target}}
 register long x4 __asm__ ("x4");
+register long x18 __asm__ ("x18"); // no_x18-error {{register 'x18' unsuitable for global register variables on this target}}

>From 255ac9526b97e3a236db95c53ea927bf9ffe8280 Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Thu, 5 Dec 2024 20:24:27 -0800
Subject: [PATCH 3/3] fixup: also check w* registers

---
 clang/lib/Basic/Targets/AArch64.cpp           | 25 +++++++++----------
 .../test/Sema/aarch64-fixed-global-register.c |  6 ++++-
 2 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp
index 7500c7bb045e54..ce2a98943a44ff 100644
--- a/clang/lib/Basic/Targets/AArch64.cpp
+++ b/clang/lib/Basic/Targets/AArch64.cpp
@@ -232,24 +232,23 @@ bool AArch64TargetInfo::validateTarget(DiagnosticsEngine &Diags) const {
 
 bool AArch64TargetInfo::validateGlobalRegisterVariable(
     StringRef RegName, unsigned RegSize, bool &HasSizeMismatch) const {
-  if (RegName.starts_with("w")) {
-    HasSizeMismatch = RegSize != 32;
-    return true;
-  }
   if (RegName == "sp") {
     HasSizeMismatch = RegSize != 64;
     return true;
   }
-  if (RegName.starts_with("x")) {
+  if (RegName.starts_with("w"))
+    HasSizeMismatch = RegSize != 32;
+  else if (RegName.starts_with("x"))
     HasSizeMismatch = RegSize != 64;
-    // Check if the register is reserved. See also
-    // AArch64TargetLowering::getRegisterByName().
-    return RegName == "x0" ||
-           (RegName == "x18" &&
-            llvm::AArch64::isX18ReservedByDefault(getTriple())) ||
-           getTargetOpts().FeatureMap.lookup(("reserve-" + RegName).str());
-  }
-  return false;
+  else
+    return false;
+  StringRef RegNum = RegName.drop_front();
+  // Check if the register is reserved. See also
+  // AArch64TargetLowering::getRegisterByName().
+  return RegNum == "0" ||
+         (RegNum == "18" &&
+          llvm::AArch64::isX18ReservedByDefault(getTriple())) ||
+         getTargetOpts().FeatureMap.lookup(("reserve-x" + RegNum).str());
 }
 
 bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef,
diff --git a/clang/test/Sema/aarch64-fixed-global-register.c b/clang/test/Sema/aarch64-fixed-global-register.c
index 9515f5ec7fbe82..f66c3475dae38f 100644
--- a/clang/test/Sema/aarch64-fixed-global-register.c
+++ b/clang/test/Sema/aarch64-fixed-global-register.c
@@ -1,9 +1,13 @@
 // RUN: %clang_cc1 -triple aarch64-unknown-none-gnu %s -target-feature +reserve-x4 -target-feature +reserve-x15 -verify -verify=no_x18 -fsyntax-only
 // RUN: %clang_cc1 -triple aarch64-unknown-android %s -target-feature +reserve-x4 -target-feature +reserve-x15 -verify -fsyntax-only
 
+register int w0 __asm__ ("w0");
 register long x0 __asm__ ("x0");
 register char i1 __asm__ ("x15"); // expected-error {{size of register 'x15' does not match variable size}}
-register long long l2 __asm__ ("w14"); // expected-error {{size of register 'w14' does not match variable size}}
+register long long l2 __asm__ ("w15"); // expected-error {{size of register 'w15' does not match variable size}}
+register int w3 __asm__ ("w3"); // expected-error {{register 'w3' unsuitable for global register variables on this target}}
 register long x3 __asm__ ("x3"); // expected-error {{register 'x3' unsuitable for global register variables on this target}}
+register int w4 __asm__ ("w4");
 register long x4 __asm__ ("x4");
+register int w18 __asm__ ("w18"); // no_x18-error {{register 'w18' unsuitable for global register variables on this target}}
 register long x18 __asm__ ("x18"); // no_x18-error {{register 'x18' unsuitable for global register variables on this target}}



More information about the cfe-commits mailing list