choikwa updated this revision to Diff 114388.
choikwa added a comment.

renamed and moved Cache to SourceLocToFileNameMap in CodeGenModule


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.cpp
  lib/CodeGen/CodeGenModule.h
  lib/Driver/ToolChains/Clang.cpp
  lib/Frontend/CompilerInvocation.cpp
  test/CodeGen/instrument-functions.c

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
@@ -771,6 +771,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
@@ -3519,7 +3519,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,
@@ -1201,6 +1204,9 @@
   /// \param QT is the clang QualType of the null pointer.
   llvm::Constant *getNullPointer(llvm::PointerType *T, QualType QT);
 
+  /// Get SourceLoc to FileName map cache
+  llvm::DenseMap<unsigned, const char*> &GetSourceLocToFileNameMap();
+
 private:
   llvm::Constant *GetOrCreateLLVMFunction(
       StringRef MangledName, llvm::Type *Ty, GlobalDecl D, bool ForVTable,
Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -4595,3 +4595,8 @@
                                 "__translate_sampler_initializer"),
                                 {C});
 }
+
+llvm::DenseMap<unsigned, const char*> &
+CodeGenModule::GetSourceLocToFileNameMap() {
+  return SourceLocToFileNameMap;
+}
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -1762,7 +1762,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.
@@ -413,13 +414,81 @@
   }
 }
 
+#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(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 !defined(_MSC_VER)
+  if (ActualFuncDecl && !ActualFuncDecl->isExternC()) {
+    int Status = 0;
+    char *Result = __cxa_demangle(FunctionName.begin(), 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 (const auto &FuncMatch : FunctionSearch) {
+    if(FunctionName.find(FuncMatch) != std::string::npos) {
+      return false;
+    }
+  }
+
   return true;
 }
 
@@ -920,7 +989,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
@@ -1007,8 +1007,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
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to