[llvm] [ARM64EC] Warn on using disallowed registers in assembly src. (PR #93618)

Namish Kukreja via llvm-commits llvm-commits at lists.llvm.org
Wed May 29 15:19:39 PDT 2024


https://github.com/namikukr updated https://github.com/llvm/llvm-project/pull/93618

>From 3c9ea0db8484e8fc2bdf4350ae09b3eb8d95b3a4 Mon Sep 17 00:00:00 2001
From: Namish Kukreja <namikukr at quicinc.com>
Date: Wed, 22 May 2024 15:44:35 -0700
Subject: [PATCH 1/2] [ARM64EC] Warn on using disallowed registers in assembly
 src.

ARM64EC designates a set of disallowed registers, because
a mapping does not exist from them to x64. The MSVC assembler
(armasm64) has a warning for this.

A test is also included as part of the patch.

See the list of disallowed registers below:
https://learn.microsoft.com/en-us/cpp/build/arm64ec-windows-abi-conventions?view=msvc-170#register-mapping
---
 .../AArch64/AsmParser/AArch64AsmParser.cpp    | 27 +++++++
 .../test/MC/AArch64/arm64ec-disallowed-regs.s | 75 +++++++++++++++++++
 2 files changed, 102 insertions(+)
 create mode 100644 llvm/test/MC/AArch64/arm64ec-disallowed-regs.s

diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 13a68b7dcf984..ea329dd71e398 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -294,11 +294,13 @@ class AArch64AsmParser : public MCTargetAsmParser {
 #include "AArch64GenAsmMatcher.inc"
   };
   bool IsILP32;
+  bool IsWindowsArm64EC;
 
   AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
                    const MCInstrInfo &MII, const MCTargetOptions &Options)
     : MCTargetAsmParser(Options, STI, MII) {
     IsILP32 = STI.getTargetTriple().getEnvironment() == Triple::GNUILP32;
+    IsWindowsArm64EC = STI.getTargetTriple().isWindowsArm64EC();
     MCAsmParserExtension::Initialize(Parser);
     MCStreamer &S = getParser().getStreamer();
     if (S.getTargetStreamer() == nullptr)
@@ -5315,6 +5317,31 @@ bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,
     }
   }
 
+  // On ARM64EC, only valid registers may be used. Warn against using
+  // explicitly disallowed registers.
+  if (IsWindowsArm64EC) {
+    for (unsigned i = 0; i < Inst.getNumOperands(); ++i) {
+      if (Inst.getOperand(i).isReg()) {
+        unsigned Reg = Inst.getOperand(i).getReg();
+        // At this point, vector registers are matched to their
+        // appropriately sized alias.
+        if ((Reg == AArch64::W13 || Reg == AArch64::X13) ||
+            (Reg == AArch64::W14 || Reg == AArch64::X14) ||
+            (Reg == AArch64::W23 || Reg == AArch64::X23) ||
+            (Reg == AArch64::W24 || Reg == AArch64::X24) ||
+            (Reg == AArch64::W28 || Reg == AArch64::X28) ||
+            (Reg >= AArch64::Q16 && Reg <= AArch64::Q31) ||
+            (Reg >= AArch64::D16 && Reg <= AArch64::D31) ||
+            (Reg >= AArch64::S16 && Reg <= AArch64::S31) ||
+            (Reg >= AArch64::H16 && Reg <= AArch64::H31) ||
+            (Reg >= AArch64::B16 && Reg <= AArch64::B31)) {
+          Warning(IDLoc, "this instruction uses disallowed registers.");
+          break;
+        }
+      }
+    }
+  }
+
   // Check for indexed addressing modes w/ the base register being the
   // same as a destination/source register or pair load where
   // the Rt == Rt2. All of those are undefined behaviour.
diff --git a/llvm/test/MC/AArch64/arm64ec-disallowed-regs.s b/llvm/test/MC/AArch64/arm64ec-disallowed-regs.s
new file mode 100644
index 0000000000000..8061987a51998
--- /dev/null
+++ b/llvm/test/MC/AArch64/arm64ec-disallowed-regs.s
@@ -0,0 +1,75 @@
+// RUN: llvm-mc -triple arm64ec-pc-windows-msvc < %s 2> %t.log
+// RUN: FileCheck %s --check-prefix=CHECK-ERR < %t.log
+
+
+// ---- disallowed x registers ----
+orr x13, x0, x1             // x13
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orr x14, x2, x3             // x14
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orr x4, x23, x5             // x23
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orr x6, x7, x24             // x24
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orr x28, x8, x9             // x28
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+
+// ---- disallowed w registers ----
+orr w0, w13, w1             // w13
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orr w14, w2, w3             // w14
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orr w4, w23, w5             // w23
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orr w6, w7, w24             // w24
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orr w28, w8, w9             // w28
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+
+// ---- disallowed vector registers ----
+orn v1.8b, v16.8b, v2.8b        // v16
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orn v2.16b, v17.16b, v3.16b     // v17
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orn v3.8b, v18.8b, v4.8b        // v18
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orn v4.16b, v19.16b, v5.16b     // v19
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orn v5.8b, v20.8b, v6.8b        // v20
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orn v21.8b, v6.8b, v7.8b        // v21
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orn v7.16b, v8.16b, v22.16b     // v22
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orn v23.8b, v8.8b, v9.8b        // v23
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orn v9.16b, v24.16b, v10.16b    // v24
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orn v10.8b, v25.8b, v11.8b      // v25
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orn v11.8b, v12.8b, v26.8b      // v26
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orn v12.8b, v27.8b, v13.8b      // v27
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orn v13.16b, v28.16b, v14.16b   // v28
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orn v14.8b, v29.8b, v15.8b      // v29
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orn v15.8b, v30.8b, v15.8b      // v30
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+orn v1.16b, v31.16b, v1.16b     // v31
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+
+// ---- random tests on h, b, d, s registers ----
+orn.16b v1, v16, v2
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+mov.4h v17, v8
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+fmul.2s v2, v18, v11
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+clz.8h v3, v19
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+add.4s v0, v20, v1
+// CHECK-ERR: warning: this instruction uses disallowed registers.
+add.2d v0, v20, v1
+// CHECK-ERR: warning: this instruction uses disallowed registers.
\ No newline at end of file

>From e4a34c0c2e5b296971cba1b1071a4e442ac1e3f1 Mon Sep 17 00:00:00 2001
From: Namish Kukreja <namikukr at quicinc.com>
Date: Wed, 29 May 2024 15:14:13 -0700
Subject: [PATCH 2/2] checked for no warnings on AArch64, more detailed
 warnings

---
 .../AArch64/AsmParser/AArch64AsmParser.cpp    | 130 +++++++++++++++++-
 .../test/MC/AArch64/arm64ec-disallowed-regs.s | 104 +++++++++-----
 2 files changed, 199 insertions(+), 35 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index ea329dd71e398..cda4824e012be 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -5244,6 +5244,132 @@ static inline bool isMatchingOrAlias(unsigned ZReg, unsigned Reg) {
          (ZReg == ((Reg - AArch64::Z0) + AArch64::Z0));
 }
 
+static std::string getArm64ECDisallowedRegName(unsigned Reg) {
+  switch (Reg) {
+  // Disallowed W registers
+  case AArch64::W13:
+    return "w13";
+  case AArch64::W14:
+    return "w14";
+  case AArch64::W23:
+    return "w23";
+  case AArch64::W24:
+    return "w24";
+  case AArch64::W28:
+    return "w28";
+  // Disallowed X registers
+  case AArch64::X13:
+    return "x13";
+  case AArch64::X14:
+    return "x14";
+  case AArch64::X23:
+    return "x23";
+  case AArch64::X24:
+    return "x24";
+  case AArch64::X28:
+    return "x28";
+  // Disallowed vector registers (all forms)
+  case AArch64::Q16:
+  case AArch64::D16:
+  case AArch64::S16:
+  case AArch64::H16:
+  case AArch64::B16:
+    return "v16";
+  case AArch64::Q17:
+  case AArch64::D17:
+  case AArch64::S17:
+  case AArch64::H17:
+  case AArch64::B17:
+    return "v17";
+  case AArch64::Q18:
+  case AArch64::D18:
+  case AArch64::S18:
+  case AArch64::H18:
+  case AArch64::B18:
+    return "v18";
+  case AArch64::Q19:
+  case AArch64::D19:
+  case AArch64::S19:
+  case AArch64::H19:
+  case AArch64::B19:
+    return "v19";
+  case AArch64::Q20:
+  case AArch64::D20:
+  case AArch64::S20:
+  case AArch64::H20:
+  case AArch64::B20:
+    return "v20";
+  case AArch64::Q21:
+  case AArch64::D21:
+  case AArch64::S21:
+  case AArch64::H21:
+  case AArch64::B21:
+    return "v21";
+  case AArch64::Q22:
+  case AArch64::D22:
+  case AArch64::S22:
+  case AArch64::H22:
+  case AArch64::B22:
+    return "v22";
+  case AArch64::Q23:
+  case AArch64::D23:
+  case AArch64::S23:
+  case AArch64::H23:
+  case AArch64::B23:
+    return "v23";
+  case AArch64::Q24:
+  case AArch64::D24:
+  case AArch64::S24:
+  case AArch64::H24:
+  case AArch64::B24:
+    return "v24";
+  case AArch64::Q25:
+  case AArch64::D25:
+  case AArch64::S25:
+  case AArch64::H25:
+  case AArch64::B25:
+    return "v25";
+  case AArch64::Q26:
+  case AArch64::D26:
+  case AArch64::S26:
+  case AArch64::H26:
+  case AArch64::B26:
+    return "v26";
+  case AArch64::Q27:
+  case AArch64::D27:
+  case AArch64::S27:
+  case AArch64::H27:
+  case AArch64::B27:
+    return "v27";
+  case AArch64::Q28:
+  case AArch64::D28:
+  case AArch64::S28:
+  case AArch64::H28:
+  case AArch64::B28:
+    return "v28";
+  case AArch64::Q29:
+  case AArch64::D29:
+  case AArch64::S29:
+  case AArch64::H29:
+  case AArch64::B29:
+    return "v29";
+  case AArch64::Q30:
+  case AArch64::D30:
+  case AArch64::S30:
+  case AArch64::H30:
+  case AArch64::B30:
+    return "v30";
+  case AArch64::Q31:
+  case AArch64::D31:
+  case AArch64::S31:
+  case AArch64::H31:
+  case AArch64::B31:
+    return "v31";
+  default:
+    llvm_unreachable("Unknown disallowed reg?");
+  }
+}
+
 // FIXME: This entire function is a giant hack to provide us with decent
 // operand range validation/diagnostics until TableGen/MC can be extended
 // to support autogeneration of this kind of validation.
@@ -5335,8 +5461,8 @@ bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,
             (Reg >= AArch64::S16 && Reg <= AArch64::S31) ||
             (Reg >= AArch64::H16 && Reg <= AArch64::H31) ||
             (Reg >= AArch64::B16 && Reg <= AArch64::B31)) {
-          Warning(IDLoc, "this instruction uses disallowed registers.");
-          break;
+          Warning(IDLoc, "register " + getArm64ECDisallowedRegName(Reg) +
+                             " is disallowed on ARM64EC.");
         }
       }
     }
diff --git a/llvm/test/MC/AArch64/arm64ec-disallowed-regs.s b/llvm/test/MC/AArch64/arm64ec-disallowed-regs.s
index 8061987a51998..d466251b2b721 100644
--- a/llvm/test/MC/AArch64/arm64ec-disallowed-regs.s
+++ b/llvm/test/MC/AArch64/arm64ec-disallowed-regs.s
@@ -1,75 +1,113 @@
 // RUN: llvm-mc -triple arm64ec-pc-windows-msvc < %s 2> %t.log
 // RUN: FileCheck %s --check-prefix=CHECK-ERR < %t.log
-
+// RUN: llvm-mc -triple aarch64-windows-msvc < %s > %t.log 2>&1
+// RUN: FileCheck %s --check-prefix=CHECK-NOEC --implicit-check-not=warning: < %t.log
 
 // ---- disallowed x registers ----
 orr x13, x0, x1             // x13
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register x13 is disallowed on ARM64EC.
 orr x14, x2, x3             // x14
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register x14 is disallowed on ARM64EC.
 orr x4, x23, x5             // x23
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register x23 is disallowed on ARM64EC.
 orr x6, x7, x24             // x24
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register x24 is disallowed on ARM64EC.
 orr x28, x8, x9             // x28
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register x28 is disallowed on ARM64EC.
 
 // ---- disallowed w registers ----
 orr w0, w13, w1             // w13
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register w13 is disallowed on ARM64EC.
 orr w14, w2, w3             // w14
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register w14 is disallowed on ARM64EC.
 orr w4, w23, w5             // w23
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register w23 is disallowed on ARM64EC.
 orr w6, w7, w24             // w24
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register w24 is disallowed on ARM64EC.
 orr w28, w8, w9             // w28
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register w28 is disallowed on ARM64EC.
 
 // ---- disallowed vector registers ----
 orn v1.8b, v16.8b, v2.8b        // v16
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register v16 is disallowed on ARM64EC.
 orn v2.16b, v17.16b, v3.16b     // v17
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register v17 is disallowed on ARM64EC.
 orn v3.8b, v18.8b, v4.8b        // v18
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register v18 is disallowed on ARM64EC.
 orn v4.16b, v19.16b, v5.16b     // v19
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register v19 is disallowed on ARM64EC.
 orn v5.8b, v20.8b, v6.8b        // v20
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register v20 is disallowed on ARM64EC.
 orn v21.8b, v6.8b, v7.8b        // v21
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register v21 is disallowed on ARM64EC.
 orn v7.16b, v8.16b, v22.16b     // v22
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register v22 is disallowed on ARM64EC.
 orn v23.8b, v8.8b, v9.8b        // v23
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register v23 is disallowed on ARM64EC.
 orn v9.16b, v24.16b, v10.16b    // v24
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register v24 is disallowed on ARM64EC.
 orn v10.8b, v25.8b, v11.8b      // v25
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register v25 is disallowed on ARM64EC.
 orn v11.8b, v12.8b, v26.8b      // v26
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register v26 is disallowed on ARM64EC.
 orn v12.8b, v27.8b, v13.8b      // v27
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register v27 is disallowed on ARM64EC.
 orn v13.16b, v28.16b, v14.16b   // v28
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register v28 is disallowed on ARM64EC.
 orn v14.8b, v29.8b, v15.8b      // v29
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register v29 is disallowed on ARM64EC.
 orn v15.8b, v30.8b, v15.8b      // v30
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register v30 is disallowed on ARM64EC.
 orn v1.16b, v31.16b, v1.16b     // v31
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register v31 is disallowed on ARM64EC.
 
 // ---- random tests on h, b, d, s registers ----
 orn.16b v1, v16, v2
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register v16 is disallowed on ARM64EC.
 mov.4h v17, v8
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register v17 is disallowed on ARM64EC.
 fmul.2s v2, v18, v11
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register v18 is disallowed on ARM64EC.
 clz.8h v3, v19
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register v19 is disallowed on ARM64EC.
 add.4s v0, v20, v1
-// CHECK-ERR: warning: this instruction uses disallowed registers.
+// CHECK-ERR: warning: register v20 is disallowed on ARM64EC.
 add.2d v0, v20, v1
-// CHECK-ERR: warning: this instruction uses disallowed registers.
\ No newline at end of file
+// CHECK-ERR: warning: register v20 is disallowed on ARM64EC.
+
+// CHECK-NOEC: .text
+// CHECK-NOEC: orr x13, x0, x1
+// CHECK-NOEC: orr x14, x2, x3
+// CHECK-NOEC: orr x4, x23, x5
+// CHECK-NOEC: orr x6, x7, x24
+// CHECK-NOEC: orr x28, x8, x9 
+
+// CHECK-NOEC: orr w0, w13, w1
+// CHECK-NOEC: orr w14, w2, w3
+// CHECK-NOEC: orr w4, w23, w5
+// CHECK-NOEC: orr w6, w7, w24
+// CHECK-NOEC: orr w28, w8, w9
+
+// CHECK-NOEC: orn v1.8b, v16.8b, v2.8b
+// CHECK-NOEC: orn v2.16b, v17.16b, v3.16b
+// CHECK-NOEC: orn v3.8b, v18.8b, v4.8b
+// CHECK-NOEC: orn v4.16b, v19.16b, v5.16b
+// CHECK-NOEC: orn v5.8b, v20.8b, v6.8b
+// CHECK-NOEC: orn v21.8b, v6.8b, v7.8b
+// CHECK-NOEC: orn v7.16b, v8.16b, v22.16b
+// CHECK-NOEC: orn v23.8b, v8.8b, v9.8b
+// CHECK-NOEC: orn v9.16b, v24.16b, v10.16b
+// CHECK-NOEC: orn v10.8b, v25.8b, v11.8b
+// CHECK-NOEC: orn v11.8b, v12.8b, v26.8b
+// CHECK-NOEC: orn v12.8b, v27.8b, v13.8b
+// CHECK-NOEC: orn v13.16b, v28.16b, v14.16b
+// CHECK-NOEC: orn v14.8b, v29.8b, v15.8b
+// CHECK-NOEC: orn v15.8b, v30.8b, v15.8b
+// CHECK-NOEC: orn v1.16b, v31.16b, v1.16b
+
+// CHECK-NOEC: orn v1.16b, v16.16b, v2.16b
+// CHECK-NOEC: mov v17.8b, v8.8b
+// CHECK-NOEC: fmul v2.2s, v18.2s, v11.2s
+// CHECK-NOEC: clz v3.8h, v19.8h
+// CHECK-NOEC: add v0.4s, v20.4s, v1.4s
+// CHECK-NOEC: add v0.2d, v20.2d, v1.2d



More information about the llvm-commits mailing list