[prev in list] [next in list] [prev in thread] [next in thread]
List: cfe-commits
Subject: [PATCH] D37624: add support for -fno-instrument-functions and -finstrument-functions-exclude-{file,
From: kchoi via Phabricator via cfe-commits <cfe-commits () lists ! llvm ! org>
Date: 2017-09-30 21:34:57
Message-ID: c5f7d4f143b8fbe34763c8c4f9638b99 () localhost ! localdomain
[Download RAW message or body]
choikwa updated this revision to Diff 117264.
choikwa added a comment.
Addressing Hal's feedback
https://reviews.llvm.org/D37624
Files:
docs/ClangCommandLineReference.rst
include/clang/Driver/Options.td
include/clang/Frontend/CodeGenOptions.h
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenFunction.h
lib/CodeGen/CodeGenModule.h
lib/Driver/ToolChains/Clang.cpp
lib/Frontend/CompilerInvocation.cpp
test/CodeGen/instrument-functions.c
test/CodeGenCXX/instrument-functions.cpp
["D37624.117264.patch" (text/x-patch)]
Index: test/CodeGenCXX/instrument-functions.cpp
===================================================================
--- test/CodeGenCXX/instrument-functions.cpp
+++ test/CodeGenCXX/instrument-functions.cpp
@@ -1,10 +1,28 @@
// RUN: %clang_cc1 -S -emit-llvm -triple %itanium_abi_triple -o - %s \
-finstrument-functions | FileCheck %s
+// RUN: %clang -S -emit-llvm -o - %s -finstrument-functions | FileCheck %s
+// RUN: %clang -S -emit-llvm -o - %s -fno-instrument-functions | FileCheck %s \
--check-prefix=NOINSTR +
+// RUN: %clang -S -emit-llvm -o - %s -finstrument-functions \
-finstrument-functions-exclude-file-list=instrument | FileCheck %s \
--check-prefix=NOFILE +// RUN: %clang -S -emit-llvm -o - %s -finstrument-functions \
-finstrument-functions-exclude-function-list=test3 | FileCheck %s \
--check-prefix=NOFUNC +
// CHECK: @_Z5test1i
+// NOINSTR: @_Z5test1i
+// NOFILE: @_Z5test1i
+// NOFUNC: @_Z5test1i
int test1(int x) {
// CHECK: __cyg_profile_func_enter
// CHECK: __cyg_profile_func_exit
// CHECK: ret
+// NOINSTR-NOT: __cyg_profile_func_enter
+// NOINSTR-NOT: __cyg_profile_func_exit
+// NOINSTR: ret
+// NOFILE-NOT: __cyg_profile_func_enter
+// NOFILE-NOT: __cyg_profile_func_exit
+// NOFILE: ret
+// NOFUNC: __cyg_profile_func_enter
+// NOFUNC: __cyg_profile_func_exit
+// NOFUNC: ret
return x;
}
@@ -17,6 +35,26 @@
return x;
}
+// CHECK: @_Z5test3i
+// NOINSTR: @_Z5test3i
+// NOFILE: @_Z5test3i
+// NOFUNC: @_Z5test3i
+int test3(int x){
+// CHECK: __cyg_profile_func_enter
+// CHECK: __cyg_profile_func_exit
+// CHECK: ret
+// NOINSTR-NOT: __cyg_profile_func_enter
+// NOINSTR-NOT: __cyg_profile_func_exit
+// NOINSTR: ret
+// NOFILE-NOT: __cyg_profile_func_enter
+// NOFILE-NOT: __cyg_profile_func_exit
+// NOFILE: ret
+// NOFUNC-NOT: __cyg_profile_func_enter
+// NOFUNC-NOT: __cyg_profile_func_exit
+// NOFUNC: ret
+ return x;
+}
+
// This test case previously crashed code generation. It exists solely
// to test -finstrument-function does not crash codegen for this trivial
// case.
Index: test/CodeGen/instrument-functions.c
===================================================================
--- test/CodeGen/instrument-functions.c
+++ test/CodeGen/instrument-functions.c
@@ -1,18 +1,66 @@
-// RUN: %clang_cc1 -S -debug-info-kind=standalone -emit-llvm -o - %s \
-finstrument-functions | FileCheck %s +// RUN: %clang -S -emit-llvm -o - %s \
-finstrument-functions | FileCheck %s +// RUN: %clang -S -emit-llvm -o - %s \
-fno-instrument-functions | FileCheck %s --check-prefix=NOINSTR +
+// RUN: %clang -S -emit-llvm -o - %s -finstrument-functions \
-finstrument-functions-exclude-file-list=instrument | FileCheck %s \
--check-prefix=NOFILE +// RUN: %clang -S -emit-llvm -o - %s -finstrument-functions \
-finstrument-functions-exclude-function-list=test3 | FileCheck %s \
--check-prefix=NOFUNC
// CHECK: @test1
+// NOINSTR: @test1
+// NOFILE: @test1
+// NOFUNC: @test1
int test1(int x) {
-// CHECK: call void @__cyg_profile_func_enter({{.*}}, !dbg
-// CHECK: call void @__cyg_profile_func_exit({{.*}}, !dbg
+// CHECK: __cyg_profile_func_enter
+// CHECK: __cyg_profile_func_exit
// CHECK: ret
+// NOINSTR-NOT: __cyg_profile_func_enter
+// NOINSTR-NOT: __cyg_profile_func_exit
+// NOINSTR: ret
+// NOFILE-NOT: __cyg_profile_func_enter
+// NOFILE-NOT: __cyg_profile_func_exit
+// NOFILE: ret
+// NOFUNC: __cyg_profile_func_enter
+// NOFUNC: __cyg_profile_func_exit
+// NOFUNC: ret
return x;
}
// CHECK: @test2
+// NOINSTR: @test2
+// NOFILE: @test2
+// NOFUNC: @test2
int test2(int) __attribute__((no_instrument_function));
int test2(int x) {
// CHECK-NOT: __cyg_profile_func_enter
// CHECK-NOT: __cyg_profile_func_exit
// CHECK: ret
+// NOINSTR-NOT: __cyg_profile_func_enter
+// NOINSTR-NOT: __cyg_profile_func_exit
+// NOINSTR: ret
+// NOFILE-NOT: __cyg_profile_func_enter
+// NOFILE-NOT: __cyg_profile_func_exit
+// NOFILE: ret
+// NOFUNC-NOT: __cyg_profile_func_enter
+// NOFUNC-NOT: __cyg_profile_func_exit
+// NOFUNC: ret
+ return x;
+}
+
+// CHECK: @test3
+// NOINSTR: @test3
+// NOFILE: @test3
+// NOFUNC: @test3
+int test3(int x) {
+// CHECK: __cyg_profile_func_enter
+// CHECK: __cyg_profile_func_exit
+// CHECK: ret
+// NOINSTR-NOT: __cyg_profile_func_enter
+// NOINSTR-NOT: __cyg_profile_func_exit
+// NOINSTR: ret
+// NOFILE-NOT: __cyg_profile_func_enter
+// NOFILE-NOT: __cyg_profile_func_exit
+// NOFILE: ret
+// NOFUNC-NOT: __cyg_profile_func_enter
+// NOFUNC-NOT: __cyg_profile_func_exit
+// NOFUNC: ret
return x;
}
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -773,6 +773,12 @@
Opts.PreserveVec3Type = Args.hasArg(OPT_fpreserve_vec3_type);
Opts.InstrumentFunctions = Args.hasArg(OPT_finstrument_functions);
+ if (Opts.InstrumentFunctions) {
+ Opts.InstrumentFunctionExclusionsFunctions
+ = Args.getAllArgValues(OPT_finstrument_functions_exclude_function_list);
+ Opts.InstrumentFunctionExclusionsPathSegments
+ = Args.getAllArgValues(OPT_finstrument_functions_exclude_file_list);
+ }
Opts.XRayInstrumentFunctions = Args.hasArg(OPT_fxray_instrument);
Opts.XRayInstructionThreshold =
getLastArgIntValue(Args, OPT_fxray_instruction_threshold_EQ, 200, Diags);
Index: lib/Driver/ToolChains/Clang.cpp
===================================================================
--- lib/Driver/ToolChains/Clang.cpp
+++ lib/Driver/ToolChains/Clang.cpp
@@ -3535,7 +3535,14 @@
options::OPT_fno_unique_section_names, true))
CmdArgs.push_back("-fno-unique-section-names");
- Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions);
+ if (Args.hasArg(options::OPT_finstrument_functions,
+ options::OPT_fno_instrument_functions, false)) {
+ Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions);
+ Args.AddAllArgs(CmdArgs,
+ options::OPT_finstrument_functions_exclude_file_list);
+ Args.AddAllArgs(CmdArgs,
+ options::OPT_finstrument_functions_exclude_function_list);
+ }
addPGOAndCoverageFlags(C, D, Output, Args, CmdArgs);
Index: lib/CodeGen/CodeGenModule.h
===================================================================
--- lib/CodeGen/CodeGenModule.h
+++ lib/CodeGen/CodeGenModule.h
@@ -499,6 +499,9 @@
/// MDNodes.
llvm::DenseMap<QualType, llvm::Metadata *> MetadataIdMap;
+ /// Mapping from SourceLocation to PresumedLoc FileName
+ llvm::DenseMap<unsigned, const char*> SourceLocToFileNameMap;
+
public:
CodeGenModule(ASTContext &C, const HeaderSearchOptions &headersearchopts,
const PreprocessorOptions &ppopts,
@@ -1205,6 +1208,11 @@
/// \param QT is the clang QualType of the null pointer.
llvm::Constant *getNullPointer(llvm::PointerType *T, QualType QT);
+ /// Get SourceLoc to FileName map cache
+ inline llvm::DenseMap<unsigned, const char*> &GetSourceLocToFileNameMap() {
+ return SourceLocToFileNameMap;
+ }
+
private:
llvm::Constant *GetOrCreateLLVMFunction(
StringRef MangledName, llvm::Type *Ty, GlobalDecl D, bool ForVTable,
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -1763,7 +1763,7 @@
/// ShouldInstrumentFunction - Return true if the current function should be
/// instrumented with __cyg_profile_func_* calls
- bool ShouldInstrumentFunction();
+ bool ShouldInstrumentFunction(const llvm::Function *Fn);
/// ShouldXRayInstrument - Return true if the current function should be
/// instrumented with XRay nop sleds.
Index: lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- lib/CodeGen/CodeGenFunction.cpp
+++ lib/CodeGen/CodeGenFunction.cpp
@@ -36,6 +36,7 @@
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Operator.h"
+#include "llvm/ADT/DenseMap.h"
using namespace clang;
using namespace CodeGen;
@@ -344,7 +345,7 @@
// Emit function epilog (to return).
llvm::DebugLoc Loc = EmitReturnBlock();
- if (ShouldInstrumentFunction())
+ if (ShouldInstrumentFunction(CurFn))
EmitFunctionInstrumentation("__cyg_profile_func_exit");
// Emit debug descriptor for function end.
@@ -415,11 +416,64 @@
/// ShouldInstrumentFunction - Return true if the current function should be
/// instrumented with __cyg_profile_func_* calls
-bool CodeGenFunction::ShouldInstrumentFunction() {
+bool CodeGenFunction::ShouldInstrumentFunction(const llvm::Function *Fn) {
if (!CGM.getCodeGenOpts().InstrumentFunctions)
return false;
if (!CurFuncDecl || CurFuncDecl->hasAttr<NoInstrumentFunctionAttr>())
return false;
+
+ // Inline functions that are not externally visible mustn't be instrumented.
+ // They create a named reference to the inlined function, as the first
+ // parameter to __cyg_profile_* functions, which a linker will never be able
+ // to resolve.
+ const auto *ActualFuncDecl = dyn_cast<FunctionDecl>(CurFuncDecl);
+ if (ActualFuncDecl &&
+ ActualFuncDecl->isInlined() &&
+ !ActualFuncDecl->isInlineDefinitionExternallyVisible()) {
+ return false;
+ }
+
+ SourceLocation SLoc = CurFuncDecl->getLocation();
+
+
+ if (SLoc.isFileID()) {
+ unsigned Key = SLoc.getRawEncoding();
+ auto &Cache = CGM.GetSourceLocToFileNameMap();
+ if (Cache.find(Key) == Cache.end()) {
+ const ASTContext &CTX = CurFuncDecl->getASTContext();
+ const SourceManager &SM = CTX.getSourceManager();
+
+ PresumedLoc PLoc = SM.getPresumedLoc(SLoc);
+ Cache[Key] = PLoc.getFilename();
+ }
+ std::string FunctionDeclPath = Cache[Key];
+
+ const std::vector<std::string> &PathSearch =
+ CGM.getCodeGenOpts().InstrumentFunctionExclusionsPathSegments;
+
+ for (const auto &FileMatch : PathSearch) {
+ if(FunctionDeclPath.find(FileMatch) != std::string::npos) {
+ return false;
+ }
+ }
+ }
+
+ StringRef FunctionName(Fn->getName());
+
+ // Skip demangling if decl is extern "C"
+ if (ActualFuncDecl && !ActualFuncDecl->isExternC()) {
+ FunctionName = StringRef(PredefinedExpr::ComputeName(
+ PredefinedExpr::PrettyFunctionNoVirtual, CurFuncDecl));
+ }
+
+ const std::vector<std::string> &FunctionSearch =
+ CGM.getCodeGenOpts().InstrumentFunctionExclusionsFunctions;
+ for (const auto &FuncMatch : FunctionSearch) {
+ if(FunctionName.find(FuncMatch) != std::string::npos) {
+ return false;
+ }
+ }
+
return true;
}
@@ -971,7 +1025,7 @@
DI->EmitFunctionStart(GD, Loc, StartLoc, FnType, CurFn, Builder);
}
- if (ShouldInstrumentFunction())
+ if (ShouldInstrumentFunction(CurFn))
EmitFunctionInstrumentation("__cyg_profile_func_enter");
// Since emitting the mcount call here impacts optimizations such as function
Index: include/clang/Frontend/CodeGenOptions.h
===================================================================
--- include/clang/Frontend/CodeGenOptions.h
+++ include/clang/Frontend/CodeGenOptions.h
@@ -182,6 +182,12 @@
/// A list of dependent libraries.
std::vector<std::string> DependentLibraries;
+ /// Functions to exclude from function instrumentation.
+ std::vector<std::string> InstrumentFunctionExclusionsFunctions;
+
+ /// Path segments to exclude from function instrumentation, eg, '/bits'
+ std::vector<std::string> InstrumentFunctionExclusionsPathSegments;
+
/// A list of linker options to embed in the object file.
std::vector<std::string> LinkerOptions;
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -1010,8 +1010,17 @@
HelpText<"Enables an experimental new pass manager in LLVM.">;
def finput_charset_EQ : Joined<["-"], "finput-charset=">, Group<f_Group>;
def fexec_charset_EQ : Joined<["-"], "fexec-charset=">, Group<f_Group>;
+
+def finstrument_functions_exclude_function_list : CommaJoined<["-"],
+ "finstrument-functions-exclude-function-list=">, Group<f_Group>, \
Flags<[CC1Option]>, + HelpText<"Exclude given (demangled, if C++) functions from \
function instrumentation.">; +def finstrument_functions_exclude_file_list : \
CommaJoined<["-"], + "finstrument-functions-exclude-file-list=">, Group<f_Group>, \
Flags<[CC1Option]>, + HelpText<"Exclude given path segments from function \
instrumentation.">; def finstrument_functions : Flag<["-"], \
"finstrument-functions">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Generate \
calls to instrument function entry and exit">; +def fno_instrument_functions : \
Flag<["-"], "fno-instrument-functions">, Group<f_Group>, + HelpText<"Don't generate \
calls to instrument function entry and exit">;
def fxray_instrument : Flag<["-"], "fxray-instrument">, Group<f_Group>,
Flags<[CC1Option]>,
Index: docs/ClangCommandLineReference.rst
===================================================================
--- docs/ClangCommandLineReference.rst
+++ docs/ClangCommandLineReference.rst
@@ -1341,7 +1341,7 @@
.. option:: -finput-charset=<arg>
-.. option:: -finstrument-functions
+.. option:: -finstrument-functions, -fno-instrument-functions, \
-finstrument-functions-exclude-file-list=<arg>, \
-finstrument-functions-exclude-function-list=<arg>
Generate calls to instrument function entry and exit
[Attachment #4 (text/plain)]
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic