[clang] __sys builtin support (PR #145079)

2025-06-20 Thread Adam Glass via cfe-commits

https://github.com/AdamGlass created 
https://github.com/llvm/llvm-project/pull/145079

Adds support for __sys Clang builtin for Aarch64

__sys is a long existing MSVC intrinsic used to manage caches, tlbs, etc by 
writing to system registers:
• It takes a macro-generated constant and uses it to form the AArch64 SYS 
instruction which is MSR with op0=1.  The macro drops op0 and expects the 
implementation to hardcode it to 1 in the encoding.
• Volume use is in systems code (kernels, hypervisors, boot environments, 
firmware)
• Has an unused return value due to MSVC cut/paste error

Implementation:
• Clang builtin, sharing code with Read/WriteStatusReg
• Hardcodes the op0=1
• Explicitly returns 0
• Code-format change from clang-format
• Unittests included
• Not limited to MSVC-environment as its generally useful and neutral

Adam Glass
adamgl...@spottedfoobar.com 
adamgl...@microsoft.com  
@dpaoliello


>From cd5afb986fbbc6ceb68e2b4c6afc48bd1c8bf02e Mon Sep 17 00:00:00 2001
From: Adam Glass 
Date: Fri, 13 Jun 2025 17:59:20 -0700
Subject: [PATCH] __sys builtin support

---
 clang/include/clang/Basic/BuiltinsAArch64.def |  1 +
 clang/lib/CodeGen/TargetBuiltins/ARM.cpp  | 25 ---
 clang/lib/Headers/intrin.h|  1 +
 clang/lib/Sema/SemaARM.cpp|  2 +-
 clang/test/CodeGen/arm64-microsoft-sys.c  | 68 +++
 clang/test/Sema/builtins-microsoft-arm64.c|  9 +++
 6 files changed, 96 insertions(+), 10 deletions(-)
 create mode 100644 clang/test/CodeGen/arm64-microsoft-sys.c

diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def 
b/clang/include/clang/Basic/BuiltinsAArch64.def
index 8867a9fe09fb9..3bb329d210c07 100644
--- a/clang/include/clang/Basic/BuiltinsAArch64.def
+++ b/clang/include/clang/Basic/BuiltinsAArch64.def
@@ -267,6 +267,7 @@ TARGET_HEADER_BUILTIN(_ReadWriteBarrier, "v", "nh", 
INTRIN_H, ALL_MS_LANGUAGES,
 TARGET_HEADER_BUILTIN(__getReg, "ULLii", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
 TARGET_HEADER_BUILTIN(_ReadStatusReg,  "LLii",  "nh", INTRIN_H, 
ALL_MS_LANGUAGES, "")
 TARGET_HEADER_BUILTIN(_WriteStatusReg, "viLLi", "nh", INTRIN_H, 
ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__sys, "UiiLLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
 TARGET_HEADER_BUILTIN(_AddressOfReturnAddress, "v*", "nh", INTRIN_H, 
ALL_MS_LANGUAGES, "")
 
 TARGET_HEADER_BUILTIN(__mulh,  "SLLiSLLiSLLi", "nh", INTRIN_H, 
ALL_MS_LANGUAGES, "")
diff --git a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp 
b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
index dab311903f6dd..d1c62c6b754a5 100644
--- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
@@ -5471,19 +5471,21 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned 
BuiltinID,
   }
 
   if (BuiltinID == clang::AArch64::BI_ReadStatusReg ||
-  BuiltinID == clang::AArch64::BI_WriteStatusReg) {
+  BuiltinID == clang::AArch64::BI_WriteStatusReg ||
+  BuiltinID == clang::AArch64::BI__sys) {
 LLVMContext &Context = CGM.getLLVMContext();
 
 unsigned SysReg =
   E->getArg(0)->EvaluateKnownConstInt(getContext()).getZExtValue();
 
 std::string SysRegStr;
-llvm::raw_string_ostream(SysRegStr) <<
-   ((1 << 1) | ((SysReg >> 14) & 1))  << ":" <<
-   ((SysReg >> 11) & 7)   << ":" <<
-   ((SysReg >> 7)  & 15)  << ":" <<
-   ((SysReg >> 3)  & 15)  << ":" <<
-   ( SysReg& 7);
+unsigned SysRegOp0 = (BuiltinID != clang::AArch64::BI__sys)
+ ? ((1 << 1) | ((SysReg >> 14) & 1))
+ : 1;
+llvm::raw_string_ostream(SysRegStr)
+<< SysRegOp0 << ":" << ((SysReg >> 11) & 7) << ":"
+<< ((SysReg >> 7) & 15) << ":" << ((SysReg >> 3) & 15) << ":"
+<< (SysReg & 7);
 
 llvm::Metadata *Ops[] = { llvm::MDString::get(Context, SysRegStr) };
 llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
@@ -5500,8 +5502,13 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned 
BuiltinID,
 
 llvm::Function *F = CGM.getIntrinsic(Intrinsic::write_register, Types);
 llvm::Value *ArgValue = EmitScalarExpr(E->getArg(1));
-
-return Builder.CreateCall(F, { Metadata, ArgValue });
+llvm::Value *Result = Builder.CreateCall(F, {Metadata, ArgValue});
+if (BuiltinID == clang::AArch64::BI__sys) {
+  // Return 0 for convenience, even though MSVC returns some other 
undefined
+  // value.
+  Result = ConstantInt::get(Builder.getInt32Ty(), 0);
+}
+return Result;
   }
 
   if (BuiltinID == clang::AArch64::BI_AddressOfReturnAddress) {
diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h
index 3dd1eb45817d4..0ab69fd403d2d 100644
--- a/clang/lib/Headers/intrin.h
+++ b/clang/lib/Headers/intrin.h
@@ -374,6 +374,7 @@ long _InterlockedAdd(long volatile *Addend, long Value);
 __int64 _InterlockedAdd64(__int64 

[clang] __sys builtin support (PR #145079)

2025-06-20 Thread Adam Glass via cfe-commits

AdamGlass wrote:

pushed updated version with ternary operation test swapped.  resolved that 
discussion -- is that my role or daniel's?

https://github.com/llvm/llvm-project/pull/145079
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] __sys builtin support (PR #145079)

2025-06-20 Thread Adam Glass via cfe-commits

https://github.com/AdamGlass updated 
https://github.com/llvm/llvm-project/pull/145079

>From cd5afb986fbbc6ceb68e2b4c6afc48bd1c8bf02e Mon Sep 17 00:00:00 2001
From: Adam Glass 
Date: Fri, 13 Jun 2025 17:59:20 -0700
Subject: [PATCH 1/2] __sys builtin support

---
 clang/include/clang/Basic/BuiltinsAArch64.def |  1 +
 clang/lib/CodeGen/TargetBuiltins/ARM.cpp  | 25 ---
 clang/lib/Headers/intrin.h|  1 +
 clang/lib/Sema/SemaARM.cpp|  2 +-
 clang/test/CodeGen/arm64-microsoft-sys.c  | 68 +++
 clang/test/Sema/builtins-microsoft-arm64.c|  9 +++
 6 files changed, 96 insertions(+), 10 deletions(-)
 create mode 100644 clang/test/CodeGen/arm64-microsoft-sys.c

diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def 
b/clang/include/clang/Basic/BuiltinsAArch64.def
index 8867a9fe09fb9..3bb329d210c07 100644
--- a/clang/include/clang/Basic/BuiltinsAArch64.def
+++ b/clang/include/clang/Basic/BuiltinsAArch64.def
@@ -267,6 +267,7 @@ TARGET_HEADER_BUILTIN(_ReadWriteBarrier, "v", "nh", 
INTRIN_H, ALL_MS_LANGUAGES,
 TARGET_HEADER_BUILTIN(__getReg, "ULLii", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
 TARGET_HEADER_BUILTIN(_ReadStatusReg,  "LLii",  "nh", INTRIN_H, 
ALL_MS_LANGUAGES, "")
 TARGET_HEADER_BUILTIN(_WriteStatusReg, "viLLi", "nh", INTRIN_H, 
ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__sys, "UiiLLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
 TARGET_HEADER_BUILTIN(_AddressOfReturnAddress, "v*", "nh", INTRIN_H, 
ALL_MS_LANGUAGES, "")
 
 TARGET_HEADER_BUILTIN(__mulh,  "SLLiSLLiSLLi", "nh", INTRIN_H, 
ALL_MS_LANGUAGES, "")
diff --git a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp 
b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
index dab311903f6dd..d1c62c6b754a5 100644
--- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
@@ -5471,19 +5471,21 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned 
BuiltinID,
   }
 
   if (BuiltinID == clang::AArch64::BI_ReadStatusReg ||
-  BuiltinID == clang::AArch64::BI_WriteStatusReg) {
+  BuiltinID == clang::AArch64::BI_WriteStatusReg ||
+  BuiltinID == clang::AArch64::BI__sys) {
 LLVMContext &Context = CGM.getLLVMContext();
 
 unsigned SysReg =
   E->getArg(0)->EvaluateKnownConstInt(getContext()).getZExtValue();
 
 std::string SysRegStr;
-llvm::raw_string_ostream(SysRegStr) <<
-   ((1 << 1) | ((SysReg >> 14) & 1))  << ":" <<
-   ((SysReg >> 11) & 7)   << ":" <<
-   ((SysReg >> 7)  & 15)  << ":" <<
-   ((SysReg >> 3)  & 15)  << ":" <<
-   ( SysReg& 7);
+unsigned SysRegOp0 = (BuiltinID != clang::AArch64::BI__sys)
+ ? ((1 << 1) | ((SysReg >> 14) & 1))
+ : 1;
+llvm::raw_string_ostream(SysRegStr)
+<< SysRegOp0 << ":" << ((SysReg >> 11) & 7) << ":"
+<< ((SysReg >> 7) & 15) << ":" << ((SysReg >> 3) & 15) << ":"
+<< (SysReg & 7);
 
 llvm::Metadata *Ops[] = { llvm::MDString::get(Context, SysRegStr) };
 llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
@@ -5500,8 +5502,13 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned 
BuiltinID,
 
 llvm::Function *F = CGM.getIntrinsic(Intrinsic::write_register, Types);
 llvm::Value *ArgValue = EmitScalarExpr(E->getArg(1));
-
-return Builder.CreateCall(F, { Metadata, ArgValue });
+llvm::Value *Result = Builder.CreateCall(F, {Metadata, ArgValue});
+if (BuiltinID == clang::AArch64::BI__sys) {
+  // Return 0 for convenience, even though MSVC returns some other 
undefined
+  // value.
+  Result = ConstantInt::get(Builder.getInt32Ty(), 0);
+}
+return Result;
   }
 
   if (BuiltinID == clang::AArch64::BI_AddressOfReturnAddress) {
diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h
index 3dd1eb45817d4..0ab69fd403d2d 100644
--- a/clang/lib/Headers/intrin.h
+++ b/clang/lib/Headers/intrin.h
@@ -374,6 +374,7 @@ long _InterlockedAdd(long volatile *Addend, long Value);
 __int64 _InterlockedAdd64(__int64 volatile *Addend, __int64 Value);
 __int64 _ReadStatusReg(int);
 void _WriteStatusReg(int, __int64);
+unsigned int __sys(int, __int64);
 
 unsigned short __cdecl _byteswap_ushort(unsigned short val);
 unsigned long __cdecl _byteswap_ulong (unsigned long val);
diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp
index e992a1012fde0..d76f1a62ff2b7 100644
--- a/clang/lib/Sema/SemaARM.cpp
+++ b/clang/lib/Sema/SemaARM.cpp
@@ -1084,7 +1084,7 @@ bool SemaARM::CheckAArch64BuiltinFunctionCall(const 
TargetInfo &TI,
   // converted to a register of the form S1_2_C3_C4_5. Let the hardware throw
   // an exception for incorrect registers. This matches MSVC behavior.
   if (BuiltinID == AArch64::BI_ReadStatusReg ||
-  BuiltinID == AArch64::BI_WriteStatusReg)
+  BuiltinID == AArch64::BI_WriteStatusReg || BuiltinID == AArch