diff --git a/clang/docs/ClangCommandLineReference.rst b/clang/docs/ClangCommandLineReference.rst --- a/clang/docs/ClangCommandLineReference.rst +++ b/clang/docs/ClangCommandLineReference.rst @@ -1917,6 +1917,14 @@ Like -finstrument-functions, but insert the calls after inlining +.. option:: -finstrument-functions-exclude-file-list= + +Exclude from instrumentation any function pulled in from the specified path(s) + +.. option:: -finstrument-functions-exclude-function-list= + +Exclude from instrumentation the specified function(s) + .. option:: -fintegrated-as, -fno-integrated-as, -integrated-as Enable the integrated assembler diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -426,6 +426,12 @@ /// values in order to be included in misexpect diagnostics. Optional DiagnosticsMisExpectTolerance = 0; + /// List of functions excluded from function instrumentation. + std::vector InstrumentFunctionsExcludedFunctions; + + /// List of paths containing excluded function definitions. + std::vector InstrumentFunctionsExcludedPaths; + public: // Define accessors/mutators for code generation options of enumeration type. #define CODEGENOPT(Name, Bits, Default) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2010,6 +2010,13 @@ def finstrument_function_entry_bare : Flag<["-"], "finstrument-function-entry-bare">, Group, Flags<[CC1Option]>, HelpText<"Instrument function entry only, after inlining, without arguments to the instrumentation call">, MarshallingInfoFlag>; +def finstrument_functions_exclude_function_list : CommaJoined<["-"], + "finstrument-functions-exclude-function-list=">, Group, Flags<[CC1Option]>, + HelpText<"Exclude the listed functions from function instrumentation.">, + MarshallingInfoStringVector>; +def finstrument_functions_exclude_file_list : CommaJoined<["-"], + "finstrument-functions-exclude-file-list=">, Group, Flags<[CC1Option]>, + HelpText<"Exclude the functions defined in the given files from function instrumentation.">; def fcf_protection_EQ : Joined<["-"], "fcf-protection=">, Flags<[CoreOption, CC1Option]>, Group, HelpText<"Instrument control-flow architecture protection">, Values<"return,branch,full,none">; def fcf_protection : Flag<["-"], "fcf-protection">, Group, Flags<[CoreOption, CC1Option]>, diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2338,7 +2338,7 @@ /// ShouldInstrumentFunction - Return true if the current function should be /// instrumented with __cyg_profile_func_* calls - bool ShouldInstrumentFunction(); + bool ShouldInstrumentFunction(llvm::Function *F); /// ShouldSkipSanitizerInstrumentation - Return true if the current function /// should not be instrumented with sanitizers. diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -375,7 +375,7 @@ // Emit function epilog (to return). llvm::DebugLoc Loc = EmitReturnBlock(); - if (ShouldInstrumentFunction()) { + if (ShouldInstrumentFunction(CurFn)) { if (CGM.getCodeGenOpts().InstrumentFunctions) CurFn->addFnAttr("instrument-function-exit", "__cyg_profile_func_exit"); if (CGM.getCodeGenOpts().InstrumentFunctionsAfterInlining) @@ -521,13 +521,40 @@ /// ShouldInstrumentFunction - Return true if the current function should be /// instrumented with __cyg_profile_func_* calls -bool CodeGenFunction::ShouldInstrumentFunction() { +bool CodeGenFunction::ShouldInstrumentFunction(llvm::Function *F) { if (!CGM.getCodeGenOpts().InstrumentFunctions && !CGM.getCodeGenOpts().InstrumentFunctionsAfterInlining && !CGM.getCodeGenOpts().InstrumentFunctionEntryBare) return false; if (!CurFuncDecl || CurFuncDecl->hasAttr()) return false; + + // Downcast to a function declaration and check to see if the current function + // is inlined. If it is inlined but not externally-visible, then don't + // generate tracing for it: at link-time, the function will be gone and the + // first argument to the __cyg_profile_* function will be unresolvable. + const FunctionDecl *FDecl = dyn_cast(CurFuncDecl); + if (FDecl && + FDecl->isInlined() && + !FDecl->isInlineDefinitionExternallyVisible()) + return false; + + typedef std::vector::const_iterator ExcludedFunctionIterator; + + // The list of excluded function name substrings specified on the command-line + // is searched to see if any of them is a substring of our (current) function + // name. + const std::vector &ExcludedFunctions = + CGM.getCodeGenOpts().InstrumentFunctionsExcludedFunctions; + + std::string FName(F->getName()); + for (ExcludedFunctionIterator ExcludedFunction = ExcludedFunctions.begin(), + Sentinel = ExcludedFunctions.end(); + ExcludedFunction != Sentinel; ++ExcludedFunction) { + if (FName.find(*ExcludedFunction) != std::string::npos) + return false; + } + return true; } @@ -1018,7 +1045,7 @@ CurFuncIsThunk); } - if (ShouldInstrumentFunction()) { + if (ShouldInstrumentFunction(CurFn)) { if (CGM.getCodeGenOpts().InstrumentFunctions) CurFn->addFnAttr("instrument-function-entry", "__cyg_profile_func_enter"); if (CGM.getCodeGenOpts().InstrumentFunctionsAfterInlining) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5628,6 +5628,8 @@ Args.AddLastArg(CmdArgs, options::OPT_finstrument_functions, options::OPT_finstrument_functions_after_inlining, options::OPT_finstrument_function_entry_bare); + Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions_exclude_function_list); + Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions_exclude_file_list); // NVPTX/AMDGCN doesn't support PGO or coverage. There's no runtime support // for sampling, overhead of call arc collection is way too high and there's