This revision was automatically updated to reflect the committed changes. Closed by commit rGa44c434b68e5: Support function attribute patchable_function_entry (authored by MaskRay).
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D72221/new/ https://reviews.llvm.org/D72221 Files: clang/include/clang/Basic/Attr.td clang/include/clang/Basic/AttrDocs.td clang/lib/CodeGen/CodeGenFunction.cpp clang/lib/Sema/SemaDeclAttr.cpp clang/test/CodeGen/patchable-function-entry.c clang/test/Misc/pragma-attribute-supported-attributes-list.test clang/test/Sema/patchable-function-entry-attr.c clang/test/Sema/patchable-function-entry-attr.cpp
Index: clang/test/Sema/patchable-function-entry-attr.cpp =================================================================== --- /dev/null +++ clang/test/Sema/patchable-function-entry-attr.cpp @@ -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(); Index: clang/test/Sema/patchable-function-entry-attr.c =================================================================== --- /dev/null +++ clang/test/Sema/patchable-function-entry-attr.c @@ -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(); Index: clang/test/Misc/pragma-attribute-supported-attributes-list.test =================================================================== --- clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -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) Index: clang/test/CodeGen/patchable-function-entry.c =================================================================== --- /dev/null +++ clang/test/CodeGen/patchable-function-entry.c @@ -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" Index: clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- clang/lib/Sema/SemaDeclAttr.cpp +++ clang/lib/Sema/SemaDeclAttr.cpp @@ -4915,6 +4915,25 @@ 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 @@ 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); Index: clang/lib/CodeGen/CodeGenFunction.cpp =================================================================== --- clang/lib/CodeGen/CodeGenFunction.cpp +++ clang/lib/CodeGen/CodeGenFunction.cpp @@ -799,8 +799,8 @@ 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 @@ "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. Index: clang/include/clang/Basic/AttrDocs.td =================================================================== --- clang/include/clang/Basic/AttrDocs.td +++ clang/include/clang/Basic/AttrDocs.td @@ -3988,6 +3988,18 @@ }]; } +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 = [{ Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -683,6 +683,15 @@ 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>;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits