Wire up the -ftest-coverage and -fprofile-arcs flags to .gcno file emission (at
compile time) and .gcda emission (at runtime). --coverage enables both.

This does not yet add the profile_rt library to the link step if -fprofile-arcs
is enabled when linking.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129956 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 3457a20..0c2a077 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -135,6 +135,10 @@
   HelpText<"Place each data in its own section (ELF Only)">;
 def funroll_loops : Flag<"-funroll-loops">,
   HelpText<"Turn on loop unroller">;
+def femit_coverage_notes : Flag<"-femit-coverage-notes">,
+  HelpText<"Emit a gcov coverage notes file when compiling.">;
+def femit_coverage_data: Flag<"-femit-coverage-data">,
+  HelpText<"Instrument the program to emit gcov coverage data when run.">;
 def relaxed_aliasing : Flag<"-relaxed-aliasing">,
   HelpText<"Turn off Type Based Alias Analysis">;
 def masm_verbose : Flag<"-masm-verbose">,
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index ed891c0..542728f 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -423,6 +423,7 @@
 def ftemplate_depth_ : Joined<"-ftemplate-depth-">, Group<f_Group>;
 def ftemplate_backtrace_limit_EQ : Joined<"-ftemplate-backtrace-limit=">,
                                    Group<f_Group>;
+def ftest_coverage : Flag<"-ftest-coverage">, Group<f_Group>;
 def Wlarge_by_value_copy_def : Flag<"-Wlarge-by-value-copy">;
 def Wlarge_by_value_copy_EQ : Joined<"-Wlarge-by-value-copy=">;
 
diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h
index 60a6398..cede010 100644
--- a/include/clang/Frontend/CodeGenOptions.h
+++ b/include/clang/Frontend/CodeGenOptions.h
@@ -52,6 +52,8 @@
                                   /// Decl* various IR entities came from.  Only
                                   /// useful when running CodeGen as a
                                   /// subroutine.
+  unsigned EmitGcovArcs      : 1; /// Emit coverage data files, aka. GCDA.
+  unsigned EmitGcovNotes     : 1; /// Emit coverage "notes" files, aka GCNO.
   unsigned ForbidGuardVariables : 1; /// Issue errors if C++ guard variables
                                   /// are required
   unsigned FunctionSections  : 1; /// Set when -ffunction-sections is enabled
@@ -135,6 +137,8 @@
     DisableLLVMOpts = 0;
     DisableRedZone = 0;
     EmitDeclMetadata = 0;
+    EmitGcovArcs = 0;
+    EmitGcovNotes = 0;
     ForbidGuardVariables = 0;
     FunctionSections = 0;
     HiddenWeakTemplateVTables = 0;
diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp
index f3d79cb..9bd4bfd 100644
--- a/lib/CodeGen/BackendUtil.cpp
+++ b/lib/CodeGen/BackendUtil.cpp
@@ -30,6 +30,7 @@
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetOptions.h"
 #include "llvm/Target/TargetRegistry.h"
+#include "llvm/Transforms/Instrumentation.h"
 using namespace clang;
 using namespace llvm;
 
@@ -152,6 +153,13 @@
     TLI->disableAllFunctions();
   MPM->add(TLI);
 
+  if (CodeGenOpts.EmitGcovArcs || CodeGenOpts.EmitGcovNotes) {
+    MPM->add(createGCOVProfilerPass(CodeGenOpts.EmitGcovNotes,
+                                    CodeGenOpts.EmitGcovArcs));
+    if (!CodeGenOpts.DebugInfo)
+      MPM->add(createStripSymbolsPass(true));
+  }
+
   // For now we always create per module passes.
   llvm::createStandardModulePasses(MPM, OptLevel,
                                    CodeGenOpts.OptimizeSize,
diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt
index 0a51b85..80e46d2 100644
--- a/lib/CodeGen/CMakeLists.txt
+++ b/lib/CodeGen/CMakeLists.txt
@@ -2,6 +2,7 @@
   asmparser
   bitreader
   bitwriter
+  instrumentation
   ipo
   )
 
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 603e8c1..e73a0cf 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -64,7 +64,7 @@
     ABI(createCXXABI(*this)), 
     Types(C, M, TD, getTargetCodeGenInfo().getABIInfo(), ABI),
     TBAA(0),
-    VTables(*this), Runtime(0),
+    VTables(*this), Runtime(0), DebugInfo(0),
     CFConstantStringClassRef(0), ConstantStringClassRef(0),
     VMContext(M.getContext()),
     NSConcreteGlobalBlockDecl(0), NSConcreteStackBlockDecl(0),
@@ -80,8 +80,11 @@
     TBAA = new CodeGenTBAA(Context, VMContext, getLangOptions(),
                            ABI.getMangleContext());
 
-  // If debug info generation is enabled, create the CGDebugInfo object.
-  DebugInfo = CodeGenOpts.DebugInfo ? new CGDebugInfo(*this) : 0;
+  // If debug info or coverage generation is enabled, create the CGDebugInfo
+  // object.
+  if (CodeGenOpts.DebugInfo || CodeGenOpts.EmitGcovArcs ||
+      CodeGenOpts.EmitGcovNotes)
+    DebugInfo = new CGDebugInfo(*this);
 
   Block.GlobalUniqueCount = 0;
 
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 7cc1059..c1f7e15 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -1277,6 +1277,13 @@
 
   Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions);
 
+  if (Args.hasArg(options::OPT_ftest_coverage) ||
+      Args.hasArg(options::OPT_coverage))
+    CmdArgs.push_back("-femit-coverage-notes");
+  if (Args.hasArg(options::OPT_fprofile_arcs) ||
+      Args.hasArg(options::OPT_coverage))
+    CmdArgs.push_back("-femit-coverage-data");
+
   Args.AddLastArg(CmdArgs, options::OPT_nostdinc);
   Args.AddLastArg(CmdArgs, options::OPT_nostdincxx);
   Args.AddLastArg(CmdArgs, options::OPT_nobuiltininc);
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index bf863d7..5449df2 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -123,6 +123,10 @@
     Res.push_back("-dwarf-debug-flags");
     Res.push_back(Opts.DwarfDebugFlags);
   }
+  if (Opts.EmitGcovArcs)
+    Res.push_back("-femit-coverage-data");
+  if (Opts.EmitGcovNotes)
+    Res.push_back("-femit-coverage-notes");
   if (!Opts.MergeAllConstants)
     Res.push_back("-fno-merge-all-constants");
   if (Opts.NoCommon)
@@ -960,6 +964,8 @@
 
   Opts.InstrumentFunctions = Args.hasArg(OPT_finstrument_functions);
   Opts.InstrumentForProfiling = Args.hasArg(OPT_pg);
+  Opts.EmitGcovArcs = Args.hasArg(OPT_femit_coverage_data);
+  Opts.EmitGcovNotes = Args.hasArg(OPT_femit_coverage_notes);
 
   if (Arg *A = Args.getLastArg(OPT_fobjc_dispatch_method_EQ)) {
     llvm::StringRef Name = A->getValue(Args);
diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt
index 552e7a5..0c41490 100644
--- a/tools/driver/CMakeLists.txt
+++ b/tools/driver/CMakeLists.txt
@@ -23,6 +23,7 @@
   bitreader
   bitwriter
   codegen
+  instrumentation
   ipo
   selectiondag
   )
diff --git a/tools/driver/Makefile b/tools/driver/Makefile
index d96f950..abe7098 100644
--- a/tools/driver/Makefile
+++ b/tools/driver/Makefile
@@ -36,7 +36,7 @@
 include $(CLANG_LEVEL)/../../Makefile.config
 
 LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader bitwriter codegen \
-                   ipo selectiondag
+                   instrumentation ipo selectiondag
 USEDLIBS = clangFrontendTool.a clangFrontend.a clangDriver.a \
            clangSerialization.a clangCodeGen.a clangParse.a clangSema.a \
            clangStaticAnalyzerFrontend.a clangStaticAnalyzerCheckers.a \