mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-26 05:18:46 +00:00
Support function attribute patchable_function_entry
This feature is generic. Make it applicable for AArch64 and X86 because the backend has only implemented NOP insertion for AArch64 and X86. Reviewed By: nickdesaulniers, aaron.ballman Differential Revision: https://reviews.llvm.org/D72221
This commit is contained in:
parent
a8fbdc5769
commit
a44c434b68
@ -683,6 +683,15 @@ def XRayLogArgs : InheritableAttr {
|
||||
let Documentation = [XRayDocs];
|
||||
}
|
||||
|
||||
def PatchableFunctionEntry
|
||||
: InheritableAttr,
|
||||
TargetSpecificAttr<TargetArch<["aarch64", "x86", "x86_64"]>> {
|
||||
let Spellings = [GCC<"patchable_function_entry">];
|
||||
let Subjects = SubjectList<[Function, ObjCMethod]>;
|
||||
let Args = [UnsignedArgument<"Count">, DefaultIntArgument<"Offset", 0>];
|
||||
let Documentation = [PatchableFunctionEntryDocs];
|
||||
}
|
||||
|
||||
def TLSModel : InheritableAttr {
|
||||
let Spellings = [GCC<"tls_model">];
|
||||
let Subjects = SubjectList<[TLSVar], ErrorDiag>;
|
||||
|
@ -3988,6 +3988,18 @@ If a function has neither of these attributes, they become subject to the XRay h
|
||||
}];
|
||||
}
|
||||
|
||||
def PatchableFunctionEntryDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
``__attribute__((patchable_function_entry(N,M)))`` is used to generate M NOPs
|
||||
before the function entry and N-M NOPs after the function entry. This attribute
|
||||
takes precedence over the command line option ``-fpatchable-function-entry=N,M``.
|
||||
``M`` defaults to 0 if omitted.
|
||||
|
||||
Currently, only M=0 is supported.
|
||||
}];
|
||||
}
|
||||
|
||||
def TransparentUnionDocs : Documentation {
|
||||
let Category = DocCatDecl;
|
||||
let Content = [{
|
||||
|
@ -799,8 +799,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
|
||||
FD->getBody()->getStmtClass() == Stmt::CoroutineBodyStmtClass)
|
||||
SanOpts.Mask &= ~SanitizerKind::Null;
|
||||
|
||||
// Apply xray attributes to the function (as a string, for now)
|
||||
if (D) {
|
||||
// Apply xray attributes to the function (as a string, for now)
|
||||
if (const auto *XRayAttr = D->getAttr<XRayInstrumentAttr>()) {
|
||||
if (CGM.getCodeGenOpts().XRayInstrumentationBundle.has(
|
||||
XRayInstrKind::Function)) {
|
||||
@ -819,6 +819,12 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
|
||||
"xray-instruction-threshold",
|
||||
llvm::itostr(CGM.getCodeGenOpts().XRayInstructionThreshold));
|
||||
}
|
||||
|
||||
if (const auto *Attr = D->getAttr<PatchableFunctionEntryAttr>()) {
|
||||
// Attr->getStart is currently ignored.
|
||||
Fn->addFnAttr("patchable-function-entry",
|
||||
std::to_string(Attr->getCount()));
|
||||
}
|
||||
}
|
||||
|
||||
// Add no-jump-tables value.
|
||||
|
@ -4915,6 +4915,25 @@ static void handleXRayLogArgsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
|
||||
XRayLogArgsAttr(S.Context, AL, ArgCount.getSourceIndex()));
|
||||
}
|
||||
|
||||
static void handlePatchableFunctionEntryAttr(Sema &S, Decl *D,
|
||||
const ParsedAttr &AL) {
|
||||
uint32_t Count = 0, Offset = 0;
|
||||
if (!checkUInt32Argument(S, AL, AL.getArgAsExpr(0), Count, 0, true))
|
||||
return;
|
||||
if (AL.getNumArgs() == 2) {
|
||||
Expr *Arg = AL.getArgAsExpr(1);
|
||||
if (!checkUInt32Argument(S, AL, Arg, Offset, 1, true))
|
||||
return;
|
||||
if (Offset) {
|
||||
S.Diag(getAttrLoc(AL), diag::err_attribute_argument_out_of_range)
|
||||
<< &AL << 0 << 0 << Arg->getBeginLoc();
|
||||
return;
|
||||
}
|
||||
}
|
||||
D->addAttr(::new (S.Context)
|
||||
PatchableFunctionEntryAttr(S.Context, AL, Count, Offset));
|
||||
}
|
||||
|
||||
static bool ArmMveAliasValid(unsigned BuiltinID, StringRef AliasName) {
|
||||
if (AliasName.startswith("__arm_"))
|
||||
AliasName = AliasName.substr(6);
|
||||
@ -7396,6 +7415,10 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
|
||||
handleXRayLogArgsAttr(S, D, AL);
|
||||
break;
|
||||
|
||||
case ParsedAttr::AT_PatchableFunctionEntry:
|
||||
handlePatchableFunctionEntryAttr(S, D, AL);
|
||||
break;
|
||||
|
||||
// Move semantics attribute.
|
||||
case ParsedAttr::AT_Reinitializes:
|
||||
handleSimpleAttribute<ReinitializesAttr>(S, D, AL);
|
||||
|
21
clang/test/CodeGen/patchable-function-entry.c
Normal file
21
clang/test/CodeGen/patchable-function-entry.c
Normal file
@ -0,0 +1,21 @@
|
||||
// RUN: %clang_cc1 -triple aarch64 -emit-llvm %s -o - | FileCheck %s
|
||||
|
||||
// CHECK: define void @f0() #0
|
||||
__attribute__((patchable_function_entry(0))) void f0() {}
|
||||
|
||||
// CHECK: define void @f00() #0
|
||||
__attribute__((patchable_function_entry(0, 0))) void f00() {}
|
||||
|
||||
// CHECK: define void @f2() #1
|
||||
__attribute__((patchable_function_entry(2))) void f2() {}
|
||||
|
||||
// CHECK: define void @f20() #1
|
||||
__attribute__((patchable_function_entry(2, 0))) void f20() {}
|
||||
|
||||
// CHECK: define void @f20decl() #1
|
||||
__attribute__((patchable_function_entry(2, 0))) void f20decl();
|
||||
void f20decl() {}
|
||||
|
||||
/// M in patchable_function_entry(N,M) is currently ignored.
|
||||
// CHECK: attributes #0 = { {{.*}} "patchable-function-entry"="0"
|
||||
// CHECK: attributes #1 = { {{.*}} "patchable-function-entry"="2"
|
@ -128,6 +128,7 @@
|
||||
// CHECK-NEXT: Owner (SubjectMatchRule_record_not_is_union)
|
||||
// CHECK-NEXT: ParamTypestate (SubjectMatchRule_variable_is_parameter)
|
||||
// CHECK-NEXT: PassObjectSize (SubjectMatchRule_variable_is_parameter)
|
||||
// CHECK-NEXT: PatchableFunctionEntry (SubjectMatchRule_function, SubjectMatchRule_objc_method)
|
||||
// CHECK-NEXT: Pointer (SubjectMatchRule_record_not_is_union)
|
||||
// CHECK-NEXT: ReleaseHandle (SubjectMatchRule_variable_is_parameter)
|
||||
// CHECK-NEXT: RenderScriptKernel (SubjectMatchRule_function)
|
||||
|
17
clang/test/Sema/patchable-function-entry-attr.c
Normal file
17
clang/test/Sema/patchable-function-entry-attr.c
Normal file
@ -0,0 +1,17 @@
|
||||
// RUN: %clang_cc1 -triple aarch64 -fsyntax-only -verify %s
|
||||
|
||||
// expected-error@+1 {{'patchable_function_entry' attribute takes at least 1 argument}}
|
||||
__attribute__((patchable_function_entry)) void f();
|
||||
|
||||
// expected-error@+1 {{'patchable_function_entry' attribute takes no more than 2 arguments}}
|
||||
__attribute__((patchable_function_entry(0, 0, 0))) void f();
|
||||
|
||||
// expected-error@+1 {{'patchable_function_entry' attribute requires a non-negative integral compile time constant expression}}
|
||||
__attribute__((patchable_function_entry(-1))) void f();
|
||||
|
||||
int i;
|
||||
// expected-error@+1 {{'patchable_function_entry' attribute requires parameter 0 to be an integer constant}}
|
||||
__attribute__((patchable_function_entry(i))) void f();
|
||||
|
||||
// expected-error@+1 {{'patchable_function_entry' attribute requires integer constant between 0 and 0 inclusive}}
|
||||
__attribute__((patchable_function_entry(1, 1))) void f();
|
9
clang/test/Sema/patchable-function-entry-attr.cpp
Normal file
9
clang/test/Sema/patchable-function-entry-attr.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
// RUN: %clang_cc1 -triple aarch64 -fsyntax-only -verify=silence %s
|
||||
// RUN: %clang_cc1 -triple i386 -fsyntax-only -verify=silence %s
|
||||
// RUN: %clang_cc1 -triple x86_64 -fsyntax-only -verify=silence %s
|
||||
// RUN: %clang_cc1 -triple ppc64le -fsyntax-only -verify %s
|
||||
|
||||
// silence-no-diagnostics
|
||||
|
||||
// expected-warning@+1 {{unknown attribute 'patchable_function_entry' ignored}}
|
||||
[[gnu::patchable_function_entry(0)]] void f();
|
Loading…
x
Reference in New Issue
Block a user