lenary edited the summary of this revision.
lenary updated this revision to Diff 484281.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D140222/new/

https://reviews.llvm.org/D140222

Files:
  clang/include/clang/Basic/BuiltinsAArch64.def
  clang/lib/Headers/arm_acle.h
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/aarch64-sysregs-target.c
  clang/test/Sema/aarch64-special-register.c

Index: clang/test/Sema/aarch64-special-register.c
===================================================================
--- clang/test/Sema/aarch64-special-register.c
+++ clang/test/Sema/aarch64-special-register.c
@@ -16,6 +16,10 @@
   __builtin_arm_wsr64("sysreg", v);
 }
 
+void wsr128_1(__uint128_t v) {
+  __builtin_arm_wsr128("sysreg", v);
+}
+
 unsigned rsr_1(void) {
   return __builtin_arm_rsr("sysreg");
 }
@@ -28,6 +32,10 @@
   return __builtin_arm_rsr64("sysreg");
 }
 
+__uint128_t rsr128_1(void) {
+  return __builtin_arm_rsr128("sysreg");
+}
+
 void wsr_2(unsigned v) {
   __builtin_arm_wsr("0:1:2:3:4", v);
 }
@@ -52,6 +60,10 @@
   return __builtin_arm_rsr64("0:1:15:15:4");
 }
 
+__uint128_t rsr128_2(void) {
+  return __builtin_arm_rsr128("0:1:15:15:4");
+}
+
 void wsr_3(unsigned v) {
   __builtin_arm_wsr("0:1:2", v); //expected-error {{invalid special register for builtin}}
 }
@@ -64,6 +76,10 @@
   __builtin_arm_wsr64("0:1:2", v); //expected-error {{invalid special register for builtin}}
 }
 
+void wsr128_3(__uint128_t v) {
+  __builtin_arm_wsr128("0:1:2", v); //expected-error {{invalid special register for builtin}}
+}
+
 unsigned rsr_3(void) {
   return __builtin_arm_rsr("0:1:2"); //expected-error {{invalid special register for builtin}}
 }
@@ -99,3 +115,101 @@
 unsigned long rsr64_6(void) {
   return __builtin_arm_rsr64("0:1:16:16:2"); //expected-error {{invalid special register for builtin}}
 }
+
+__uint128_t rsr128_3(void) {
+  return __builtin_arm_rsr128("0:1:2"); //expected-error {{invalid special register for builtin}}
+}
+
+__uint128_t rsr128_4(void) {
+  return __builtin_arm_rsr128("0:1:2:3:8"); //expected-error {{invalid special register for builtin}}
+}
+
+__uint128_t rsr128_5(void) {
+  return __builtin_arm_rsr128("0:8:2:3:4"); //expected-error {{invalid special register for builtin}}
+}
+
+__uint128_t rsr128_6(void) {
+  return __builtin_arm_rsr128("0:1:16:16:2"); //expected-error {{invalid special register for builtin}}
+}
+
+void wsr_4(void) {
+  __builtin_arm_wsr("spsel", 15);
+  __builtin_arm_wsr("daifclr", 15);
+  __builtin_arm_wsr("daifset", 15);
+  __builtin_arm_wsr("pan", 15);
+  __builtin_arm_wsr("uao", 15);
+  __builtin_arm_wsr("dit", 15);
+  __builtin_arm_wsr("ssbs", 15);
+  __builtin_arm_wsr("tco", 15);
+
+  __builtin_arm_wsr("allint", 1);
+  __builtin_arm_wsr("pm", 1);
+}
+
+void wsr64_4(void) {
+  __builtin_arm_wsr("spsel", 15);
+  __builtin_arm_wsr("daifclr", 15);
+  __builtin_arm_wsr("daifset", 15);
+  __builtin_arm_wsr("pan", 15);
+  __builtin_arm_wsr("uao", 15);
+  __builtin_arm_wsr("dit", 15);
+  __builtin_arm_wsr("ssbs", 15);
+  __builtin_arm_wsr("tco", 15);
+
+  __builtin_arm_wsr("allint", 1);
+  __builtin_arm_wsr("pm", 1);
+}
+
+void wsr_5(unsigned v) {
+  __builtin_arm_wsr("spsel", v); // expected-error {{must be a constant integer}}
+  __builtin_arm_wsr("daifclr", v); // expected-error {{must be a constant integer}}
+  __builtin_arm_wsr("daifset", v); // expected-error {{must be a constant integer}}
+  __builtin_arm_wsr("pan", v); // expected-error {{must be a constant integer}}
+  __builtin_arm_wsr("uao", v); // expected-error {{must be a constant integer}}
+  __builtin_arm_wsr("dit", v); // expected-error {{must be a constant integer}}
+  __builtin_arm_wsr("ssbs", v); // expected-error {{must be a constant integer}}
+  __builtin_arm_wsr("tco", v); // expected-error {{must be a constant integer}}
+  __builtin_arm_wsr("allint", v); // expected-error {{must be a constant integer}}
+  __builtin_arm_wsr("pm", v); // expected-error {{must be a constant integer}}
+}
+
+void wsr64_5(unsigned long v) {
+  __builtin_arm_wsr64("spsel", v); // expected-error {{must be a constant integer}}
+  __builtin_arm_wsr64("daifclr", v); // expected-error {{must be a constant integer}}
+  __builtin_arm_wsr64("daifset", v); // expected-error {{must be a constant integer}}
+  __builtin_arm_wsr64("pan", v); // expected-error {{must be a constant integer}}
+  __builtin_arm_wsr64("uao", v); // expected-error {{must be a constant integer}}
+  __builtin_arm_wsr64("dit", v); // expected-error {{must be a constant integer}}
+  __builtin_arm_wsr64("ssbs", v); // expected-error {{must be a constant integer}}
+  __builtin_arm_wsr64("tco", v); // expected-error {{must be a constant integer}}
+  __builtin_arm_wsr64("allint", v); // expected-error {{must be a constant integer}}
+  __builtin_arm_wsr64("pm", v); // expected-error {{must be a constant integer}}
+}
+
+void wsr_6(void) {
+  __builtin_arm_wsr("spsel", 16); // expected-error {{outside the valid range}}
+  __builtin_arm_wsr("daifclr", 16); // expected-error {{outside the valid range}}
+  __builtin_arm_wsr("daifset", 16); // expected-error {{outside the valid range}}
+  __builtin_arm_wsr("pan", 16); // expected-error {{outside the valid range}}
+  __builtin_arm_wsr("uao", 16); // expected-error {{outside the valid range}}
+  __builtin_arm_wsr("dit", 16); // expected-error {{outside the valid range}}
+  __builtin_arm_wsr("ssbs", 16); // expected-error {{outside the valid range}}
+  __builtin_arm_wsr("tco", 16); // expected-error {{outside the valid range}}
+
+  __builtin_arm_wsr("allint", 2); // expected-error {{outside the valid range}}
+  __builtin_arm_wsr("pm", 2); // expected-error {{outside the valid range}}
+}
+
+void wsr64_6(void) {
+  __builtin_arm_wsr64("spsel", 16); // expected-error {{outside the valid range}}
+  __builtin_arm_wsr64("daifclr", 16); // expected-error {{outside the valid range}}
+  __builtin_arm_wsr64("daifset", 16); // expected-error {{outside the valid range}}
+  __builtin_arm_wsr64("pan", 16); // expected-error {{outside the valid range}}
+  __builtin_arm_wsr64("uao", 16); // expected-error {{outside the valid range}}
+  __builtin_arm_wsr64("dit", 16); // expected-error {{outside the valid range}}
+  __builtin_arm_wsr64("ssbs", 16); // expected-error {{outside the valid range}}
+  __builtin_arm_wsr64("tco", 16); // expected-error {{outside the valid range}}
+
+  __builtin_arm_wsr64("allint", 2); // expected-error {{outside the valid range}}
+  __builtin_arm_wsr64("pm", 2); // expected-error {{outside the valid range}}
+}
Index: clang/test/CodeGen/aarch64-sysregs-target.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/aarch64-sysregs-target.c
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +v8a -fsyntax-only -verify -emit-llvm -o - %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +d128 -fsyntax-only -verify=d128 -emit-llvm -o - %s
+
+// REQUIRES: aarch64-registered-target
+
+// Test that functions with the correct target attributes can use the correct
+// system-register intriniscs.
+
+// All the calls below are valid if you have -target-feature +d128
+// d128-no-diagnostics
+
+#include <arm_acle.h>
+
+void anytarget(void) {
+  unsigned x = __arm_rsr("1:2:3:4:5");
+  __arm_wsr("1:2:3:4:5", x);
+  unsigned long y = __arm_rsr64("1:2:3:4:5");
+  __arm_wsr64("1:2:3:4:5", y);
+  void *p = __arm_rsrp("1:2:3:4:5");
+  __arm_wsrp("1:2:3:4:5", p);
+}
+
+__attribute__((target("d128")))
+void d128target(void) {
+  __uint128_t x = __arm_rsr128("1:2:3:4:5");
+  __arm_wsr128("1:2:3:4:5", x);
+}
+
+void notd128target(void) {
+  __uint128_t x = __arm_rsr128("1:2:3:4:5"); // expected-error {{needs target feature d128}}
+  __arm_wsr128("1:2:3:4:5", x); // expected-error {{needs target feature d128}}
+}
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -3232,7 +3232,9 @@
   }
 
   if (BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
-      BuiltinID == AArch64::BI__builtin_arm_wsr64)
+      BuiltinID == AArch64::BI__builtin_arm_wsr64 ||
+      BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
+      BuiltinID == AArch64::BI__builtin_arm_wsr128)
     return SemaBuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
 
   // Memory Tagging Extensions (MTE) Intrinsics
@@ -8224,6 +8226,8 @@
                       BuiltinID == ARM::BI__builtin_arm_wsrp;
   bool IsAArch64Builtin = BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
                           BuiltinID == AArch64::BI__builtin_arm_wsr64 ||
+                          BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
+                          BuiltinID == AArch64::BI__builtin_arm_wsr128 ||
                           BuiltinID == AArch64::BI__builtin_arm_rsr ||
                           BuiltinID == AArch64::BI__builtin_arm_rsrp ||
                           BuiltinID == AArch64::BI__builtin_arm_wsr ||
@@ -8291,21 +8295,51 @@
       return Diag(TheCall->getBeginLoc(), diag::err_arm_invalid_specialreg)
              << Arg->getSourceRange();
   } else if (IsAArch64Builtin && Fields.size() == 1) {
-    // If the register name is one of those that appear in the condition below
-    // and the special register builtin being used is one of the write builtins,
-    // then we require that the argument provided for writing to the register
-    // is an integer constant expression. This is because it will be lowered to
-    // an MSR (immediate) instruction, so we need to know the immediate at
-    // compile time.
+    // This code validates writes to PSTATE registers.
+
+    // Not a write.
     if (TheCall->getNumArgs() != 2)
       return false;
 
-    std::string RegLower = Reg.lower();
-    if (RegLower != "spsel" && RegLower != "daifset" && RegLower != "daifclr" &&
-        RegLower != "pan" && RegLower != "uao")
+    // The 128-bit system register accesses do not touch PSTATE.
+    if (BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
+        BuiltinID == AArch64::BI__builtin_arm_wsr128)
       return false;
 
-    return SemaBuiltinConstantArgRange(TheCall, 1, 0, 15);
+    // These are the named PSTATE accesses using "MSR (immediate)" instructions,
+    // along with the upper limit on the immediates allowed.
+    auto MaxLimit = llvm::StringSwitch<std::optional<unsigned>>(Reg)
+      .CaseLower("spsel", 15)
+      .CaseLower("daifclr", 15)
+      .CaseLower("daifset", 15)
+      .CaseLower("pan", 15)
+      .CaseLower("uao", 15)
+      .CaseLower("dit", 15)
+      .CaseLower("ssbs", 15)
+      .CaseLower("tco", 15)
+      .CaseLower("allint", 1)
+      .CaseLower("pm", 1)
+      .Default(std::nullopt);
+
+    // If this is not a named PSTATE, just continue without validating, as this
+    // will be lowered to an "MSR (register)" instruction directly
+    if (!MaxLimit)
+      return false;
+
+    // Here we only allow constants in the range for that pstate, as required by
+    // the ACLE.
+    //
+    // While clang also accepts the names of system registers in its ACLE
+    // intrinsics, we prevent this with the PSTATE names used in MSR (immediate)
+    // as the value written via a register is different to the value used as an
+    // immediate to have the same effect. e.g., for the instruction `msr tco,
+    // x0`, it is bit 25 of register x0 that is written into PSTATE.TCO, but
+    // with `msr tco, #imm`, it is bit 0 of xN that is written into PSTATE.TCO.
+    //
+    // If a programmer wants to codegen the MSR (register) form of `msr tco,
+    // xN`, they can still do so by specifying the register using five
+    // colon-separated numbers in a string.
+    return SemaBuiltinConstantArgRange(TheCall, 1, 0, *MaxLimit);
   }
 
   return false;
Index: clang/lib/Headers/arm_acle.h
===================================================================
--- clang/lib/Headers/arm_acle.h
+++ clang/lib/Headers/arm_acle.h
@@ -712,17 +712,13 @@
 /* 10.1 Special register intrinsics */
 #define __arm_rsr(sysreg) __builtin_arm_rsr(sysreg)
 #define __arm_rsr64(sysreg) __builtin_arm_rsr64(sysreg)
-#if __ARM_FEATURE_SYSREG128
 #define __arm_rsr128(sysreg) __builtin_arm_rsr128(sysreg)
-#endif
 #define __arm_rsrp(sysreg) __builtin_arm_rsrp(sysreg)
 #define __arm_rsrf(sysreg) __builtin_bit_cast(float, __arm_rsr(sysreg))
 #define __arm_rsrf64(sysreg) __builtin_bit_cast(double, __arm_rsr64(sysreg))
 #define __arm_wsr(sysreg, v) __builtin_arm_wsr(sysreg, v)
 #define __arm_wsr64(sysreg, v) __builtin_arm_wsr64(sysreg, v)
-#if __ARM_FEATURE_SYSREG128
 #define __arm_wsr128(sysreg, v) __builtin_arm_wsr128(sysreg, v)
-#endif
 #define __arm_wsrp(sysreg, v) __builtin_arm_wsrp(sysreg, v)
 #define __arm_wsrf(sysreg, v) __arm_wsr(sysreg, __builtin_bit_cast(uint32_t, v))
 #define __arm_wsrf64(sysreg, v) __arm_wsr64(sysreg, __builtin_bit_cast(uint64_t, v))
Index: clang/include/clang/Basic/BuiltinsAArch64.def
===================================================================
--- clang/include/clang/Basic/BuiltinsAArch64.def
+++ clang/include/clang/Basic/BuiltinsAArch64.def
@@ -82,11 +82,11 @@
 // System Registers
 BUILTIN(__builtin_arm_rsr, "UicC*", "nc")
 BUILTIN(__builtin_arm_rsr64, "WUicC*", "nc")
-BUILTIN(__builtin_arm_rsr128, "LLLUicC*", "nc")
+TARGET_BUILTIN(__builtin_arm_rsr128, "LLLUicC*", "nc", "d128")
 BUILTIN(__builtin_arm_rsrp, "v*cC*", "nc")
 BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc")
 BUILTIN(__builtin_arm_wsr64, "vcC*WUi", "nc")
-BUILTIN(__builtin_arm_wsr128, "vcC*LLLUi", "nc")
+TARGET_BUILTIN(__builtin_arm_wsr128, "vcC*LLLUi", "nc", "d128")
 BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
 
 // MSVC
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to