llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Adam Glass (AdamGlass) <details> <summary>Changes</summary> 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 adamglass@<!-- -->spottedfoobar.com adamglass@<!-- -->microsoft.com @<!-- -->dpaoliello --- Full diff: https://github.com/llvm/llvm-project/pull/145079.diff 6 Files Affected: - (modified) clang/include/clang/Basic/BuiltinsAArch64.def (+1) - (modified) clang/lib/CodeGen/TargetBuiltins/ARM.cpp (+16-9) - (modified) clang/lib/Headers/intrin.h (+1) - (modified) clang/lib/Sema/SemaARM.cpp (+1-1) - (added) clang/test/CodeGen/arm64-microsoft-sys.c (+68) - (modified) clang/test/Sema/builtins-microsoft-arm64.c (+9) ``````````diff 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 == AArch64::BI__sys) return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0x7fff); if (BuiltinID == AArch64::BI__getReg) diff --git a/clang/test/CodeGen/arm64-microsoft-sys.c b/clang/test/CodeGen/arm64-microsoft-sys.c new file mode 100644 index 0000000000000..a9790de43341f --- /dev/null +++ b/clang/test/CodeGen/arm64-microsoft-sys.c @@ -0,0 +1,68 @@ +// REQUIRES: aarch64-registered-target + +// RUN: %clang_cc1 -triple arm64-windows -fms-compatibility -S \ +// RUN: -o - %s | FileCheck %s -check-prefix CHECK-ASM + +// RUN: %clang_cc1 -triple arm64-darwin -fms-compatibility -S \ +// RUN: -o - %s | FileCheck %s -check-prefix CHECK-ASM + +// RUN: %clang_cc1 -triple arm64-windows -fms-compatibility -emit-llvm \ +// RUN: -o - %s | FileCheck %s -check-prefix CHECK-IR + +// RUN: %clang_cc1 -triple arm64-darwin -fms-compatibility -emit-llvm \ +// RUN: -o - %s | FileCheck %s -check-prefix CHECK-IR + +// From winnt.h +// op0=1 encodings, use with __sys +#define ARM64_SYSINSTR(op0, op1, crn, crm, op2) \ + ( ((op1 & 7) << 11) | \ + ((crn & 15) << 7) | \ + ((crm & 15) << 3) | \ + ((op2 & 7) << 0) ) + +// +// Sampling of instructions +// +#define ARM64_DC_CGDSW_EL1 ARM64_SYSINSTR(1,0, 7,10,6) // Clean of Data and Allocation Tags by Set/Way +#define ARM64_IC_IALLU_EL1 ARM64_SYSINSTR(1,0, 7, 5,0) // Instruction Cache Invalidate All to PoU +#define ARM64_AT_S1E2W ARM64_SYSINSTR(1,4, 7, 8,1) // Translate Stage1, EL2, write +#define ARM64_TLBI_VMALLE1 ARM64_SYSINSTR(1,0, 8, 7,0) // Invalidate stage 1 TLB [CP15_TLBIALL] +#define ARM64_CFP_RCTX ARM64_SYSINSTR(1,3, 7, 3,4) // Control Flow Prediction Restriction by Context + +// From intrin.h +unsigned int __sys(int, __int64); + +void check__sys(__int64 v) { + __int64 ret; + + __sys(ARM64_DC_CGDSW_EL1, v); +// CHECK-ASM: msr S1_0_C7_C10_6, x8 +// CHECK-IR: %[[VAR:.*]] = load i64, +// CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD2:.*]], i64 %[[VAR]]) + + __sys(ARM64_IC_IALLU_EL1, v); +// CHECK-ASM: msr S1_0_C7_C5_0, x8 +// CHECK-IR: %[[VAR:.*]] = load i64, +// CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD3:.*]], i64 %[[VAR]]) + + __sys(ARM64_AT_S1E2W, v); +// CHECK-ASM: msr S1_4_C7_C8_1, x8 +// CHECK-IR: %[[VAR:.*]] = load i64, +// CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD4:.*]], i64 %[[VAR]]) + + __sys(ARM64_TLBI_VMALLE1, v); +// CHECK-ASM: msr S1_0_C8_C7_0, x8 +// CHECK-IR: %[[VAR:.*]] = load i64, +// CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD5:.*]], i64 %[[VAR]]) + + __sys(ARM64_CFP_RCTX, v); +// CHECK-ASM: msr S1_3_C7_C3_4, x8 +// CHECK-IR: %[[VAR:.*]] = load i64, +// CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD6:.*]], i64 %[[VAR]]) +} + +// CHECK-IR: ![[MD2]] = !{!"1:0:7:10:6"} +// CHECK-IR: ![[MD3]] = !{!"1:0:7:5:0"} +// CHECK-IR: ![[MD4]] = !{!"1:4:7:8:1"} +// CHECK-IR: ![[MD5]] = !{!"1:0:8:7:0"} +// CHECK-IR: ![[MD6]] = !{!"1:3:7:3:4"} diff --git a/clang/test/Sema/builtins-microsoft-arm64.c b/clang/test/Sema/builtins-microsoft-arm64.c index 322cf7542f43a..a915a370cde14 100644 --- a/clang/test/Sema/builtins-microsoft-arm64.c +++ b/clang/test/Sema/builtins-microsoft-arm64.c @@ -24,3 +24,12 @@ void check_ReadWriteStatusReg(int v) { _ReadStatusReg(x); // expected-error {{argument to '_ReadStatusReg' must be a constant integer}} _WriteStatusReg(x, v); // expected-error {{argument to '_WriteStatusReg' must be a constant integer}} } + +void check__sys(int v) { + int x; + __sys(x, v); // expected-error {{argument to '__sys' must be a constant integer}} +} + +unsigned int check__sys_retval() { + return __sys(0, 1); // builtin has superfluous return value for MSVC compatibility +} `````````` </details> 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