[clang] __sys builtin support (PR #145079)
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)
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)
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