Skip to content
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

[clang][ARM64EC] Add support for hybrid_patchable attribute. #99478

Merged
merged 1 commit into from
Jul 27, 2024
Merged
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
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,9 @@ Attribute Changes in Clang
The attributes declare constraints about a function's behavior pertaining to blocking and
heap memory allocation.

- 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
-----------------------------------
- Clang now emits an error instead of a warning for ``-Wundefined-internal``
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 @@ -5984,6 +5984,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 @@ -3671,6 +3671,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 @@ -989,6 +989,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 @@ -7039,6 +7039,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
Loading