Skip to content

Commit ae7ab04

Browse files
authored
Add __hlt intrinsic for Windows ARM. (#96578)
Add __hlt, which is a MSVC ARM64 intrinsic. This intrinsic is just the HLT instruction. MSVC's version seems to return something undefined; in this patch it will just return zero. MSVC intrinsics are defined here https://learn.microsoft.com/en-us/cpp/intrinsics/arm64-intrinsics. I used unsigned int as the return type, because that is what the MSVC intrin.h header uses, even though it conflicts with the documentation.
1 parent 393eff4 commit ae7ab04

File tree

9 files changed

+46
-1
lines changed

9 files changed

+46
-1
lines changed

clang/include/clang/Basic/BuiltinsAArch64.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,8 @@ TARGET_HEADER_BUILTIN(_CountOneBits64, "UiULLi", "nh", INTRIN_H, ALL_MS_LANGUAGE
292292

293293
TARGET_HEADER_BUILTIN(__prefetch, "vvC*", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
294294

295+
TARGET_HEADER_BUILTIN(__hlt, "UiUi.", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
296+
295297
#undef BUILTIN
296298
#undef LANGBUILTIN
297299
#undef TARGET_BUILTIN

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11506,6 +11506,15 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
1150611506
return Builder.CreateCall(F, {Address, RW, Locality, Data});
1150711507
}
1150811508

11509+
if (BuiltinID == AArch64::BI__hlt) {
11510+
Function *F = CGM.getIntrinsic(Intrinsic::aarch64_hlt);
11511+
Builder.CreateCall(F, {EmitScalarExpr(E->getArg(0))});
11512+
11513+
// Return 0 for convenience, even though MSVC returns some other undefined
11514+
// value.
11515+
return ConstantInt::get(Builder.getInt32Ty(), 0);
11516+
}
11517+
1150911518
// Handle MSVC intrinsics before argument evaluation to prevent double
1151011519
// evaluation.
1151111520
if (std::optional<MSVCIntrin> MsvcIntId =

clang/lib/Headers/intrin.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,10 @@ unsigned int _CountLeadingSigns64(__int64);
408408
unsigned int _CountOneBits(unsigned long);
409409
unsigned int _CountOneBits64(unsigned __int64);
410410

411+
unsigned int __hlt(unsigned int, ...);
412+
411413
void __cdecl __prefetch(const void *);
414+
412415
#endif
413416

414417
/*----------------------------------------------------------------------------*\

clang/lib/Sema/SemaARM.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,6 +1112,9 @@ bool SemaARM::CheckAArch64BuiltinFunctionCall(const TargetInfo &TI,
11121112
if (BuiltinID == AArch64::BI__break)
11131113
return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);
11141114

1115+
if (BuiltinID == AArch64::BI__hlt)
1116+
return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);
1117+
11151118
if (CheckNeonBuiltinFunctionCall(TI, BuiltinID, TheCall))
11161119
return true;
11171120

clang/test/CodeGen/arm64-microsoft-intrinsics.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,15 @@ void check__break() {
127127
// CHECK-MSVC: call void @llvm.aarch64.break(i32 0)
128128
// CHECK-LINUX: error: call to undeclared function '__break'
129129

130+
void check__hlt() {
131+
__hlt(0);
132+
__hlt(1, 2, 3, 4, 5);
133+
int x = __hlt(0);
134+
}
135+
136+
// CHECK-MSVC: call void @llvm.aarch64.hlt(i32 0)
137+
// CHECK-LINUX: error: call to undeclared function '__hlt'
138+
130139
unsigned __int64 check__getReg(void) {
131140
unsigned volatile __int64 reg;
132141
reg = __getReg(18);

clang/test/Sema/builtins-microsoft-arm64.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ void check__break(int x) {
99
__break(x); // expected-error {{argument to '__break' must be a constant integer}}
1010
}
1111

12+
void check__hlt() {
13+
__hlt(-1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
14+
__hlt(65536); // expected-error-re {{argument value {{.*}} is outside the valid range}}
15+
}
16+
1217
void check__getReg(void) {
1318
__getReg(-1); // expected-error-re {{argument value {{.*}} is outside the valid range}}
1419
__getReg(32); // expected-error-re {{argument value {{.*}} is outside the valid range}}

llvm/include/llvm/IR/IntrinsicsAArch64.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ def int_aarch64_frint64x
5757
: DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0> ],
5858
[ IntrNoMem ]>;
5959

60+
6061
//===----------------------------------------------------------------------===//
6162
// HINT
6263

@@ -65,6 +66,8 @@ def int_aarch64_hint : DefaultAttrsIntrinsic<[], [llvm_i32_ty]>;
6566
def int_aarch64_break : Intrinsic<[], [llvm_i32_ty],
6667
[IntrNoMem, IntrHasSideEffects, IntrNoReturn, IntrCold, ImmArg<ArgIndex<0>>]>;
6768

69+
def int_aarch64_hlt : Intrinsic<[], [llvm_i32_ty],
70+
[IntrNoMem, IntrHasSideEffects, IntrNoReturn, IntrCold, ImmArg<ArgIndex<0>>]>;
6871

6972
def int_aarch64_prefetch : Intrinsic<[],
7073
[llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],

llvm/lib/Target/AArch64/AArch64InstrInfo.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3111,7 +3111,8 @@ def BRK : ExceptionGeneration<0b001, 0b00, "brk",
31113111
def DCPS1 : ExceptionGeneration<0b101, 0b01, "dcps1">;
31123112
def DCPS2 : ExceptionGeneration<0b101, 0b10, "dcps2">;
31133113
def DCPS3 : ExceptionGeneration<0b101, 0b11, "dcps3">, Requires<[HasEL3]>;
3114-
def HLT : ExceptionGeneration<0b010, 0b00, "hlt">;
3114+
def HLT : ExceptionGeneration<0b010, 0b00, "hlt",
3115+
[(int_aarch64_hlt timm32_0_65535:$imm)]>;
31153116
def HVC : ExceptionGeneration<0b000, 0b10, "hvc">;
31163117
def SMC : ExceptionGeneration<0b000, 0b11, "smc">, Requires<[HasEL3]>;
31173118
def SVC : ExceptionGeneration<0b000, 0b01, "svc">;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
; RUN: llc < %s -mtriple=arm64-eabi | FileCheck %s
2+
3+
define void @foo() nounwind {
4+
; CHECK-LABEL: foo
5+
; CHECK: hlt #0x2
6+
tail call void @llvm.aarch64.hlt(i32 2)
7+
ret void
8+
}
9+
10+
declare void @llvm.aarch64.hlt(i32 immarg) nounwind

0 commit comments

Comments
 (0)