Skip to content

Commit 5d1fe1a

Browse files
committed
[Driver][CodeGen] Support -fpatchable-function-entry=N,M and __attribute__((patchable_function_entry(N,M))) where M>0
Reviewed By: nickdesaulniers Differential Revision: https://reviews.llvm.org/D73072 (cherry picked from commit 69bf40c)
1 parent 6f4edc6 commit 5d1fe1a

File tree

12 files changed

+49
-25
lines changed

12 files changed

+49
-25
lines changed

clang/include/clang/Basic/AttrDocs.td

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3995,8 +3995,6 @@ def PatchableFunctionEntryDocs : Documentation {
39953995
before the function entry and N-M NOPs after the function entry. This attribute
39963996
takes precedence over the command line option ``-fpatchable-function-entry=N,M``.
39973997
``M`` defaults to 0 if omitted.
3998-
3999-
Currently, only M=0 is supported.
40003998
}];
40013999
}
40024000

clang/include/clang/Basic/CodeGenOptions.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ CODEGENOPT(XRayAlwaysEmitTypedEvents , 1, 0)
111111
VALUE_CODEGENOPT(XRayInstructionThreshold , 32, 200)
112112

113113
VALUE_CODEGENOPT(PatchableFunctionEntryCount , 32, 0) ///< Number of NOPs at function entry
114+
VALUE_CODEGENOPT(PatchableFunctionEntryOffset , 32, 0)
114115

115116
CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled.
116117
CODEGENOPT(CallFEntry , 1, 0) ///< Set when -mfentry is enabled.

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ def err_drv_unsupported_indirect_jump_opt : Error<
408408
def err_drv_unknown_indirect_jump_opt : Error<
409409
"unknown '-mindirect-jump=' option '%0'">;
410410
def err_drv_unsupported_fpatchable_function_entry_argument : Error<
411-
"the second argument of '-fpatchable-function-entry' must be 0 or omitted">;
411+
"the second argument of '-fpatchable-function-entry' must be smaller than the first argument">;
412412

413413
def warn_drv_unable_to_find_directory_expected : Warning<
414414
"unable to find %0 directory, expected to be in '%1'">,

clang/include/clang/Driver/CC1Options.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,9 @@ def fsanitize_coverage_no_prune
372372
def fsanitize_coverage_stack_depth
373373
: Flag<["-"], "fsanitize-coverage-stack-depth">,
374374
HelpText<"Enable max stack depth tracing">;
375+
def fpatchable_function_entry_offset_EQ
376+
: Joined<["-"], "fpatchable-function-entry-offset=">, MetaVarName<"<M>">,
377+
HelpText<"Generate M NOPs before function entry">;
375378
def fprofile_instrument_EQ : Joined<["-"], "fprofile-instrument=">,
376379
HelpText<"Enable PGO instrumentation. The accepted value is clang, llvm, "
377380
"or none">, Values<"none,clang,llvm">;

clang/include/clang/Driver/Options.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1707,7 +1707,7 @@ def fno_max_type_align : Flag<["-"], "fno-max-type-align">, Group<f_Group>;
17071707
def fpascal_strings : Flag<["-"], "fpascal-strings">, Group<f_Group>, Flags<[CC1Option]>,
17081708
HelpText<"Recognize and construct Pascal-style string literals">;
17091709
def fpatchable_function_entry_EQ : Joined<["-"], "fpatchable-function-entry=">, Group<f_Group>, Flags<[CC1Option]>,
1710-
HelpText<"Generate N NOPs at function entry">;
1710+
MetaVarName<"<N,M>">, HelpText<"Generate M NOPs before function entry and N-M NOPs after function entry">;
17111711
def fpcc_struct_return : Flag<["-"], "fpcc-struct-return">, Group<f_Group>, Flags<[CC1Option]>,
17121712
HelpText<"Override the default ABI to return all structs on the stack">;
17131713
def fpch_preprocess : Flag<["-"], "fpch-preprocess">, Group<f_Group>;

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -820,13 +820,18 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
820820
llvm::itostr(CGM.getCodeGenOpts().XRayInstructionThreshold));
821821
}
822822

823+
unsigned Count, Offset;
823824
if (const auto *Attr = D->getAttr<PatchableFunctionEntryAttr>()) {
824-
// Attr->getStart is currently ignored.
825-
Fn->addFnAttr("patchable-function-entry",
826-
std::to_string(Attr->getCount()));
827-
} else if (unsigned Count = CGM.getCodeGenOpts().PatchableFunctionEntryCount) {
828-
Fn->addFnAttr("patchable-function-entry",
829-
std::to_string(Count));
825+
Count = Attr->getCount();
826+
Offset = Attr->getOffset();
827+
} else {
828+
Count = CGM.getCodeGenOpts().PatchableFunctionEntryCount;
829+
Offset = CGM.getCodeGenOpts().PatchableFunctionEntryOffset;
830+
}
831+
if (Count && Offset <= Count) {
832+
Fn->addFnAttr("patchable-function-entry", std::to_string(Count - Offset));
833+
if (Offset)
834+
Fn->addFnAttr("patchable-function-prefix", std::to_string(Offset));
830835
}
831836
}
832837

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5077,20 +5077,23 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
50775077

50785078
if (Arg *A = Args.getLastArg(options::OPT_fpatchable_function_entry_EQ)) {
50795079
StringRef S0 = A->getValue(), S = S0;
5080-
unsigned Size, Start = 0;
5080+
unsigned Size, Offset = 0;
50815081
if (!Triple.isAArch64() && Triple.getArch() != llvm::Triple::x86 &&
50825082
Triple.getArch() != llvm::Triple::x86_64)
50835083
D.Diag(diag::err_drv_unsupported_opt_for_target)
50845084
<< A->getAsString(Args) << TripleStr;
50855085
else if (S.consumeInteger(10, Size) ||
50865086
(!S.empty() && (!S.consume_front(",") ||
5087-
S.consumeInteger(10, Start) || !S.empty())))
5087+
S.consumeInteger(10, Offset) || !S.empty())))
50885088
D.Diag(diag::err_drv_invalid_argument_to_option)
50895089
<< S0 << A->getOption().getName();
5090-
else if (Start)
5090+
else if (Size < Offset)
50915091
D.Diag(diag::err_drv_unsupported_fpatchable_function_entry_argument);
5092-
else
5092+
else {
50935093
CmdArgs.push_back(Args.MakeArgString(A->getSpelling() + Twine(Size)));
5094+
CmdArgs.push_back(Args.MakeArgString(
5095+
"-fpatchable-function-entry-offset=" + Twine(Offset)));
5096+
}
50945097
}
50955098

50965099
if (TC.SupportsProfiling()) {

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,6 +1103,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
11031103

11041104
Opts.PatchableFunctionEntryCount =
11051105
getLastArgIntValue(Args, OPT_fpatchable_function_entry_EQ, 0, Diags);
1106+
Opts.PatchableFunctionEntryOffset = getLastArgIntValue(
1107+
Args, OPT_fpatchable_function_entry_offset_EQ, 0, Diags);
11061108
Opts.InstrumentForProfiling = Args.hasArg(OPT_pg);
11071109
Opts.CallFEntry = Args.hasArg(OPT_mfentry);
11081110
Opts.MNopMCount = Args.hasArg(OPT_mnop_mcount);

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4924,9 +4924,9 @@ static void handlePatchableFunctionEntryAttr(Sema &S, Decl *D,
49244924
Expr *Arg = AL.getArgAsExpr(1);
49254925
if (!checkUInt32Argument(S, AL, Arg, Offset, 1, true))
49264926
return;
4927-
if (Offset) {
4927+
if (Count < Offset) {
49284928
S.Diag(getAttrLoc(AL), diag::err_attribute_argument_out_of_range)
4929-
<< &AL << 0 << 0 << Arg->getBeginLoc();
4929+
<< &AL << 0 << Count << Arg->getBeginLoc();
49304930
return;
49314931
}
49324932
}

clang/test/CodeGen/patchable-function-entry.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,20 @@ __attribute__((patchable_function_entry(2, 0))) void f20() {}
1717
__attribute__((patchable_function_entry(2, 0))) void f20decl();
1818
void f20decl() {}
1919

20-
// OPT: define void @f() #2
20+
// CHECK: define void @f44() #2
21+
__attribute__((patchable_function_entry(4, 4))) void f44() {}
22+
23+
// CHECK: define void @f52() #3
24+
__attribute__((patchable_function_entry(5, 2))) void f52() {}
25+
26+
// OPT: define void @f() #4
2127
void f() {}
2228

23-
/// M in patchable_function_entry(N,M) is currently ignored.
24-
// CHECK: attributes #0 = { {{.*}} "patchable-function-entry"="0"
29+
/// No need to emit "patchable-function-entry"="0"
30+
// CHECK: attributes #0 = { {{.*}}
31+
// CHECK-NOT: "patchable-function-entry"
32+
2533
// CHECK: attributes #1 = { {{.*}} "patchable-function-entry"="2"
26-
// OPT: attributes #2 = { {{.*}} "patchable-function-entry"="1"
34+
// CHECK: attributes #2 = { {{.*}} "patchable-function-entry"="0" "patchable-function-prefix"="4"
35+
// CHECK: attributes #3 = { {{.*}} "patchable-function-entry"="3" "patchable-function-prefix"="2"
36+
// OPT: attributes #4 = { {{.*}} "patchable-function-entry"="1"

0 commit comments

Comments
 (0)