Skip to content

Commit ea98dc8

Browse files
authored
[clang][ARM64EC] Add support for hybrid_patchable attribute. (llvm#99478)
1 parent ae4f249 commit ea98dc8

9 files changed

+71
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ Attribute Changes in Clang
116116

117117
- Introduced a new format attribute ``__attribute__((format(syslog, 1, 2)))`` from OpenBSD.
118118

119+
- The ``hybrid_patchable`` attribute is now supported on ARM64EC targets. It can be used to specify
120+
that a function requires an additional x86-64 thunk, which may be patched at runtime.
121+
119122
Improvements to Clang's diagnostics
120123
-----------------------------------
121124

clang/include/clang/Basic/Attr.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,9 @@ def TargetELF : TargetSpec {
477477
def TargetELFOrMachO : TargetSpec {
478478
let ObjectFormats = ["ELF", "MachO"];
479479
}
480+
def TargetWindowsArm64EC : TargetSpec {
481+
let CustomCode = [{ Target.getTriple().isWindowsArm64EC() }];
482+
}
480483

481484
def TargetSupportsInitPriority : TargetSpec {
482485
let CustomCode = [{ !Target.getTriple().isOSzOS() }];
@@ -4027,6 +4030,12 @@ def SelectAny : InheritableAttr {
40274030
let SimpleHandler = 1;
40284031
}
40294032

4033+
def HybridPatchable : InheritableAttr, TargetSpecificAttr<TargetWindowsArm64EC> {
4034+
let Spellings = [Declspec<"hybrid_patchable">, Clang<"hybrid_patchable">];
4035+
let Subjects = SubjectList<[Function]>;
4036+
let Documentation = [HybridPatchableDocs];
4037+
}
4038+
40304039
def Thread : Attr {
40314040
let Spellings = [Declspec<"thread">];
40324041
let LangOpts = [MicrosoftExt];

clang/include/clang/Basic/AttrDocs.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5985,6 +5985,16 @@ For more information see
59855985
or `msvc documentation <https://docs.microsoft.com/pl-pl/cpp/cpp/selectany>`_.
59865986
}]; }
59875987

5988+
def HybridPatchableDocs : Documentation {
5989+
let Category = DocCatFunction;
5990+
let Content = [{
5991+
The ``hybrid_patchable`` attribute declares an ARM64EC function with an additional
5992+
x86-64 thunk, which may be patched at runtime.
5993+
5994+
For more information see
5995+
`ARM64EC ABI documentation <https://learn.microsoft.com/en-us/windows/arm/arm64ec-abi>`_.
5996+
}]; }
5997+
59885998
def WebAssemblyExportNameDocs : Documentation {
59895999
let Category = DocCatFunction;
59906000
let Content = [{

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3681,6 +3681,9 @@ def err_attribute_weak_static : Error<
36813681
"weak declaration cannot have internal linkage">;
36823682
def err_attribute_selectany_non_extern_data : Error<
36833683
"'selectany' can only be applied to data items with external linkage">;
3684+
def warn_attribute_hybrid_patchable_non_extern : Warning<
3685+
"'hybrid_patchable' is ignored on functions without external linkage">,
3686+
InGroup<IgnoredAttributes>;
36843687
def err_declspec_thread_on_thread_variable : Error<
36853688
"'__declspec(thread)' applied to variable that already has a "
36863689
"thread-local storage specifier">;

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,9 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
991991
if (D && D->hasAttr<NoProfileFunctionAttr>())
992992
Fn->addFnAttr(llvm::Attribute::NoProfile);
993993

994+
if (D && D->hasAttr<HybridPatchableAttr>())
995+
Fn->addFnAttr(llvm::Attribute::HybridPatchable);
996+
994997
if (D) {
995998
// Function attributes take precedence over command line flags.
996999
if (auto *A = D->getAttr<FunctionReturnThunksAttr>()) {

clang/lib/Sema/SemaDecl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6890,6 +6890,11 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
68906890
}
68916891
}
68926892

6893+
if (HybridPatchableAttr *Attr = ND.getAttr<HybridPatchableAttr>()) {
6894+
if (!ND.isExternallyVisible())
6895+
S.Diag(Attr->getLocation(),
6896+
diag::warn_attribute_hybrid_patchable_non_extern);
6897+
}
68936898
if (const InheritableAttr *Attr = getDLLAttr(&ND)) {
68946899
auto *VD = dyn_cast<VarDecl>(&ND);
68956900
bool IsAnonymousNS = false;

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6871,6 +6871,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
68716871
case ParsedAttr::AT_MSConstexpr:
68726872
handleMSConstexprAttr(S, D, AL);
68736873
break;
6874+
case ParsedAttr::AT_HybridPatchable:
6875+
handleSimpleAttribute<HybridPatchableAttr>(S, D, AL);
6876+
break;
68746877

68756878
// HLSL attributes:
68766879
case ParsedAttr::AT_HLSLNumThreads:
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// REQUIRES: aarch64-registered-target
2+
// RUN: %clang_cc1 -triple arm64ec-pc-windows -fms-extensions -emit-llvm -o - %s -verify | FileCheck %s
3+
4+
// CHECK: ; Function Attrs: hybrid_patchable noinline nounwind optnone
5+
// CHECK-NEXT: define dso_local i32 @func() #0 {
6+
int __attribute__((hybrid_patchable)) func(void) { return 1; }
7+
8+
// CHECK: ; Function Attrs: hybrid_patchable noinline nounwind optnone
9+
// CHECK-NEXT: define dso_local i32 @func2() #0 {
10+
int __declspec(hybrid_patchable) func2(void) { return 2; }
11+
12+
// CHECK: ; Function Attrs: hybrid_patchable noinline nounwind optnone
13+
// CHECK-NEXT: define dso_local i32 @func3() #0 {
14+
int __declspec(hybrid_patchable) func3(void);
15+
int func3(void) { return 3; }
16+
17+
// CHECK: ; Function Attrs: hybrid_patchable noinline nounwind optnone
18+
// CHECK-NEXT: define dso_local i32 @func4() #0 {
19+
[[clang::hybrid_patchable]] int func4(void);
20+
int func4(void) { return 3; }
21+
22+
// CHECK: ; Function Attrs: hybrid_patchable noinline nounwind optnone
23+
// CHECK-NEXT: define internal void @static_func() #0 {
24+
// expected-warning@+1 {{'hybrid_patchable' is ignored on functions without external linkage}}
25+
static void __declspec(hybrid_patchable) static_func(void) {}
26+
27+
// CHECK: ; Function Attrs: hybrid_patchable noinline nounwind optnone
28+
// CHECK-NEXT: define linkonce_odr dso_local i32 @func5() #0 comdat {
29+
int inline __declspec(hybrid_patchable) func5(void) { return 4; }
30+
31+
void caller(void) {
32+
static_func();
33+
func5();
34+
}

clang/test/Misc/pragma-attribute-supported-attributes-list.test

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
// CHECK-NEXT: HIPManaged (SubjectMatchRule_variable)
8484
// CHECK-NEXT: HLSLResourceClass (SubjectMatchRule_record_not_is_union)
8585
// CHECK-NEXT: Hot (SubjectMatchRule_function)
86+
// CHECK-NEXT: HybridPatchable (SubjectMatchRule_function)
8687
// CHECK-NEXT: IBAction (SubjectMatchRule_objc_method_is_instance)
8788
// CHECK-NEXT: IFunc (SubjectMatchRule_function)
8889
// CHECK-NEXT: InitPriority (SubjectMatchRule_variable)

0 commit comments

Comments
 (0)