Skip to content

Commit 1ac6b1b

Browse files
committed
[clang][ARM64EC] Add support for hybrid_patchable attribute.
1 parent b27a120 commit 1ac6b1b

9 files changed

+68
-0
lines changed

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 TargetArm64EC : 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 : DeclOrTypeAttr, TargetSpecificAttr<TargetArm64EC> {
4034+
let Spellings = [Declspec<"hybrid_patchable">, GCC<"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
@@ -5984,6 +5984,16 @@ For more information see
59845984
or `msvc documentation <https://docs.microsoft.com/pl-pl/cpp/cpp/selectany>`_.
59855985
}]; }
59865986

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

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3671,6 +3671,9 @@ def err_attribute_weak_static : Error<
36713671
"weak declaration cannot have internal linkage">;
36723672
def err_attribute_selectany_non_extern_data : Error<
36733673
"'selectany' can only be applied to data items with external linkage">;
3674+
def warn_attribute_hybrid_patchable_non_extern : Warning<
3675+
"'hybrid_patchable' is ignored on functions without external linkage">,
3676+
InGroup<IgnoredAttributes>;
36743677
def err_declspec_thread_on_thread_variable : Error<
36753678
"'__declspec(thread)' applied to variable that already has a "
36763679
"thread-local storage specifier">;

clang/lib/AST/TypePrinter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1984,6 +1984,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
19841984
case attr::MSABI: OS << "ms_abi"; break;
19851985
case attr::SysVABI: OS << "sysv_abi"; break;
19861986
case attr::RegCall: OS << "regcall"; break;
1987+
case attr::HybridPatchable:
1988+
OS << "hybrid_patchable";
1989+
break;
19871990
case attr::Pcs: {
19881991
OS << "pcs(";
19891992
QualType t = T->getEquivalentType();

clang/lib/CodeGen/CodeGenFunction.cpp

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

980+
if (D && D->hasAttr<HybridPatchableAttr>())
981+
Fn->addFnAttr(llvm::Attribute::HybridPatchable);
982+
980983
if (D) {
981984
// Function attributes take precedence over command line flags.
982985
if (auto *A = D->getAttr<FunctionReturnThunksAttr>()) {

clang/lib/Sema/SemaDecl.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6886,6 +6886,13 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
68866886
}
68876887
}
68886888

6889+
if (HybridPatchableAttr *Attr = ND.getAttr<HybridPatchableAttr>()) {
6890+
if (!ND.isExternallyVisible()) {
6891+
S.Diag(Attr->getLocation(),
6892+
diag::warn_attribute_hybrid_patchable_non_extern);
6893+
ND.dropAttr<SelectAnyAttr>();
6894+
}
6895+
}
68896896
if (const InheritableAttr *Attr = getDLLAttr(&ND)) {
68906897
auto *VD = dyn_cast<VarDecl>(&ND);
68916898
bool IsAnonymousNS = false;

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7033,6 +7033,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
70337033
case ParsedAttr::AT_MSConstexpr:
70347034
handleMSConstexprAttr(S, D, AL);
70357035
break;
7036+
case ParsedAttr::AT_HybridPatchable:
7037+
handleSimpleAttribute<HybridPatchableAttr>(S, D, AL);
7038+
break;
70367039

70377040
// HLSL attributes:
70387041
case ParsedAttr::AT_HLSLNumThreads:
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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 internal void @static_func() #0 {
19+
// expected-warning@+1 {{'hybrid_patchable' is ignored on functions without external linkage}}
20+
static void __declspec(hybrid_patchable) static_func(void) {}
21+
22+
// CHECK: ; Function Attrs: hybrid_patchable noinline nounwind optnone
23+
// CHECK-NEXT: define linkonce_odr dso_local i32 @func4() #0 comdat {
24+
int inline __declspec(hybrid_patchable) func4(void) { return 4; }
25+
26+
void caller(void) {
27+
static_func();
28+
func4();
29+
}

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)