Skip to content

Commit

Permalink
[clang][ARM64EC] Add support for hybrid_patchable attribute. (llvm#99478
Browse files Browse the repository at this point in the history
)
  • Loading branch information
cjacek authored Jul 27, 2024
1 parent ae4f249 commit ea98dc8
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 0 deletions.
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ Attribute Changes in Clang

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

- The ``hybrid_patchable`` attribute is now supported on ARM64EC targets. It can be used to specify
that a function requires an additional x86-64 thunk, which may be patched at runtime.

Improvements to Clang's diagnostics
-----------------------------------

Expand Down
9 changes: 9 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,9 @@ def TargetELF : TargetSpec {
def TargetELFOrMachO : TargetSpec {
let ObjectFormats = ["ELF", "MachO"];
}
def TargetWindowsArm64EC : TargetSpec {
let CustomCode = [{ Target.getTriple().isWindowsArm64EC() }];
}

def TargetSupportsInitPriority : TargetSpec {
let CustomCode = [{ !Target.getTriple().isOSzOS() }];
Expand Down Expand Up @@ -4027,6 +4030,12 @@ def SelectAny : InheritableAttr {
let SimpleHandler = 1;
}

def HybridPatchable : InheritableAttr, TargetSpecificAttr<TargetWindowsArm64EC> {
let Spellings = [Declspec<"hybrid_patchable">, Clang<"hybrid_patchable">];
let Subjects = SubjectList<[Function]>;
let Documentation = [HybridPatchableDocs];
}

def Thread : Attr {
let Spellings = [Declspec<"thread">];
let LangOpts = [MicrosoftExt];
Expand Down
10 changes: 10 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -5985,6 +5985,16 @@ For more information see
or `msvc documentation <https://docs.microsoft.com/pl-pl/cpp/cpp/selectany>`_.
}]; }

def HybridPatchableDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
The ``hybrid_patchable`` attribute declares an ARM64EC function with an additional
x86-64 thunk, which may be patched at runtime.

For more information see
`ARM64EC ABI documentation <https://learn.microsoft.com/en-us/windows/arm/arm64ec-abi>`_.
}]; }

def WebAssemblyExportNameDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -3681,6 +3681,9 @@ def err_attribute_weak_static : Error<
"weak declaration cannot have internal linkage">;
def err_attribute_selectany_non_extern_data : Error<
"'selectany' can only be applied to data items with external linkage">;
def warn_attribute_hybrid_patchable_non_extern : Warning<
"'hybrid_patchable' is ignored on functions without external linkage">,
InGroup<IgnoredAttributes>;
def err_declspec_thread_on_thread_variable : Error<
"'__declspec(thread)' applied to variable that already has a "
"thread-local storage specifier">;
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,9 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
if (D && D->hasAttr<NoProfileFunctionAttr>())
Fn->addFnAttr(llvm::Attribute::NoProfile);

if (D && D->hasAttr<HybridPatchableAttr>())
Fn->addFnAttr(llvm::Attribute::HybridPatchable);

if (D) {
// Function attributes take precedence over command line flags.
if (auto *A = D->getAttr<FunctionReturnThunksAttr>()) {
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6890,6 +6890,11 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
}
}

if (HybridPatchableAttr *Attr = ND.getAttr<HybridPatchableAttr>()) {
if (!ND.isExternallyVisible())
S.Diag(Attr->getLocation(),
diag::warn_attribute_hybrid_patchable_non_extern);
}
if (const InheritableAttr *Attr = getDLLAttr(&ND)) {
auto *VD = dyn_cast<VarDecl>(&ND);
bool IsAnonymousNS = false;
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6871,6 +6871,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
case ParsedAttr::AT_MSConstexpr:
handleMSConstexprAttr(S, D, AL);
break;
case ParsedAttr::AT_HybridPatchable:
handleSimpleAttribute<HybridPatchableAttr>(S, D, AL);
break;

// HLSL attributes:
case ParsedAttr::AT_HLSLNumThreads:
Expand Down
34 changes: 34 additions & 0 deletions clang/test/CodeGen/arm64ec-hybrid-patchable.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// REQUIRES: aarch64-registered-target
// RUN: %clang_cc1 -triple arm64ec-pc-windows -fms-extensions -emit-llvm -o - %s -verify | FileCheck %s

// CHECK: ; Function Attrs: hybrid_patchable noinline nounwind optnone
// CHECK-NEXT: define dso_local i32 @func() #0 {
int __attribute__((hybrid_patchable)) func(void) { return 1; }

// CHECK: ; Function Attrs: hybrid_patchable noinline nounwind optnone
// CHECK-NEXT: define dso_local i32 @func2() #0 {
int __declspec(hybrid_patchable) func2(void) { return 2; }

// CHECK: ; Function Attrs: hybrid_patchable noinline nounwind optnone
// CHECK-NEXT: define dso_local i32 @func3() #0 {
int __declspec(hybrid_patchable) func3(void);
int func3(void) { return 3; }

// CHECK: ; Function Attrs: hybrid_patchable noinline nounwind optnone
// CHECK-NEXT: define dso_local i32 @func4() #0 {
[[clang::hybrid_patchable]] int func4(void);
int func4(void) { return 3; }

// CHECK: ; Function Attrs: hybrid_patchable noinline nounwind optnone
// CHECK-NEXT: define internal void @static_func() #0 {
// expected-warning@+1 {{'hybrid_patchable' is ignored on functions without external linkage}}
static void __declspec(hybrid_patchable) static_func(void) {}

// CHECK: ; Function Attrs: hybrid_patchable noinline nounwind optnone
// CHECK-NEXT: define linkonce_odr dso_local i32 @func5() #0 comdat {
int inline __declspec(hybrid_patchable) func5(void) { return 4; }

void caller(void) {
static_func();
func5();
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
// CHECK-NEXT: HIPManaged (SubjectMatchRule_variable)
// CHECK-NEXT: HLSLResourceClass (SubjectMatchRule_record_not_is_union)
// CHECK-NEXT: Hot (SubjectMatchRule_function)
// CHECK-NEXT: HybridPatchable (SubjectMatchRule_function)
// CHECK-NEXT: IBAction (SubjectMatchRule_objc_method_is_instance)
// CHECK-NEXT: IFunc (SubjectMatchRule_function)
// CHECK-NEXT: InitPriority (SubjectMatchRule_variable)
Expand Down

0 comments on commit ea98dc8

Please sign in to comment.