Skip to content

__sys builtin support #145079

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/include/clang/Basic/BuiltinsAArch64.def
Original file line number Diff line number Diff line change
Expand Up @@ -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, "")
Expand Down
26 changes: 17 additions & 9 deletions clang/lib/CodeGen/TargetBuiltins/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Headers/intrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
68 changes: 68 additions & 0 deletions clang/test/CodeGen/arm64-microsoft-sys.c
Original file line number Diff line number Diff line change
@@ -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"}
9 changes: 9 additions & 0 deletions clang/test/Sema/builtins-microsoft-arm64.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
}