-
Notifications
You must be signed in to change notification settings - Fork 14.3k
__sys builtin support for AArch64 #146456
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-backend-aarch64 @llvm/pr-subscribers-backend-arm Author: Adam Glass (AdamGlass) Changes[This is a resubmit of 145079 after some git clumsiness on my part responding to feedback] 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: Implementation: Adam Glass Full diff: https://github.com/llvm/llvm-project/pull/146456.diff 6 Files Affected:
diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def b/clang/include/clang/Basic/BuiltinsAArch64.def
index 909e35792b461..b2aa36acd4506 100644
--- a/clang/include/clang/Basic/BuiltinsAArch64.def
+++ b/clang/include/clang/Basic/BuiltinsAArch64.def
@@ -274,6 +274,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 c0165a5eac3f1..aea4f1cd97837 100644
--- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
@@ -5471,19 +5471,22 @@ 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_ReadStatusReg ||
+ BuiltinID == clang::AArch64::BI_WriteStatusReg)
+ ? ((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 +5503,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 d9382440f4b42..588c283cbdfba 100644
--- a/clang/lib/Headers/intrin.h
+++ b/clang/lib/Headers/intrin.h
@@ -392,6 +392,7 @@ __int64 _InterlockedAdd64_nf(__int64 volatile *, __int64);
__int64 _InterlockedAdd64_rel(__int64 volatile *, __int64);
__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 f7965ff889bba..b7dca8d090949 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..5913a02d933ae
--- /dev/null
+++ b/clang/test/CodeGen/arm64-microsoft-sys.c
@@ -0,0 +1,65 @@
+// 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-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
+}
|
@llvm/pr-subscribers-backend-x86 Author: Adam Glass (AdamGlass) Changes[This is a resubmit of 145079 after some git clumsiness on my part responding to feedback] 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: Implementation: Adam Glass Full diff: https://github.com/llvm/llvm-project/pull/146456.diff 6 Files Affected:
diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def b/clang/include/clang/Basic/BuiltinsAArch64.def
index 909e35792b461..b2aa36acd4506 100644
--- a/clang/include/clang/Basic/BuiltinsAArch64.def
+++ b/clang/include/clang/Basic/BuiltinsAArch64.def
@@ -274,6 +274,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 c0165a5eac3f1..aea4f1cd97837 100644
--- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
@@ -5471,19 +5471,22 @@ 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_ReadStatusReg ||
+ BuiltinID == clang::AArch64::BI_WriteStatusReg)
+ ? ((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 +5503,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 d9382440f4b42..588c283cbdfba 100644
--- a/clang/lib/Headers/intrin.h
+++ b/clang/lib/Headers/intrin.h
@@ -392,6 +392,7 @@ __int64 _InterlockedAdd64_nf(__int64 volatile *, __int64);
__int64 _InterlockedAdd64_rel(__int64 volatile *, __int64);
__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 f7965ff889bba..b7dca8d090949 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..5913a02d933ae
--- /dev/null
+++ b/clang/test/CodeGen/arm64-microsoft-sys.c
@@ -0,0 +1,65 @@
+// 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-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
+}
|
@llvm/pr-subscribers-clang-codegen Author: Adam Glass (AdamGlass) Changes[This is a resubmit of 145079 after some git clumsiness on my part responding to feedback] 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: Implementation: Adam Glass Full diff: https://github.com/llvm/llvm-project/pull/146456.diff 6 Files Affected:
diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def b/clang/include/clang/Basic/BuiltinsAArch64.def
index 909e35792b461..b2aa36acd4506 100644
--- a/clang/include/clang/Basic/BuiltinsAArch64.def
+++ b/clang/include/clang/Basic/BuiltinsAArch64.def
@@ -274,6 +274,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 c0165a5eac3f1..aea4f1cd97837 100644
--- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
@@ -5471,19 +5471,22 @@ 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_ReadStatusReg ||
+ BuiltinID == clang::AArch64::BI_WriteStatusReg)
+ ? ((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 +5503,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 d9382440f4b42..588c283cbdfba 100644
--- a/clang/lib/Headers/intrin.h
+++ b/clang/lib/Headers/intrin.h
@@ -392,6 +392,7 @@ __int64 _InterlockedAdd64_nf(__int64 volatile *, __int64);
__int64 _InterlockedAdd64_rel(__int64 volatile *, __int64);
__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 f7965ff889bba..b7dca8d090949 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..5913a02d933ae
--- /dev/null
+++ b/clang/test/CodeGen/arm64-microsoft-sys.c
@@ -0,0 +1,65 @@
+// 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-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
+}
|
@llvm/pr-subscribers-clang Author: Adam Glass (AdamGlass) Changes[This is a resubmit of 145079 after some git clumsiness on my part responding to feedback] 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: Implementation: Adam Glass Full diff: https://github.com/llvm/llvm-project/pull/146456.diff 6 Files Affected:
diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def b/clang/include/clang/Basic/BuiltinsAArch64.def
index 909e35792b461..b2aa36acd4506 100644
--- a/clang/include/clang/Basic/BuiltinsAArch64.def
+++ b/clang/include/clang/Basic/BuiltinsAArch64.def
@@ -274,6 +274,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 c0165a5eac3f1..aea4f1cd97837 100644
--- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
@@ -5471,19 +5471,22 @@ 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_ReadStatusReg ||
+ BuiltinID == clang::AArch64::BI_WriteStatusReg)
+ ? ((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 +5503,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 d9382440f4b42..588c283cbdfba 100644
--- a/clang/lib/Headers/intrin.h
+++ b/clang/lib/Headers/intrin.h
@@ -392,6 +392,7 @@ __int64 _InterlockedAdd64_nf(__int64 volatile *, __int64);
__int64 _InterlockedAdd64_rel(__int64 volatile *, __int64);
__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 f7965ff889bba..b7dca8d090949 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..5913a02d933ae
--- /dev/null
+++ b/clang/test/CodeGen/arm64-microsoft-sys.c
@@ -0,0 +1,65 @@
+// 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-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
+}
|
[This is a resubmit of 145079 after some git clumsiness on my part responding to feedback]
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
[email protected]
@dpaoliello