[cfe-dev] Why hasn't patch for -finstrument-functions-exclude-file-list support been merged?
Gonzalo BG
gonzalobg88 at gmail.com
Tue Nov 12 09:01:42 PST 2013
>
> Maybe you can try to pick up the patch?
I can try but i've never messed with a compiler before so please consider
that I have no idea of what I'm doing and need some guidance.
First, I compiled ToT llvm/clang and applied the patch. There are 4 new
tests in the patch. Everything passes. I tried a small example using the
"-finstrument-exclude-file-list" feature and it works as expected.
In the original mailings:
http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20130311/075910.html
some
issues were raised.
+ // 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.
> + if (const FunctionDecl *ActualFuncDecl =
> + dyn_cast<FunctionDecl>(CurFuncDecl)) {
> + if (ActualFuncDecl->isInlined() &&
> + !ActualFuncDecl->isInlineDefinitionExternallyVisible())
> + return false;
> + }
> This seems like a separable, ready-to-commit bug fix.
>
I've re-submitted Matthews original patch.
std::set is pretty heavyweight, and isn't buying us anything. I think just
> having one large string to search would be best. Comma probably isn't the
> best separator character; embedded NULLs or something non-ASCII would be
> better.
I replaced std::set<std::string> with a std::vector<std::string>.
Rationale: 1) we get a std::vector<string> as input anyways, 2) using a
string with a delimiter is more complicated, 3) in particular NULLs,
because some string algorithms like find stop at the first NULL. I looked
in the docs but wasn't able to find algorithms for working with this type
of data structure (
http://llvm.org/docs/ProgrammersManual.html#string-like-containers). Please
point me to them in case I miss them. Otherwise, I don't think is worth it
to implement them for this case.
If Fn->isExternC(), there's no point in demangling. Let's save ourselves
> the work in that case.
How can I call isExternC()? Fn is of type llvm::Function but I've only been
able to find clang::FunctionDecl::isExternC().
Our correctness did not depend on host's cxa_demangle before... There's
> also a fixme in compiler_rt about shipping our own cxa_demangle in order
> not to leak memory (it is used inside sanitizers, so it has special
> requirements about allocating memory).
Is there another better demangle function I should call instead? Or what
should be done about this?
I didn't see anything to handle escaped commas in the input, which GCC's
> documentation mentions.
Can you give me hints about what to look for in the docs to be able to
implement this? I haven't been able to find anything about dealing with
escaped commas or characters.H
I suggest that we look through macro expansions to find the FileID where
> the expansion occurred, then check that. Also, can we cache the result of
> this lookup based on the FileID? There are a lot of string searches we're
> potentially doing here, many of which will be redundant.
What is the best way to do this? I've added a std::map for the caching but
don't know if this is the preferred solution. Any hints are welcome.
Bests,
Gonzalo
On Tue, Nov 12, 2013 at 5:38 AM, Nico Weber <thakis at chromium.org> wrote:
> It looks like the patch stalled in review. This is the last message on the
> thread:
> http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20130311/075917.html("I will look at these issues with the patch and work on resolving them"
> and then nothing). Maybe you can try to pick up the patch?
>
>
> On Mon, Nov 11, 2013 at 11:24 AM, Gonzalo BG <gonzalobg88 at gmail.com>wrote:
>
>> Hi,
>>
>> I'm trying to use "-finstrument-functions" in an application and this
>> feature seems to work fine.
>>
>> However, I can't exclude the standard library from getting instrumented.
>> This means I cannot use any std library function in the
>> "__cyg_profile_func_enter" and "__cyg_profile_func_exit" call backs. This
>> is severely limiting.
>>
>> GCC defines "-finstrument-functions-exclude-file-list=file,file,..." (see
>> http://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html) which allows
>> you to exclude instrumentation of some files (e.g. the std library
>> headers!). Someone filled a bug report and submitted a patch in march but
>> it hasn't been merged yet: http://llvm.org/bugs/show_bug.cgi?id=15255 .
>>
>> Anyone knows the reason? If I'm not able to exclude the standard library
>> I can't use instrumentation in my application.
>>
>> Bests,
>> Gonzalo
>>
>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20131112/f73fa6d1/attachment.html>
-------------- next part --------------
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td (revision 194458)
+++ include/clang/Driver/Options.td (working copy)
@@ -535,6 +535,12 @@
def findirect_virtual_calls : Flag<["-"], "findirect-virtual-calls">, Alias<fapple_kext>;
def finline_functions : Flag<["-"], "finline-functions">, Group<clang_ignored_f_Group>;
def finline : Flag<["-"], "finline">, Group<clang_ignored_f_Group>;
+def finstrument_functions_exclude_function_list : CommaJoined<["-"],
+ "finstrument-functions-exclude-function-list=">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Exclude given (mangled, 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 fkeep_inline_functions : Flag<["-"], "fkeep-inline-functions">, Group<clang_ignored_f_Group>;
Index: include/clang/Frontend/CodeGenOptions.h
===================================================================
--- include/clang/Frontend/CodeGenOptions.h (revision 194458)
+++ include/clang/Frontend/CodeGenOptions.h (working copy)
@@ -131,6 +131,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;
+
public:
// Define accessors/mutators for code generation options of enumeration type.
#define CODEGENOPT(Name, Bits, Default)
Index: lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- lib/CodeGen/CodeGenFunction.cpp (revision 194458)
+++ lib/CodeGen/CodeGenFunction.cpp (working copy)
@@ -29,6 +29,7 @@
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Operator.h"
+#include <map>
using namespace clang;
using namespace CodeGen;
@@ -232,7 +233,7 @@
// Emit function epilog (to return).
EmitReturnBlock();
- if (ShouldInstrumentFunction())
+ if (ShouldInstrumentFunction(CurFn))
EmitFunctionInstrumentation("__cyg_profile_func_exit");
// Emit debug descriptor for function end.
@@ -277,13 +278,77 @@
EmitDeclMetadata();
}
+#if !defined(_MSC_VER)
+// Assume that __cxa_demangle is provided by libcxxabi (except for Windows).
+extern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer,
+ size_t *length, int *status);
+#endif
+
/// ShouldInstrumentFunction - Return true if the current function should be
/// instrumented with __cyg_profile_func_* calls
-bool CodeGenFunction::ShouldInstrumentFunction() {
+bool CodeGenFunction::ShouldInstrumentFunction(llvm::Function *Fn) {
+ typedef std::vector<std::string>::const_iterator CIt;
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.
+ if (const FunctionDecl *ActualFuncDecl =
+ dyn_cast<FunctionDecl>(CurFuncDecl)) {
+ if (ActualFuncDecl->isInlined() &&
+ !ActualFuncDecl->isInlineDefinitionExternallyVisible())
+ return false;
+ }
+
+ SourceLocation SLoc = CurFuncDecl->getLocation();
+ static std::map<SourceLocation, std::string> cache;
+
+ if (SLoc.isFileID()) {
+ if (cache.find(SLoc) == cache.end()) {
+ ASTContext &ctx = CurFuncDecl->getASTContext();
+ const SourceManager &SM = ctx.getSourceManager();
+
+ PresumedLoc PLoc = SM.getPresumedLoc(SLoc);
+ cache[SLoc] = PLoc.getFilename();
+ }
+ std::string FunctionDeclPath = cache[SLoc];
+
+ const std::vector<std::string> &PathSearch =
+ CGM.getCodeGenOpts().InstrumentFunctionExclusionsPathSegments;
+
+ for (CIt i = PathSearch.begin(), e = PathSearch.end(); i != e; ++i) {
+ if(FunctionDeclPath.find(*i) != std::string::npos) {
+ return false;
+ }
+ }
+ }
+
+ // Demangle the name if it's mangled
+ std::string FunctionName = Fn->getName();
+#if !defined(_MSC_VER)
+ int status = 0;
+ char *result = __cxa_demangle(FunctionName.c_str(), 0, 0, &status);
+
+ assert((status == 0 || status == -2) && "Couldn't demangle name.");
+
+ if (status == 0) {
+ FunctionName = result;
+ free(result);
+ }
+#endif
+
+ const std::vector<std::string> &FunctionSearch =
+ CGM.getCodeGenOpts().InstrumentFunctionExclusionsFunctions;
+ for (CIt i = FunctionSearch.begin(), e = FunctionSearch.end(); i != e; ++i) {
+ if(FunctionName.find(*i) != std::string::npos) {
+ return false;
+ }
+ }
+
return true;
}
@@ -567,7 +632,7 @@
DI->EmitFunctionStart(GD, FnType, CurFn, Builder);
}
- if (ShouldInstrumentFunction())
+ if (ShouldInstrumentFunction(CurFn))
EmitFunctionInstrumentation("__cyg_profile_func_enter");
if (CGM.getCodeGenOpts().InstrumentForProfiling)
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h (revision 194458)
+++ lib/CodeGen/CodeGenFunction.h (working copy)
@@ -1202,7 +1202,7 @@
/// ShouldInstrumentFunction - Return true if the current function should be
/// instrumented with __cyg_profile_func_* calls
- bool ShouldInstrumentFunction();
+ bool ShouldInstrumentFunction(llvm::Function *Fn);
/// EmitFunctionInstrumentation - Emit LLVM code to call the specified
/// instrumentation function with the current function and the call site, if
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp (revision 194458)
+++ lib/Driver/Tools.cpp (working copy)
@@ -2620,6 +2620,12 @@
Args.AddAllArgs(CmdArgs, options::OPT_fdata_sections);
Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions);
+ if (Args.hasArg(options::OPT_finstrument_functions)) {
+ Args.AddAllArgs(CmdArgs,
+ options::OPT_finstrument_functions_exclude_file_list);
+ Args.AddAllArgs(CmdArgs,
+ options::OPT_finstrument_functions_exclude_function_list);
+ }
if (Args.hasArg(options::OPT_ftest_coverage) ||
Args.hasArg(options::OPT_coverage))
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp (revision 194458)
+++ lib/Frontend/CompilerInvocation.cpp (working copy)
@@ -432,6 +432,13 @@
}
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.InstrumentForProfiling = Args.hasArg(OPT_pg);
Opts.EmitOpenCLArgMetadata = Args.hasArg(OPT_cl_kernel_arg_info);
Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
More information about the cfe-dev
mailing list