r214752 - Add coverage mapping generation.

Alex Lorenz arphaman at gmail.com
Mon Aug 4 11:41:51 PDT 2014


Author: arphaman
Date: Mon Aug  4 13:41:51 2014
New Revision: 214752

URL: http://llvm.org/viewvc/llvm-project?rev=214752&view=rev
Log:
Add coverage mapping generation.

This patch adds the '-fcoverage-mapping' option which
allows clang to generate the coverage mapping information
that can be used to provide code coverage analysis using
the execution counts obtained from the instrumentation 
based profiling (-fprofile-instr-generate).

Added:
    cfe/trunk/lib/CodeGen/CoverageMappingGen.cpp
    cfe/trunk/lib/CodeGen/CoverageMappingGen.h
Modified:
    cfe/trunk/include/clang/CodeGen/CodeGenABITypes.h
    cfe/trunk/include/clang/CodeGen/ModuleBuilder.h
    cfe/trunk/include/clang/Driver/Options.td
    cfe/trunk/include/clang/Frontend/CodeGenOptions.def
    cfe/trunk/lib/CodeGen/CodeGenABITypes.cpp
    cfe/trunk/lib/CodeGen/CodeGenAction.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    cfe/trunk/lib/CodeGen/CodeGenPGO.cpp
    cfe/trunk/lib/CodeGen/CodeGenPGO.h
    cfe/trunk/lib/CodeGen/ModuleBuilder.cpp
    cfe/trunk/lib/Driver/Tools.cpp
    cfe/trunk/lib/Frontend/CompilerInvocation.cpp

Modified: cfe/trunk/include/clang/CodeGen/CodeGenABITypes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/CodeGen/CodeGenABITypes.h?rev=214752&r1=214751&r2=214752&view=diff
==============================================================================
--- cfe/trunk/include/clang/CodeGen/CodeGenABITypes.h (original)
+++ cfe/trunk/include/clang/CodeGen/CodeGenABITypes.h Mon Aug  4 13:41:51 2014
@@ -39,6 +39,7 @@ class CXXRecordDecl;
 class CodeGenOptions;
 class DiagnosticsEngine;
 class ObjCMethodDecl;
+class CoverageSourceInfo;
 
 namespace CodeGen {
 class CGFunctionInfo;
@@ -47,7 +48,8 @@ class CodeGenModule;
 class CodeGenABITypes
 {
 public:
-  CodeGenABITypes(ASTContext &C, llvm::Module &M, const llvm::DataLayout &TD);
+  CodeGenABITypes(ASTContext &C, llvm::Module &M, const llvm::DataLayout &TD,
+                  CoverageSourceInfo *CoverageInfo = nullptr);
   ~CodeGenABITypes();
 
   /// These methods all forward to methods in the private implementation class

Modified: cfe/trunk/include/clang/CodeGen/ModuleBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/CodeGen/ModuleBuilder.h?rev=214752&r1=214751&r2=214752&view=diff
==============================================================================
--- cfe/trunk/include/clang/CodeGen/ModuleBuilder.h (original)
+++ cfe/trunk/include/clang/CodeGen/ModuleBuilder.h Mon Aug  4 13:41:51 2014
@@ -24,6 +24,7 @@ namespace llvm {
 
 namespace clang {
   class DiagnosticsEngine;
+  class CoverageSourceInfo;
   class LangOptions;
   class CodeGenOptions;
   class TargetOptions;
@@ -44,7 +45,8 @@ namespace clang {
                                    const std::string &ModuleName,
                                    const CodeGenOptions &CGO,
                                    const TargetOptions &TO,
-                                   llvm::LLVMContext& C);
+                                   llvm::LLVMContext& C,
+                                   CoverageSourceInfo *CoverageInfo = nullptr);
 }
 
 #endif

Modified: cfe/trunk/include/clang/Driver/Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=214752&r1=214751&r2=214752&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Options.td (original)
+++ cfe/trunk/include/clang/Driver/Options.td Mon Aug  4 13:41:51 2014
@@ -408,6 +408,9 @@ def fprofile_instr_use : Flag<["-"], "fp
 def fprofile_instr_use_EQ : Joined<["-"], "fprofile-instr-use=">,
     Group<f_Group>, Flags<[CC1Option]>,
     HelpText<"Use instrumentation data for profile-guided optimization">;
+def fcoverage_mapping : Flag<["-"], "fcoverage-mapping">,
+    Group<f_Group>, Flags<[CC1Option]>,
+    HelpText<"Generate coverage mapping to enable code coverage analysis">;
 
 def fblocks : Flag<["-"], "fblocks">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Enable the 'blocks' language feature">;

Modified: cfe/trunk/include/clang/Frontend/CodeGenOptions.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/CodeGenOptions.def?rev=214752&r1=214751&r2=214752&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/CodeGenOptions.def (original)
+++ cfe/trunk/include/clang/Frontend/CodeGenOptions.def Mon Aug  4 13:41:51 2014
@@ -88,6 +88,8 @@ VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///
 
 CODEGENOPT(ProfileInstrGenerate , 1, 0) ///< Instrument code to generate
                                         ///< execution counts to use with PGO.
+CODEGENOPT(CoverageMapping , 1, 0) ///< Generate coverage mapping regions to
+                                   ///< enable code coverage analysis.
 
   /// If -fpcc-struct-return or -freg-struct-return is specified.
 ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default)

Modified: cfe/trunk/lib/CodeGen/CodeGenABITypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenABITypes.cpp?rev=214752&r1=214751&r2=214752&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenABITypes.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenABITypes.cpp Mon Aug  4 13:41:51 2014
@@ -26,9 +26,11 @@ using namespace CodeGen;
 
 CodeGenABITypes::CodeGenABITypes(ASTContext &C,
                                  llvm::Module &M,
-                                 const llvm::DataLayout &TD)
+                                 const llvm::DataLayout &TD,
+                                 CoverageSourceInfo *CoverageInfo)
   : CGO(new CodeGenOptions),
-    CGM(new CodeGen::CodeGenModule(C, *CGO, M, TD, C.getDiagnostics())) {
+    CGM(new CodeGen::CodeGenModule(C, *CGO, M, TD, C.getDiagnostics(),
+                                   CoverageInfo)) {
 }
 
 CodeGenABITypes::~CodeGenABITypes()

Modified: cfe/trunk/lib/CodeGen/CodeGenAction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenAction.cpp?rev=214752&r1=214751&r2=214752&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenAction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenAction.cpp Mon Aug  4 13:41:51 2014
@@ -7,6 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "CoverageMappingGen.h"
 #include "clang/CodeGen/CodeGenAction.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
@@ -15,6 +16,7 @@
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/Preprocessor.h"
 #include "clang/CodeGen/BackendUtil.h"
 #include "clang/CodeGen/ModuleBuilder.h"
 #include "clang/Frontend/CompilerInstance.h"
@@ -59,11 +61,13 @@ namespace clang {
                     const TargetOptions &targetopts,
                     const LangOptions &langopts, bool TimePasses,
                     const std::string &infile, llvm::Module *LinkModule,
-                    raw_ostream *OS, LLVMContext &C)
+                    raw_ostream *OS, LLVMContext &C,
+                    CoverageSourceInfo *CoverageInfo = nullptr)
         : Diags(_Diags), Action(action), CodeGenOpts(compopts),
           TargetOpts(targetopts), LangOpts(langopts), AsmOutStream(OS),
           Context(), LLVMIRGeneration("LLVM IR Generation Time"),
-          Gen(CreateLLVMCodeGen(Diags, infile, compopts, targetopts, C)),
+          Gen(CreateLLVMCodeGen(Diags, infile, compopts,
+                                targetopts, C, CoverageInfo)),
           LinkModule(LinkModule) {
       llvm::TimePassesIsEnabled = TimePasses;
     }
@@ -636,10 +640,17 @@ ASTConsumer *CodeGenAction::CreateASTCon
     LinkModuleToUse = ModuleOrErr.get();
   }
 
+  CoverageSourceInfo *CoverageInfo = nullptr;
+  // Add the preprocessor callback only when the coverage mapping is generated.
+  if (CI.getCodeGenOpts().CoverageMapping) {
+    CoverageInfo = new CoverageSourceInfo;
+    CI.getPreprocessor().addPPCallbacks(CoverageInfo);
+  }
   BEConsumer = new BackendConsumer(BA, CI.getDiagnostics(), CI.getCodeGenOpts(),
                                    CI.getTargetOpts(), CI.getLangOpts(),
                                    CI.getFrontendOpts().ShowTimers, InFile,
-                                   LinkModuleToUse, OS.release(), *VMContext);
+                                   LinkModuleToUse, OS.release(), *VMContext,
+                                   CoverageInfo);
   return BEConsumer;
 }
 

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=214752&r1=214751&r2=214752&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Mon Aug  4 13:41:51 2014
@@ -829,6 +829,7 @@ void CodeGenFunction::GenerateCode(Globa
   StartFunction(GD, ResTy, Fn, FnInfo, Args, Loc, BodyRange.getBegin());
 
   // Generate the body of the function.
+  PGO.checkGlobalDecl(GD);
   PGO.assignRegionCounters(GD.getDecl(), CurFn);
   if (isa<CXXDestructorDecl>(FD))
     EmitDestructorBody(Args);

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=214752&r1=214751&r2=214752&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Mon Aug  4 13:41:51 2014
@@ -21,6 +21,7 @@
 #include "CGOpenMPRuntime.h"
 #include "CodeGenFunction.h"
 #include "CodeGenPGO.h"
+#include "CoverageMappingGen.h"
 #include "CodeGenTBAA.h"
 #include "TargetInfo.h"
 #include "clang/AST/ASTContext.h"
@@ -74,7 +75,8 @@ static CGCXXABI *createCXXABI(CodeGenMod
 
 CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
                              llvm::Module &M, const llvm::DataLayout &TD,
-                             DiagnosticsEngine &diags)
+                             DiagnosticsEngine &diags,
+                             CoverageSourceInfo *CoverageInfo)
     : Context(C), LangOpts(C.getLangOpts()), CodeGenOpts(CGO), TheModule(M),
       Diags(diags), TheDataLayout(TD), Target(C.getTargetInfo()),
       ABI(createCXXABI(*this)), VMContext(M.getContext()), TBAA(nullptr),
@@ -146,6 +148,11 @@ CodeGenModule::CodeGenModule(ASTContext
       getDiags().Report(DiagID) << EC.message();
     }
   }
+
+  // If coverage mapping generation is enabled, create the
+  // CoverageMappingModuleGen object.
+  if (CodeGenOpts.CoverageMapping)
+    CoverageMapping.reset(new CoverageMappingModuleGen(*this, *CoverageInfo));
 }
 
 CodeGenModule::~CodeGenModule() {
@@ -344,6 +351,9 @@ void CodeGenModule::Release() {
   EmitCtorList(GlobalDtors, "llvm.global_dtors");
   EmitGlobalAnnotations();
   EmitStaticExternCAliases();
+  EmitDeferredUnusedCoverageMappings();
+  if (CoverageMapping)
+    CoverageMapping->emit();
   emitLLVMUsed();
 
   if (CodeGenOpts.Autolink &&
@@ -2989,6 +2999,9 @@ void CodeGenModule::EmitTopLevelDecl(Dec
       return;
 
     EmitGlobal(cast<FunctionDecl>(D));
+    // Always provide some coverage mapping
+    // even for the functions that aren't emitted.
+    AddDeferredUnusedCoverageMapping(D);
     break;
 
   case Decl::Var:
@@ -3138,6 +3151,80 @@ void CodeGenModule::EmitTopLevelDecl(Dec
   }
 }
 
+void CodeGenModule::AddDeferredUnusedCoverageMapping(Decl *D) {
+  // Do we need to generate coverage mapping?
+  if (!CodeGenOpts.CoverageMapping)
+    return;
+  switch (D->getKind()) {
+  case Decl::CXXConversion:
+  case Decl::CXXMethod:
+  case Decl::Function:
+  case Decl::ObjCMethod:
+  case Decl::CXXConstructor:
+  case Decl::CXXDestructor: {
+    if (!cast<FunctionDecl>(D)->hasBody())
+      return;
+    auto I = DeferredEmptyCoverageMappingDecls.find(D);
+    if (I == DeferredEmptyCoverageMappingDecls.end())
+      DeferredEmptyCoverageMappingDecls[D] = true;
+    break;
+  }
+  default:
+    break;
+  };
+}
+
+void CodeGenModule::ClearUnusedCoverageMapping(const Decl *D) {
+  // Do we need to generate coverage mapping?
+  if (!CodeGenOpts.CoverageMapping)
+    return;
+  if (const auto *Fn = dyn_cast<FunctionDecl>(D)) {
+    if (Fn->isTemplateInstantiation())
+      ClearUnusedCoverageMapping(Fn->getTemplateInstantiationPattern());
+  }
+  auto I = DeferredEmptyCoverageMappingDecls.find(D);
+  if (I == DeferredEmptyCoverageMappingDecls.end())
+    DeferredEmptyCoverageMappingDecls[D] = false;
+  else
+    I->second = false;
+}
+
+void CodeGenModule::EmitDeferredUnusedCoverageMappings() {
+  for (const auto I : DeferredEmptyCoverageMappingDecls) {
+    if (!I.second)
+      continue;
+    const auto *D = I.first;
+    switch (D->getKind()) {
+    case Decl::CXXConversion:
+    case Decl::CXXMethod:
+    case Decl::Function:
+    case Decl::ObjCMethod: {
+      CodeGenPGO PGO(*this);
+      GlobalDecl GD(cast<FunctionDecl>(D));
+      PGO.emitEmptyCounterMapping(D, getMangledName(GD),
+                                  getFunctionLinkage(GD));
+      break;
+    }
+    case Decl::CXXConstructor: {
+      CodeGenPGO PGO(*this);
+      GlobalDecl GD(cast<CXXConstructorDecl>(D), Ctor_Base);
+      PGO.emitEmptyCounterMapping(D, getMangledName(GD),
+                                  getFunctionLinkage(GD));
+      break;
+    }
+    case Decl::CXXDestructor: {
+      CodeGenPGO PGO(*this);
+      GlobalDecl GD(cast<CXXDestructorDecl>(D), Dtor_Base);
+      PGO.emitEmptyCounterMapping(D, getMangledName(GD),
+                                  getFunctionLinkage(GD));
+      break;
+    }
+    default:
+      break;
+    };
+  }
+}
+
 /// Turns the given pointer into a constant.
 static llvm::Constant *GetPointerConstant(llvm::LLVMContext &Context,
                                           const void *Ptr) {

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=214752&r1=214751&r2=214752&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Mon Aug  4 13:41:51 2014
@@ -73,6 +73,7 @@ class DiagnosticsEngine;
 class AnnotateAttr;
 class CXXDestructorDecl;
 class Module;
+class CoverageSourceInfo;
 
 namespace CodeGen {
 
@@ -87,6 +88,7 @@ class CGOpenMPRuntime;
 class CGCUDARuntime;
 class BlockFieldFlags;
 class FunctionArgList;
+class CoverageMappingModuleGen;
 
 struct OrderGlobalInits {
   unsigned int priority;
@@ -477,10 +479,15 @@ class CodeGenModule : public CodeGenType
   std::unique_ptr<SanitizerMetadata> SanitizerMD;
 
   /// @}
+
+  llvm::DenseMap<const Decl *, bool> DeferredEmptyCoverageMappingDecls;
+
+  std::unique_ptr<CoverageMappingModuleGen> CoverageMapping;
 public:
   CodeGenModule(ASTContext &C, const CodeGenOptions &CodeGenOpts,
                 llvm::Module &M, const llvm::DataLayout &TD,
-                DiagnosticsEngine &Diags);
+                DiagnosticsEngine &Diags,
+                CoverageSourceInfo *CoverageInfo = nullptr);
 
   ~CodeGenModule();
 
@@ -529,6 +536,10 @@ public:
   InstrProfStats &getPGOStats() { return PGOStats; }
   llvm::IndexedInstrProfReader *getPGOReader() const { return PGOReader.get(); }
 
+  CoverageMappingModuleGen *getCoverageMapping() const {
+    return CoverageMapping.get();
+  }
+
   llvm::Constant *getStaticLocalDeclAddress(const VarDecl *D) {
     return StaticLocalDeclMap[D];
   }
@@ -815,6 +826,18 @@ public:
   /// Emit code for a single top level declaration.
   void EmitTopLevelDecl(Decl *D);
 
+  /// \brief Stored a deferred empty coverage mapping for an unused
+  /// and thus uninstrumented top level declaration.
+  void AddDeferredUnusedCoverageMapping(Decl *D);
+
+  /// \brief Remove the deferred empty coverage mapping as this
+  /// declaration is actually instrumented.
+  void ClearUnusedCoverageMapping(const Decl *D);
+
+  /// \brief Emit all the deferred coverage mappings
+  /// for the uninstrumented functions.
+  void EmitDeferredUnusedCoverageMappings();
+
   /// Tell the consumer that this variable has been instantiated.
   void HandleCXXStaticMemberVarInstantiation(VarDecl *VD);
 

Modified: cfe/trunk/lib/CodeGen/CodeGenPGO.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenPGO.cpp?rev=214752&r1=214751&r2=214752&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenPGO.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenPGO.cpp Mon Aug  4 13:41:51 2014
@@ -13,6 +13,7 @@
 
 #include "CodeGenPGO.h"
 #include "CodeGenFunction.h"
+#include "CoverageMappingGen.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/StmtVisitor.h"
 #include "llvm/IR/MDBuilder.h"
@@ -24,8 +25,9 @@
 using namespace clang;
 using namespace CodeGen;
 
-void CodeGenPGO::setFuncName(llvm::Function *Fn) {
-  RawFuncName = Fn->getName();
+void CodeGenPGO::setFuncName(StringRef Name,
+                             llvm::GlobalValue::LinkageTypes Linkage) {
+  RawFuncName = Name;
 
   // Function names may be prefixed with a binary '1' to indicate
   // that the backend should not modify the symbols due to any platform
@@ -33,7 +35,7 @@ void CodeGenPGO::setFuncName(llvm::Funct
   if (RawFuncName[0] == '\1')
     RawFuncName = RawFuncName.substr(1);
 
-  if (!Fn->hasLocalLinkage()) {
+  if (!llvm::GlobalValue::isLocalLinkage(Linkage)) {
     PrefixedFuncName.reset(new std::string(RawFuncName));
     return;
   }
@@ -49,6 +51,27 @@ void CodeGenPGO::setFuncName(llvm::Funct
   PrefixedFuncName->append(RawFuncName);
 }
 
+void CodeGenPGO::setFuncName(llvm::Function *Fn) {
+  setFuncName(Fn->getName(), Fn->getLinkage());
+}
+
+void CodeGenPGO::setVarLinkage(llvm::GlobalValue::LinkageTypes Linkage) {
+  // Set the linkage for variables based on the function linkage.  Usually, we
+  // want to match it, but available_externally and extern_weak both have the
+  // wrong semantics.
+  VarLinkage = Linkage;
+  switch (VarLinkage) {
+  case llvm::GlobalValue::ExternalWeakLinkage:
+    VarLinkage = llvm::GlobalValue::LinkOnceAnyLinkage;
+    break;
+  case llvm::GlobalValue::AvailableExternallyLinkage:
+    VarLinkage = llvm::GlobalValue::LinkOnceODRLinkage;
+    break;
+  default:
+    break;
+  }
+}
+
 static llvm::Function *getRegisterFunc(CodeGenModule &CGM) {
   return CGM.getModule().getFunction("__llvm_profile_register_functions");
 }
@@ -120,37 +143,48 @@ llvm::GlobalVariable *CodeGenPGO::buildD
   auto *Int64Ty = llvm::Type::getInt64Ty(Ctx);
   auto *Int8PtrTy = llvm::Type::getInt8PtrTy(Ctx);
   auto *Int64PtrTy = llvm::Type::getInt64PtrTy(Ctx);
-  llvm::Type *DataTypes[] = {
-    Int32Ty, Int32Ty, Int64Ty, Int8PtrTy, Int64PtrTy
-  };
-  auto *DataTy = llvm::StructType::get(Ctx, makeArrayRef(DataTypes));
-  llvm::Constant *DataVals[] = {
-    llvm::ConstantInt::get(Int32Ty, getFuncName().size()),
-    llvm::ConstantInt::get(Int32Ty, NumRegionCounters),
-    llvm::ConstantInt::get(Int64Ty, FunctionHash),
-    llvm::ConstantExpr::getBitCast(Name, Int8PtrTy),
-    llvm::ConstantExpr::getBitCast(RegionCounters, Int64PtrTy)
-  };
-  auto *Data =
-    new llvm::GlobalVariable(CGM.getModule(), DataTy, true, VarLinkage,
-                             llvm::ConstantStruct::get(DataTy, DataVals),
-                             getFuncVarName("data"));
-
-  // All the data should be packed into an array in its own section.
-  Data->setSection(getDataSection(CGM));
-  Data->setAlignment(8);
+  llvm::GlobalVariable *Data = nullptr;
+  if (RegionCounters) {
+    llvm::Type *DataTypes[] = {
+      Int32Ty, Int32Ty, Int64Ty, Int8PtrTy, Int64PtrTy
+    };
+    auto *DataTy = llvm::StructType::get(Ctx, makeArrayRef(DataTypes));
+    llvm::Constant *DataVals[] = {
+      llvm::ConstantInt::get(Int32Ty, getFuncName().size()),
+      llvm::ConstantInt::get(Int32Ty, NumRegionCounters),
+      llvm::ConstantInt::get(Int64Ty, FunctionHash),
+      llvm::ConstantExpr::getBitCast(Name, Int8PtrTy),
+      llvm::ConstantExpr::getBitCast(RegionCounters, Int64PtrTy)
+    };
+    Data =
+      new llvm::GlobalVariable(CGM.getModule(), DataTy, true, VarLinkage,
+                               llvm::ConstantStruct::get(DataTy, DataVals),
+                               getFuncVarName("data"));
+
+    // All the data should be packed into an array in its own section.
+    Data->setSection(getDataSection(CGM));
+    Data->setAlignment(8);
+  }
+
+  // Create coverage mapping data variable.
+  if (!CoverageMapping.empty())
+    CGM.getCoverageMapping()->addFunctionMappingRecord(Name,
+                                                       getFuncName().size(),
+                                                       CoverageMapping);
 
   // Hide all these symbols so that we correctly get a copy for each
   // executable.  The profile format expects names and counters to be
   // contiguous, so references into shared objects would be invalid.
   if (!llvm::GlobalValue::isLocalLinkage(VarLinkage)) {
     Name->setVisibility(llvm::GlobalValue::HiddenVisibility);
-    Data->setVisibility(llvm::GlobalValue::HiddenVisibility);
-    RegionCounters->setVisibility(llvm::GlobalValue::HiddenVisibility);
+    if (Data) {
+      Data->setVisibility(llvm::GlobalValue::HiddenVisibility);
+      RegionCounters->setVisibility(llvm::GlobalValue::HiddenVisibility);
+    }
   }
 
   // Make sure the data doesn't get deleted.
-  CGM.addUsedGlobal(Data);
+  if (Data) CGM.addUsedGlobal(Data);
   return Data;
 }
 
@@ -807,6 +841,20 @@ static void emitRuntimeHook(CodeGenModul
   CGM.addUsedGlobal(User);
 }
 
+void CodeGenPGO::checkGlobalDecl(GlobalDecl GD) {
+  // Make sure we only emit coverage mapping for one constructor/destructor.
+  // Clang emits several functions for the constructor and the destructor of
+  // a class. Every function is instrumented, but we only want to provide
+  // coverage for one of them. Because of that we only emit the coverage mapping
+  // for the base constructor/destructor.
+  if ((isa<CXXConstructorDecl>(GD.getDecl()) &&
+       GD.getCtorType() != Ctor_Base) ||
+      (isa<CXXDestructorDecl>(GD.getDecl()) &&
+       GD.getDtorType() != Dtor_Base)) {
+    SkipCoverageMapping = true;
+  }
+}
+
 void CodeGenPGO::assignRegionCounters(const Decl *D, llvm::Function *Fn) {
   bool InstrumentRegions = CGM.getCodeGenOpts().ProfileInstrGenerate;
   llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
@@ -814,27 +862,16 @@ void CodeGenPGO::assignRegionCounters(co
     return;
   if (D->isImplicit())
     return;
+  CGM.ClearUnusedCoverageMapping(D);
   setFuncName(Fn);
-
-  // Set the linkage for variables based on the function linkage.  Usually, we
-  // want to match it, but available_externally and extern_weak both have the
-  // wrong semantics.
-  VarLinkage = Fn->getLinkage();
-  switch (VarLinkage) {
-  case llvm::GlobalValue::ExternalWeakLinkage:
-    VarLinkage = llvm::GlobalValue::LinkOnceAnyLinkage;
-    break;
-  case llvm::GlobalValue::AvailableExternallyLinkage:
-    VarLinkage = llvm::GlobalValue::LinkOnceODRLinkage;
-    break;
-  default:
-    break;
-  }
+  setVarLinkage(Fn->getLinkage());
 
   mapRegionCounters(D);
   if (InstrumentRegions) {
     emitRuntimeHook(CGM);
     emitCounterVariables();
+    if (CGM.getCodeGenOpts().CoverageMapping)
+      emitCounterRegionMapping(D);
   }
   if (PGOReader) {
     SourceManager &SM = CGM.getContext().getSourceManager();
@@ -860,6 +897,45 @@ void CodeGenPGO::mapRegionCounters(const
   FunctionHash = Walker.Hash.finalize();
 }
 
+void CodeGenPGO::emitCounterRegionMapping(const Decl *D) {
+  if (SkipCoverageMapping)
+    return;
+  // Don't map the functions inside the system headers
+  auto Loc = D->getBody()->getLocStart();
+  if (CGM.getContext().getSourceManager().isInSystemHeader(Loc))
+    return;
+
+  llvm::raw_string_ostream OS(CoverageMapping);
+  CoverageMappingGen MappingGen(*CGM.getCoverageMapping(),
+                                CGM.getContext().getSourceManager(),
+                                CGM.getLangOpts(), RegionCounterMap.get(),
+                                NumRegionCounters);
+  MappingGen.emitCounterMapping(D, OS);
+  OS.flush();
+}
+
+void
+CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef FuncName,
+                                    llvm::GlobalValue::LinkageTypes Linkage) {
+  if (SkipCoverageMapping)
+    return;
+  setFuncName(FuncName, Linkage);
+  setVarLinkage(Linkage);
+
+  // Don't map the functions inside the system headers
+  auto Loc = D->getBody()->getLocStart();
+  if (CGM.getContext().getSourceManager().isInSystemHeader(Loc))
+    return;
+
+  llvm::raw_string_ostream OS(CoverageMapping);
+  CoverageMappingGen MappingGen(*CGM.getCoverageMapping(),
+                                CGM.getContext().getSourceManager(),
+                                CGM.getLangOpts());
+  MappingGen.emitEmptyMapping(D, OS);
+  OS.flush();
+  buildDataVar();
+}
+
 void CodeGenPGO::computeRegionCounts(const Decl *D) {
   StmtCountMap.reset(new llvm::DenseMap<const Stmt *, uint64_t>);
   ComputeRegionCounts Walker(*StmtCountMap, *this);

Modified: cfe/trunk/lib/CodeGen/CodeGenPGO.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenPGO.h?rev=214752&r1=214751&r2=214752&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenPGO.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenPGO.h Mon Aug  4 13:41:51 2014
@@ -42,11 +42,16 @@ private:
   std::unique_ptr<llvm::DenseMap<const Stmt *, uint64_t>> StmtCountMap;
   std::unique_ptr<std::vector<uint64_t>> RegionCounts;
   uint64_t CurrentRegionCount;
+  std::string CoverageMapping;
+  /// \brief A flag that is set to true when this function doesn't need
+  /// to have coverage mapping data.
+  bool SkipCoverageMapping;
 
 public:
   CodeGenPGO(CodeGenModule &CGM)
       : CGM(CGM), NumRegionCounters(0), FunctionHash(0),
-        RegionCounters(nullptr), CurrentRegionCount(0) {}
+        RegionCounters(nullptr), CurrentRegionCount(0),
+        SkipCoverageMapping(false) {}
 
   /// Whether or not we have PGO region data for the current function. This is
   /// false both when we have no data at all and when our data has been
@@ -99,6 +104,8 @@ public:
   llvm::MDNode *createBranchWeights(ArrayRef<uint64_t> Weights);
   llvm::MDNode *createLoopWeights(const Stmt *Cond, RegionCounter &Cnt);
 
+  /// Check if we need to emit coverage mapping for a given declaration
+  void checkGlobalDecl(GlobalDecl GD);
   /// Assign counters to regions and configure them for PGO of a given
   /// function. Does nothing if instrumentation is not enabled and either
   /// generates global variables or associates PGO data with each of the
@@ -111,9 +118,14 @@ public:
   void destroyRegionCounters();
   /// Emit static initialization code, if any.
   static llvm::Function *emitInitialization(CodeGenModule &CGM);
-
+  /// Emit a coverage mapping range with a counter zero
+  /// for an unused declaration.
+  void emitEmptyCounterMapping(const Decl *D, StringRef FuncName,
+                               llvm::GlobalValue::LinkageTypes Linkage);
 private:
   void setFuncName(llvm::Function *Fn);
+  void setFuncName(StringRef Name, llvm::GlobalValue::LinkageTypes Linkage);
+  void setVarLinkage(llvm::GlobalValue::LinkageTypes Linkage);
   void mapRegionCounters(const Decl *D);
   void computeRegionCounts(const Decl *D);
   void applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
@@ -122,6 +134,7 @@ private:
                         bool IsInMainFile);
   void emitCounterVariables();
   llvm::GlobalVariable *buildDataVar();
+  void emitCounterRegionMapping(const Decl *D);
 
   /// Emit code to increment the counter at the given index
   void emitCounterIncrement(CGBuilderTy &Builder, unsigned Counter);

Added: cfe/trunk/lib/CodeGen/CoverageMappingGen.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CoverageMappingGen.cpp?rev=214752&view=auto
==============================================================================
--- cfe/trunk/lib/CodeGen/CoverageMappingGen.cpp (added)
+++ cfe/trunk/lib/CodeGen/CoverageMappingGen.cpp Mon Aug  4 13:41:51 2014
@@ -0,0 +1,1166 @@
+//===--- CoverageMappingGen.cpp - Coverage mapping generation ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Instrumentation-based code coverage mapping generator
+//
+//===----------------------------------------------------------------------===//
+
+#include "CoverageMappingGen.h"
+#include "CodeGenFunction.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ProfileData/InstrProfReader.h"
+#include "llvm/ProfileData/CoverageMapping.h"
+#include "llvm/ProfileData/CoverageMappingWriter.h"
+#include "llvm/Support/FileSystem.h"
+
+using namespace clang;
+using namespace CodeGen;
+using namespace llvm::coverage;
+
+void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range) {
+  SkippedRanges.push_back(Range);
+}
+
+namespace {
+
+/// \brief A region of source code that can be mapped to a counter.
+struct SourceMappingRegion {
+  enum RegionFlags {
+    /// \brief This region won't be emitted if it wasn't extended.
+    /// This is useful so that we won't emit source ranges for single tokens
+    /// that we don't really care that much about, like:
+    ///   the '(' token in #define MACRO (
+    IgnoreIfNotExtended = 0x0001,
+  };
+
+  FileID File, MacroArgumentFile;
+
+  Counter Count;
+
+  /// \brief A statement that initiated the count of Zero.
+  ///
+  /// This initiator statement is useful to prevent merging of unreachable
+  /// regions with different statements that caused the counter to become
+  /// unreachable.
+  const Stmt *UnreachableInitiator;
+
+  /// \brief A statement that separates certain mapping regions into groups.
+  ///
+  /// The group statement is sometimes useful when we are emitting the source
+  /// regions not in their correct lexical order, e.g. the regions for the
+  /// incrementation expression in the 'for' construct. By marking the regions
+  /// in the incrementation expression with the group statement, we avoid the
+  /// merging of the regions from the incrementation expression and the loop's
+  /// body.
+  const Stmt *Group;
+
+  /// \brief The region's starting location.
+  SourceLocation LocStart;
+
+  /// \brief The region's ending location.
+  SourceLocation LocEnd, AlternativeLocEnd;
+  unsigned Flags;
+  CounterMappingRegion::RegionKind Kind;
+
+  SourceMappingRegion(FileID File, FileID MacroArgumentFile, Counter Count,
+                      const Stmt *UnreachableInitiator, const Stmt *Group,
+                      SourceLocation LocStart, SourceLocation LocEnd,
+                      unsigned Flags = 0,
+                      CounterMappingRegion::RegionKind Kind =
+                          CounterMappingRegion::CodeRegion)
+      : File(File), MacroArgumentFile(MacroArgumentFile), Count(Count),
+        UnreachableInitiator(UnreachableInitiator), Group(Group),
+        LocStart(LocStart), LocEnd(LocEnd), AlternativeLocEnd(LocStart),
+        Flags(Flags), Kind(Kind) {}
+
+  bool hasFlag(RegionFlags Flag) const { return (Flags & Flag) != 0; }
+
+  void setFlag(RegionFlags Flag) { Flags |= Flag; }
+
+  void clearFlag(RegionFlags Flag) { Flags &= ~Flag; }
+
+  /// \brief Return true if two regions can be merged together.
+  bool isMergeable(SourceMappingRegion &R) {
+    return File == R.File && MacroArgumentFile == R.MacroArgumentFile &&
+           Count == R.Count && UnreachableInitiator == R.UnreachableInitiator &&
+           Group == R.Group && Kind == R.Kind;
+  }
+
+  /// \brief Merge two regions by extending the 'this' region to cover the
+  /// given region.
+  void mergeByExtendingTo(SourceMappingRegion &R) {
+    LocEnd = R.LocEnd;
+    AlternativeLocEnd = R.LocStart;
+    if (hasFlag(IgnoreIfNotExtended))
+      clearFlag(IgnoreIfNotExtended);
+  }
+};
+
+/// \brief The state of the coverage mapping builder.
+struct SourceMappingState {
+  Counter CurrentRegionCount;
+  const Stmt *CurrentSourceGroup;
+  const Stmt *CurrentUnreachableRegionInitiator;
+
+  SourceMappingState(Counter CurrentRegionCount, const Stmt *CurrentSourceGroup,
+                     const Stmt *CurrentUnreachableRegionInitiator)
+      : CurrentRegionCount(CurrentRegionCount),
+        CurrentSourceGroup(CurrentSourceGroup),
+        CurrentUnreachableRegionInitiator(CurrentUnreachableRegionInitiator) {}
+};
+
+/// \brief Provides the common functionality for the different
+/// coverage mapping region builders.
+class CoverageMappingBuilder {
+public:
+  CoverageMappingModuleGen &CVM;
+  SourceManager &SM;
+  const LangOptions &LangOpts;
+
+private:
+  struct FileInfo {
+    /// \brief The file id that will be used by the coverage mapping system.
+    unsigned CovMappingFileID;
+    const FileEntry *Entry;
+
+    FileInfo(unsigned CovMappingFileID, const FileEntry *Entry)
+        : CovMappingFileID(CovMappingFileID), Entry(Entry) {}
+  };
+
+  /// \brief This mapping maps clang's FileIDs to file ids used
+  /// by the coverage mapping system and clang's file entries.
+  llvm::SmallDenseMap<FileID, FileInfo, 8> FileIDMapping;
+
+public:
+  /// \brief The statement that corresponds to the current source group.
+  const Stmt *CurrentSourceGroup;
+
+  /// \brief The statement the initiated the current unreachable region.
+  const Stmt *CurrentUnreachableRegionInitiator;
+
+  /// \brief The coverage mapping regions for this function
+  llvm::SmallVector<CounterMappingRegion, 32> MappingRegions;
+  /// \brief The source mapping regions for this function.
+  llvm::SmallVector<SourceMappingRegion, 32> SourceRegions;
+
+  CoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
+                         const LangOptions &LangOpts)
+      : CVM(CVM), SM(SM), LangOpts(LangOpts),
+        CurrentSourceGroup(nullptr),
+        CurrentUnreachableRegionInitiator(nullptr) {}
+
+  /// \brief Return the precise end location for the given token.
+  SourceLocation getPreciseTokenLocEnd(SourceLocation Loc) {
+    return Lexer::getLocForEndOfToken(SM.getSpellingLoc(Loc), 0, SM, LangOpts);
+  }
+
+  /// \brief Create the mapping that maps from the function's file ids to
+  /// the indices for the translation unit's filenames.
+  void createFileIDMapping(SmallVectorImpl<unsigned> &Mapping) {
+    Mapping.resize(FileIDMapping.size(), 0);
+    for (const auto &I : FileIDMapping)
+      Mapping[I.second.CovMappingFileID] = CVM.getFileID(I.second.Entry);
+  }
+
+  /// \brief Get the coverage mapping file id that corresponds to the given
+  /// clang file id. If such file id doesn't exist, it gets added to the
+  /// mapping that maps from clang's file ids to coverage mapping file ids.
+  /// Return true if there was an error getting the coverage mapping file id.
+  /// An example of an when this function fails is when the region tries
+  /// to get a coverage file id for a location in a built-in macro.
+  bool getCoverageFileID(SourceLocation LocStart, FileID File,
+                         FileID SpellingFile, unsigned &Result) {
+    auto Mapping = FileIDMapping.find(File);
+    if (Mapping != FileIDMapping.end()) {
+      Result = Mapping->second.CovMappingFileID;
+      return false;
+    }
+
+    auto Entry = SM.getFileEntryForID(SpellingFile);
+    if (!Entry)
+      return true;
+
+    Result = FileIDMapping.size();
+    FileIDMapping.insert(std::make_pair(File, FileInfo(Result, Entry)));
+    createFileExpansionRegion(LocStart, File);
+    return false;
+  }
+
+  /// \brief Get the coverage mapping file id that corresponds to the given
+  /// clang file id.
+  /// Return true if there was an error getting the coverage mapping file id.
+  bool getExistingCoverageFileID(FileID File, unsigned &Result) {
+    // Make sure that the file is valid.
+    if (File.isInvalid())
+      return true;
+    auto Mapping = FileIDMapping.find(File);
+    if (Mapping != FileIDMapping.end()) {
+      Result = Mapping->second.CovMappingFileID;
+      return false;
+    }
+    return true;
+  }
+
+  /// \brief Return true if the given clang's file id has a corresponding
+  /// coverage file id.
+  bool hasExistingCoverageFileID(FileID File) const {
+    return FileIDMapping.count(File);
+  }
+
+  /// \brief Gather all the regions that were skipped by the preprocessor
+  /// using the constructs like #if.
+  void gatherSkippedRegions() {
+    /// An array of the minimum lineStarts and the maximum lineEnds
+    /// for mapping regions from the appropriate source files.
+    llvm::SmallVector<std::pair<unsigned, unsigned>, 8> FileLineRanges;
+    FileLineRanges.resize(
+        FileIDMapping.size(),
+        std::make_pair(std::numeric_limits<unsigned>::max(), 0));
+    for (const auto &R : MappingRegions) {
+      FileLineRanges[R.FileID].first =
+          std::min(FileLineRanges[R.FileID].first, R.LineStart);
+      FileLineRanges[R.FileID].second =
+          std::max(FileLineRanges[R.FileID].second, R.LineEnd);
+    }
+
+    auto SkippedRanges = CVM.getSourceInfo().getSkippedRanges();
+    for (const auto &I : SkippedRanges) {
+      auto LocStart = I.getBegin();
+      auto LocEnd = I.getEnd();
+      auto FileStart = SM.getFileID(LocStart);
+      if (!hasExistingCoverageFileID(FileStart))
+        continue;
+      auto ActualFileStart = SM.getDecomposedSpellingLoc(LocStart).first;
+      if (ActualFileStart != SM.getDecomposedSpellingLoc(LocEnd).first)
+        // Ignore regions that span across multiple files.
+        continue;
+
+      unsigned CovFileID;
+      if (getCoverageFileID(LocStart, FileStart, ActualFileStart, CovFileID))
+        continue;
+      unsigned LineStart = SM.getSpellingLineNumber(LocStart);
+      unsigned ColumnStart = SM.getSpellingColumnNumber(LocStart);
+      unsigned LineEnd = SM.getSpellingLineNumber(LocEnd);
+      unsigned ColumnEnd = SM.getSpellingColumnNumber(LocEnd);
+      CounterMappingRegion Region(Counter(), CovFileID, LineStart, ColumnStart,
+                                  LineEnd, ColumnEnd, false,
+                                  CounterMappingRegion::SkippedRegion);
+      // Make sure that we only collect the regions that are inside
+      // the souce code of this function.
+      if (Region.LineStart >= FileLineRanges[CovFileID].first &&
+          Region.LineEnd <= FileLineRanges[CovFileID].second)
+        MappingRegions.push_back(Region);
+    }
+  }
+
+  /// \brief Create a mapping region that correponds to an expansion of
+  /// a macro or an embedded include.
+  void createFileExpansionRegion(SourceLocation Loc, FileID ExpandedFile) {
+    SourceLocation LocStart;
+    if (Loc.isMacroID())
+      LocStart = SM.getImmediateExpansionRange(Loc).first;
+    else {
+      LocStart = SM.getIncludeLoc(ExpandedFile);
+      if (LocStart.isInvalid())
+        return; // This file has no expansion region.
+    }
+
+    auto File = SM.getFileID(LocStart);
+    auto SpellingFile = SM.getDecomposedSpellingLoc(LocStart).first;
+    unsigned CovFileID, ExpandedFileID;
+    if (getExistingCoverageFileID(ExpandedFile, ExpandedFileID))
+      return;
+    if (getCoverageFileID(LocStart, File, SpellingFile, CovFileID))
+      return;
+    unsigned LineStart = SM.getSpellingLineNumber(LocStart);
+    unsigned ColumnStart = SM.getSpellingColumnNumber(LocStart);
+    unsigned LineEnd = LineStart;
+    // Compute the end column manually as Lexer::getLocForEndOfToken doesn't
+    // give the correct result in all cases.
+    unsigned ColumnEnd =
+        ColumnStart +
+        Lexer::MeasureTokenLength(SM.getSpellingLoc(LocStart), SM, LangOpts);
+
+    MappingRegions.push_back(CounterMappingRegion(
+        Counter(), CovFileID, LineStart, ColumnStart, LineEnd, ColumnEnd,
+        false, CounterMappingRegion::ExpansionRegion));
+    MappingRegions.back().ExpandedFileID = ExpandedFileID;
+  }
+
+  /// \brief Enter a source region group that is identified by the given
+  /// statement.
+  /// It's not possible to enter a group when there is already
+  /// another group present.
+  void beginSourceRegionGroup(const Stmt *Group) {
+    assert(!CurrentSourceGroup);
+    CurrentSourceGroup = Group;
+  }
+
+  /// \brief Exit the current source region group.
+  void endSourceRegionGroup() { CurrentSourceGroup = nullptr; }
+
+  /// \brief Brings a region that has the same counter and file to the back
+  /// of the source regions array.
+  void bringSimilarRegionBack(Counter Count, FileID File,
+                              FileID MacroArgumentFile,
+                              const Stmt *UnreachableInitiator,
+                              const Stmt *SourceGroup) {
+    for (size_t I = SourceRegions.size(); I != 0;) {
+      --I;
+      if (SourceRegions[I].Count == Count && SourceRegions[I].File == File &&
+          SourceRegions[I].MacroArgumentFile == MacroArgumentFile &&
+          SourceRegions[I].UnreachableInitiator == UnreachableInitiator &&
+          SourceRegions[I].Group == SourceGroup) {
+        if (I != SourceRegions.size() - 1)
+          std::swap(SourceRegions[I], SourceRegions.back());
+        return;
+      }
+    }
+  }
+
+  /// \brief Associate a counter with a given source code range.
+  void mapSourceCodeRange(SourceLocation LocStart, SourceLocation LocEnd,
+                          Counter Count, const Stmt *UnreachableInitiator,
+                          const Stmt *SourceGroup, unsigned Flags = 0,
+                          FileID MacroArgumentFile = FileID()) {
+    if (SM.isMacroArgExpansion(LocStart)) {
+      // Map the code range with the macro argument's value.
+      mapSourceCodeRange(SM.getImmediateSpellingLoc(LocStart),
+                         SM.getImmediateSpellingLoc(LocEnd), Count,
+                         UnreachableInitiator, SourceGroup, Flags,
+                         SM.getFileID(LocStart));
+      // Map the code range where the macro argument is referenced.
+      SourceLocation RefLocStart(SM.getImmediateExpansionRange(LocStart).first);
+      SourceLocation RefLocEnd(RefLocStart);
+      if (SM.isMacroArgExpansion(RefLocStart))
+        mapSourceCodeRange(RefLocStart, RefLocEnd, Count, UnreachableInitiator,
+                           SourceGroup, 0, SM.getFileID(RefLocStart));
+      else
+        mapSourceCodeRange(RefLocStart, RefLocEnd, Count, UnreachableInitiator,
+                           SourceGroup);
+      return;
+    }
+    auto File = SM.getFileID(LocStart);
+    // Make sure that the file id is valid.
+    if (File.isInvalid())
+      return;
+    bringSimilarRegionBack(Count, File, MacroArgumentFile, UnreachableInitiator,
+                           SourceGroup);
+    SourceMappingRegion R(File, MacroArgumentFile, Count, UnreachableInitiator,
+                          SourceGroup, LocStart, LocEnd, Flags);
+    if (SourceRegions.empty() || !SourceRegions.back().isMergeable(R)) {
+      SourceRegions.push_back(R);
+      return;
+    }
+    SourceRegions.back().mergeByExtendingTo(R);
+  }
+
+  void mapSourceCodeRange(SourceLocation LocStart, SourceLocation LocEnd,
+                          Counter Count, unsigned Flags = 0) {
+    mapSourceCodeRange(LocStart, LocEnd, Count,
+                       CurrentUnreachableRegionInitiator, CurrentSourceGroup,
+                       Flags);
+  }
+
+  void mapSourceCodeRange(const SourceMappingState &State,
+                          SourceLocation LocStart, SourceLocation LocEnd,
+                          unsigned Flags = 0) {
+    mapSourceCodeRange(LocStart, LocEnd, State.CurrentRegionCount,
+                       State.CurrentUnreachableRegionInitiator,
+                       State.CurrentSourceGroup, Flags);
+  }
+
+  /// \brief Generate the coverage counter mapping regions from collected
+  /// source regions.
+  void emitSourceRegions() {
+    for (const auto &R : SourceRegions) {
+      SourceLocation LocStart = R.LocStart;
+      SourceLocation LocEnd = R.LocEnd;
+      if (SM.getFileID(LocEnd) != R.File)
+        LocEnd = R.AlternativeLocEnd;
+
+      if (R.hasFlag(SourceMappingRegion::IgnoreIfNotExtended) &&
+          LocStart == LocEnd)
+        continue;
+
+      LocEnd = getPreciseTokenLocEnd(LocEnd);
+      unsigned LineStart = SM.getSpellingLineNumber(LocStart);
+      unsigned ColumnStart = SM.getSpellingColumnNumber(LocStart);
+      unsigned LineEnd = SM.getSpellingLineNumber(LocEnd);
+      unsigned ColumnEnd = SM.getSpellingColumnNumber(LocEnd);
+
+      auto SpellingFile = SM.getDecomposedSpellingLoc(R.LocStart).first;
+      unsigned CovFileID;
+      if (getCoverageFileID(R.LocStart, R.File, SpellingFile, CovFileID))
+        continue;
+
+      assert(LineStart <= LineEnd);
+      MappingRegions.push_back(CounterMappingRegion(
+          R.Count, CovFileID, LineStart, ColumnStart, LineEnd, ColumnEnd,
+          false, CounterMappingRegion::CodeRegion));
+    }
+  }
+};
+
+/// \brief Creates unreachable coverage regions for the functions that
+/// are not emitted.
+struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder {
+  EmptyCoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
+                              const LangOptions &LangOpts)
+      : CoverageMappingBuilder(CVM, SM, LangOpts) {}
+
+  void VisitDecl(const Decl *D) {
+    if (!D->hasBody())
+      return;
+    auto Body = D->getBody();
+    mapSourceCodeRange(Body->getLocStart(), Body->getLocEnd(), Counter());
+  }
+
+  /// \brief Write the mapping data to the output stream
+  void write(llvm::raw_ostream &OS) {
+    emitSourceRegions();
+    SmallVector<unsigned, 16> FileIDMapping;
+    createFileIDMapping(FileIDMapping);
+
+    CoverageMappingWriter Writer(
+        FileIDMapping, ArrayRef<CounterExpression>(), MappingRegions);
+    Writer.write(OS);
+  }
+};
+
+/// \brief A StmtVisitor that creates coverage mapping regions which map
+/// from the source code locations to the PGO counters.
+struct CounterCoverageMappingBuilder
+    : public CoverageMappingBuilder,
+      public ConstStmtVisitor<CounterCoverageMappingBuilder> {
+  /// \brief The map of statements to count values.
+  llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
+
+  Counter CurrentRegionCount;
+
+  CounterExpressionBuilder Builder;
+
+  /// \brief Return a counter that represents the
+  /// expression that subracts rhs from lhs.
+  Counter subtractCounters(Counter LHS, Counter RHS) {
+    return Builder.subtract(LHS, RHS);
+  }
+
+  /// \brief Return a counter that represents the
+  /// the exression that adds lhs and rhs.
+  Counter addCounters(Counter LHS, Counter RHS) {
+    return Builder.add(LHS, RHS);
+  }
+
+  /// \brief Return the region counter for the given statement.
+  /// This should only be called on statements that have a dedicated counter.
+  unsigned getRegionCounter(const Stmt *S) { return CounterMap[S]; }
+
+  /// \brief Return the region count for the counter at the given index.
+  Counter getRegionCount(unsigned CounterId) {
+    return Counter::getCounter(CounterId);
+  }
+
+  /// \brief Return the counter value of the current region.
+  Counter getCurrentRegionCount() { return CurrentRegionCount; }
+
+  /// \brief Set the counter value for the current region.
+  /// This is used to keep track of changes to the most recent counter
+  /// from control flow and non-local exits.
+  void setCurrentRegionCount(Counter Count) {
+    CurrentRegionCount = Count;
+    CurrentUnreachableRegionInitiator = nullptr;
+  }
+
+  /// \brief Indicate that the current region is never reached,
+  /// and thus should have a counter value of zero.
+  /// This is important so that subsequent regions can correctly track
+  /// their parent counts.
+  void setCurrentRegionUnreachable(const Stmt *Initiator) {
+    CurrentRegionCount = Counter::getZero();
+    CurrentUnreachableRegionInitiator = Initiator;
+  }
+
+  /// \brief A counter for a particular region.
+  /// This is the primary interface through
+  /// which the coverage mapping builder manages counters and their values.
+  class RegionMapper {
+    CounterCoverageMappingBuilder &Mapping;
+    Counter Count;
+    Counter ParentCount;
+    Counter RegionCount;
+    Counter Adjust;
+
+  public:
+    RegionMapper(CounterCoverageMappingBuilder *Mapper, const Stmt *S)
+        : Mapping(*Mapper),
+          Count(Mapper->getRegionCount(Mapper->getRegionCounter(S))),
+          ParentCount(Mapper->getCurrentRegionCount()) {}
+
+    /// Get the value of the counter. In most cases this is the number of times
+    /// the region of the counter was entered, but for switch labels it's the
+    /// number of direct jumps to that label.
+    Counter getCount() const { return Count; }
+
+    /// Get the value of the counter with adjustments applied. Adjustments occur
+    /// when control enters or leaves the region abnormally; i.e., if there is a
+    /// jump to a label within the region, or if the function can return from
+    /// within the region. The adjusted count, then, is the value of the counter
+    /// at the end of the region.
+    Counter getAdjustedCount() const {
+      return Mapping.addCounters(Count, Adjust);
+    }
+
+    /// Get the value of the counter in this region's parent, i.e., the region
+    /// that was active when this region began. This is useful for deriving
+    /// counts in implicitly counted regions, like the false case of a condition
+    /// or the normal exits of a loop.
+    Counter getParentCount() const { return ParentCount; }
+
+    /// Activate the counter by emitting an increment and starting to track
+    /// adjustments. If AddIncomingFallThrough is true, the current region count
+    /// will be added to the counter for the purposes of tracking the region.
+    void beginRegion(bool AddIncomingFallThrough = false) {
+      RegionCount = Count;
+      if (AddIncomingFallThrough)
+        RegionCount =
+            Mapping.addCounters(RegionCount, Mapping.getCurrentRegionCount());
+      Mapping.setCurrentRegionCount(RegionCount);
+    }
+
+    /// For counters on boolean branches, begins tracking adjustments for the
+    /// uncounted path.
+    void beginElseRegion() {
+      RegionCount = Mapping.subtractCounters(ParentCount, Count);
+      Mapping.setCurrentRegionCount(RegionCount);
+    }
+
+    /// Reset the current region count.
+    void setCurrentRegionCount(Counter CurrentCount) {
+      RegionCount = CurrentCount;
+      Mapping.setCurrentRegionCount(RegionCount);
+    }
+
+    /// Adjust for non-local control flow after emitting a subexpression or
+    /// substatement. This must be called to account for constructs such as
+    /// gotos,
+    /// labels, and returns, so that we can ensure that our region's count is
+    /// correct in the code that follows.
+    void adjustForControlFlow() {
+      Adjust = Mapping.addCounters(
+          Adjust, Mapping.subtractCounters(Mapping.getCurrentRegionCount(),
+                                           RegionCount));
+      // Reset the region count in case this is called again later.
+      RegionCount = Mapping.getCurrentRegionCount();
+    }
+
+    /// Commit all adjustments to the current region. If the region is a loop,
+    /// the LoopAdjust value should be the count of all the breaks and continues
+    /// from the loop, to compensate for those counts being deducted from the
+    /// adjustments for the body of the loop.
+    void applyAdjustmentsToRegion() {
+      Mapping.setCurrentRegionCount(Mapping.addCounters(ParentCount, Adjust));
+    }
+    void applyAdjustmentsToRegion(Counter LoopAdjust) {
+      Mapping.setCurrentRegionCount(Mapping.addCounters(
+          Mapping.addCounters(ParentCount, Adjust), LoopAdjust));
+    }
+  };
+
+  /// \brief Keep counts of breaks and continues inside loops.
+  struct BreakContinue {
+    Counter BreakCount;
+    Counter ContinueCount;
+  };
+  SmallVector<BreakContinue, 8> BreakContinueStack;
+
+  CounterCoverageMappingBuilder(
+      CoverageMappingModuleGen &CVM,
+      llvm::DenseMap<const Stmt *, unsigned> &CounterMap,
+      unsigned NumRegionCounters, SourceManager &SM,
+      const LangOptions &LangOpts)
+      : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap),
+        Builder(NumRegionCounters) {}
+
+  /// \brief Write the mapping data to the output stream
+  void write(llvm::raw_ostream &OS) {
+    emitSourceRegions();
+    llvm::SmallVector<unsigned, 8> VirtualFileMapping;
+    createFileIDMapping(VirtualFileMapping);
+    gatherSkippedRegions();
+
+    CoverageMappingWriter Writer(
+        VirtualFileMapping, Builder.getExpressions(), MappingRegions);
+    Writer.write(OS);
+  }
+
+  /// \brief Return the current source mapping state.
+  SourceMappingState getCurrentState() const {
+    return SourceMappingState(CurrentRegionCount, CurrentSourceGroup,
+                              CurrentUnreachableRegionInitiator);
+  }
+
+  /// \brief Associate the source code range with the current region count.
+  void mapSourceCodeRange(SourceLocation LocStart, SourceLocation LocEnd,
+                          unsigned Flags = 0) {
+    CoverageMappingBuilder::mapSourceCodeRange(LocStart, LocEnd,
+                                               CurrentRegionCount, Flags);
+  }
+
+  void mapSourceCodeRange(SourceLocation LocStart) {
+    CoverageMappingBuilder::mapSourceCodeRange(LocStart, LocStart,
+                                               CurrentRegionCount);
+  }
+
+  /// \brief Associate the source range of a token with the current region
+  /// count.
+  /// Ignore the source range for this token if it produces a distinct
+  /// mapping region with no other source ranges.
+  void mapToken(SourceLocation LocStart) {
+    CoverageMappingBuilder::mapSourceCodeRange(
+        LocStart, LocStart, CurrentRegionCount,
+        SourceMappingRegion::IgnoreIfNotExtended);
+  }
+
+  void mapToken(const SourceMappingState &State, SourceLocation LocStart) {
+    CoverageMappingBuilder::mapSourceCodeRange(
+        State, LocStart, LocStart, SourceMappingRegion::IgnoreIfNotExtended);
+  }
+
+  void VisitStmt(const Stmt *S) {
+    mapSourceCodeRange(S->getLocStart());
+    for (Stmt::const_child_range I = S->children(); I; ++I) {
+      if (*I)
+        this->Visit(*I);
+    }
+  }
+
+  /// \brief If the given statement is a compound statement,
+  /// map '}' with the same count as '{'.
+  void VisitSubStmtRBraceState(const Stmt *S) {
+    if (!isa<CompoundStmt>(S))
+      return Visit(S);
+    const auto *CS = cast<CompoundStmt>(S);
+    auto State = getCurrentState();
+    mapSourceCodeRange(CS->getLBracLoc());
+    for (Stmt::const_child_range I = S->children(); I; ++I) {
+      if (*I)
+        this->Visit(*I);
+    }
+    CoverageMappingBuilder::mapSourceCodeRange(State, CS->getRBracLoc(),
+                                               CS->getRBracLoc());
+  }
+
+  void VisitDecl(const Decl *D) {
+    if (!D->hasBody())
+      return;
+    // Counter tracks entry to the function body.
+    auto Body = D->getBody();
+    RegionMapper Cnt(this, Body);
+    Cnt.beginRegion();
+    VisitSubStmtRBraceState(Body);
+  }
+
+  void VisitDeclStmt(const DeclStmt *S) {
+    mapSourceCodeRange(S->getLocStart());
+    for (Stmt::const_child_range I = static_cast<const Stmt *>(S)->children();
+         I; ++I) {
+      if (*I)
+        this->Visit(*I);
+    }
+  }
+
+  void VisitCompoundStmt(const CompoundStmt *S) {
+    mapSourceCodeRange(S->getLBracLoc());
+    for (Stmt::const_child_range I = S->children(); I; ++I) {
+      if (*I)
+        this->Visit(*I);
+    }
+    mapSourceCodeRange(S->getRBracLoc(), S->getRBracLoc());
+  }
+
+  void VisitReturnStmt(const ReturnStmt *S) {
+    mapSourceCodeRange(S->getLocStart());
+    if (S->getRetValue())
+      Visit(S->getRetValue());
+    setCurrentRegionUnreachable(S);
+  }
+
+  void VisitGotoStmt(const GotoStmt *S) {
+    mapSourceCodeRange(S->getLocStart());
+    mapToken(S->getLabelLoc());
+    setCurrentRegionUnreachable(S);
+  }
+
+  void VisitLabelStmt(const LabelStmt *S) {
+    // Counter tracks the block following the label.
+    RegionMapper Cnt(this, S);
+    Cnt.beginRegion();
+    mapSourceCodeRange(S->getLocStart());
+    // Can't map the ':' token as its location isn't known.
+    Visit(S->getSubStmt());
+  }
+
+  void VisitBreakStmt(const BreakStmt *S) {
+    mapSourceCodeRange(S->getLocStart());
+    assert(!BreakContinueStack.empty() && "break not in a loop or switch!");
+    BreakContinueStack.back().BreakCount = addCounters(
+        BreakContinueStack.back().BreakCount, getCurrentRegionCount());
+    setCurrentRegionUnreachable(S);
+  }
+
+  void VisitContinueStmt(const ContinueStmt *S) {
+    mapSourceCodeRange(S->getLocStart());
+    assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
+    BreakContinueStack.back().ContinueCount = addCounters(
+        BreakContinueStack.back().ContinueCount, getCurrentRegionCount());
+    setCurrentRegionUnreachable(S);
+  }
+
+  void VisitWhileStmt(const WhileStmt *S) {
+    mapSourceCodeRange(S->getLocStart());
+    // Counter tracks the body of the loop.
+    RegionMapper Cnt(this, S);
+    BreakContinueStack.push_back(BreakContinue());
+    // Visit the body region first so the break/continue adjustments can be
+    // included when visiting the condition.
+    Cnt.beginRegion();
+    VisitSubStmtRBraceState(S->getBody());
+    Cnt.adjustForControlFlow();
+
+    // ...then go back and propagate counts through the condition. The count
+    // at the start of the condition is the sum of the incoming edges,
+    // the backedge from the end of the loop body, and the edges from
+    // continue statements.
+    BreakContinue BC = BreakContinueStack.pop_back_val();
+    Cnt.setCurrentRegionCount(
+        addCounters(Cnt.getParentCount(),
+                    addCounters(Cnt.getAdjustedCount(), BC.ContinueCount)));
+    beginSourceRegionGroup(S->getCond());
+    Visit(S->getCond());
+    endSourceRegionGroup();
+    Cnt.adjustForControlFlow();
+    Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount, BC.ContinueCount));
+  }
+
+  void VisitDoStmt(const DoStmt *S) {
+    mapSourceCodeRange(S->getLocStart());
+    // Counter tracks the body of the loop.
+    RegionMapper Cnt(this, S);
+    BreakContinueStack.push_back(BreakContinue());
+    Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
+    VisitSubStmtRBraceState(S->getBody());
+    Cnt.adjustForControlFlow();
+
+    BreakContinue BC = BreakContinueStack.pop_back_val();
+    // The count at the start of the condition is equal to the count at the
+    // end of the body. The adjusted count does not include either the
+    // fall-through count coming into the loop or the continue count, so add
+    // both of those separately. This is coincidentally the same equation as
+    // with while loops but for different reasons.
+    Cnt.setCurrentRegionCount(
+        addCounters(Cnt.getParentCount(),
+                    addCounters(Cnt.getAdjustedCount(), BC.ContinueCount)));
+    Visit(S->getCond());
+    Cnt.adjustForControlFlow();
+    Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount, BC.ContinueCount));
+  }
+
+  void VisitForStmt(const ForStmt *S) {
+    mapSourceCodeRange(S->getLocStart());
+    if (S->getInit())
+      Visit(S->getInit());
+
+    // Counter tracks the body of the loop.
+    RegionMapper Cnt(this, S);
+    BreakContinueStack.push_back(BreakContinue());
+    // Visit the body region first. (This is basically the same as a while
+    // loop; see further comments in VisitWhileStmt.)
+    Cnt.beginRegion();
+    VisitSubStmtRBraceState(S->getBody());
+    Cnt.adjustForControlFlow();
+
+    // The increment is essentially part of the body but it needs to include
+    // the count for all the continue statements.
+    if (S->getInc()) {
+      Cnt.setCurrentRegionCount(addCounters(
+          getCurrentRegionCount(), BreakContinueStack.back().ContinueCount));
+      beginSourceRegionGroup(S->getInc());
+      Visit(S->getInc());
+      endSourceRegionGroup();
+      Cnt.adjustForControlFlow();
+    }
+
+    BreakContinue BC = BreakContinueStack.pop_back_val();
+
+    // ...then go back and propagate counts through the condition.
+    if (S->getCond()) {
+      Cnt.setCurrentRegionCount(
+          addCounters(addCounters(Cnt.getParentCount(), Cnt.getAdjustedCount()),
+                      BC.ContinueCount));
+      beginSourceRegionGroup(S->getCond());
+      Visit(S->getCond());
+      endSourceRegionGroup();
+      Cnt.adjustForControlFlow();
+    }
+    Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount, BC.ContinueCount));
+  }
+
+  void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
+    mapSourceCodeRange(S->getLocStart());
+    Visit(S->getRangeStmt());
+    Visit(S->getBeginEndStmt());
+    // Counter tracks the body of the loop.
+    RegionMapper Cnt(this, S);
+    BreakContinueStack.push_back(BreakContinue());
+    // Visit the body region first. (This is basically the same as a while
+    // loop; see further comments in VisitWhileStmt.)
+    Cnt.beginRegion();
+    VisitSubStmtRBraceState(S->getBody());
+    Cnt.adjustForControlFlow();
+    BreakContinue BC = BreakContinueStack.pop_back_val();
+    Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount, BC.ContinueCount));
+  }
+
+  void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
+    mapSourceCodeRange(S->getLocStart());
+    Visit(S->getElement());
+    // Counter tracks the body of the loop.
+    RegionMapper Cnt(this, S);
+    BreakContinueStack.push_back(BreakContinue());
+    VisitSubStmtRBraceState(S->getBody());
+    BreakContinue BC = BreakContinueStack.pop_back_val();
+    Cnt.adjustForControlFlow();
+    Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount, BC.ContinueCount));
+  }
+
+  void VisitSwitchStmt(const SwitchStmt *S) {
+    mapSourceCodeRange(S->getLocStart());
+    Visit(S->getCond());
+    BreakContinueStack.push_back(BreakContinue());
+    // Map the '}' for the body to have the same count as the regions after
+    // the switch.
+    SourceLocation RBracLoc;
+    if (const auto *CS = dyn_cast<CompoundStmt>(S->getBody())) {
+      mapSourceCodeRange(CS->getLBracLoc());
+      setCurrentRegionUnreachable(S);
+      for (Stmt::const_child_range I = CS->children(); I; ++I) {
+        if (*I)
+          this->Visit(*I);
+      }
+      RBracLoc = CS->getRBracLoc();
+    } else {
+      setCurrentRegionUnreachable(S);
+      Visit(S->getBody());
+    }
+    // If the switch is inside a loop, add the continue counts.
+    BreakContinue BC = BreakContinueStack.pop_back_val();
+    if (!BreakContinueStack.empty())
+      BreakContinueStack.back().ContinueCount = addCounters(
+          BreakContinueStack.back().ContinueCount, BC.ContinueCount);
+    // Counter tracks the exit block of the switch.
+    RegionMapper ExitCnt(this, S);
+    ExitCnt.beginRegion();
+    if (RBracLoc.isValid())
+      mapSourceCodeRange(RBracLoc);
+  }
+
+  void VisitCaseStmt(const CaseStmt *S) {
+    // Counter for this particular case. This counts only jumps from the
+    // switch header and does not include fallthrough from the case before
+    // this one.
+    RegionMapper Cnt(this, S);
+    Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
+    mapSourceCodeRange(S->getLocStart());
+    mapToken(S->getColonLoc());
+    Visit(S->getSubStmt());
+  }
+
+  void VisitDefaultStmt(const DefaultStmt *S) {
+    // Counter for this default case. This does not include fallthrough from
+    // the previous case.
+    RegionMapper Cnt(this, S);
+    Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
+    mapSourceCodeRange(S->getLocStart());
+    mapToken(S->getColonLoc());
+    Visit(S->getSubStmt());
+  }
+
+  void VisitIfStmt(const IfStmt *S) {
+    mapSourceCodeRange(S->getLocStart());
+    Visit(S->getCond());
+    mapToken(S->getElseLoc());
+
+    // Counter tracks the "then" part of an if statement. The count for
+    // the "else" part, if it exists, will be calculated from this counter.
+    RegionMapper Cnt(this, S);
+    Cnt.beginRegion();
+    VisitSubStmtRBraceState(S->getThen());
+    Cnt.adjustForControlFlow();
+
+    if (S->getElse()) {
+      Cnt.beginElseRegion();
+      VisitSubStmtRBraceState(S->getElse());
+      Cnt.adjustForControlFlow();
+    }
+    Cnt.applyAdjustmentsToRegion();
+  }
+
+  void VisitCXXTryStmt(const CXXTryStmt *S) {
+    mapSourceCodeRange(S->getLocStart());
+    Visit(S->getTryBlock());
+    for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
+      Visit(S->getHandler(I));
+    // Counter tracks the continuation block of the try statement.
+    RegionMapper Cnt(this, S);
+    Cnt.beginRegion();
+  }
+
+  void VisitCXXCatchStmt(const CXXCatchStmt *S) {
+    mapSourceCodeRange(S->getLocStart());
+    // Counter tracks the catch statement's handler block.
+    RegionMapper Cnt(this, S);
+    Cnt.beginRegion();
+    VisitSubStmtRBraceState(S->getHandlerBlock());
+  }
+
+  void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
+    Visit(E->getCond());
+    mapToken(E->getQuestionLoc());
+    auto State = getCurrentState();
+
+    // Counter tracks the "true" part of a conditional operator. The
+    // count in the "false" part will be calculated from this counter.
+    RegionMapper Cnt(this, E);
+    Cnt.beginRegion();
+    Visit(E->getTrueExpr());
+    Cnt.adjustForControlFlow();
+
+    mapToken(State, E->getColonLoc());
+
+    Cnt.beginElseRegion();
+    Visit(E->getFalseExpr());
+    Cnt.adjustForControlFlow();
+
+    Cnt.applyAdjustmentsToRegion();
+  }
+
+  void VisitBinLAnd(const BinaryOperator *E) {
+    Visit(E->getLHS());
+    mapToken(E->getOperatorLoc());
+    // Counter tracks the right hand side of a logical and operator.
+    RegionMapper Cnt(this, E);
+    Cnt.beginRegion();
+    Visit(E->getRHS());
+    Cnt.adjustForControlFlow();
+    Cnt.applyAdjustmentsToRegion();
+  }
+
+  void VisitBinLOr(const BinaryOperator *E) {
+    Visit(E->getLHS());
+    mapToken(E->getOperatorLoc());
+    // Counter tracks the right hand side of a logical or operator.
+    RegionMapper Cnt(this, E);
+    Cnt.beginRegion();
+    Visit(E->getRHS());
+    Cnt.adjustForControlFlow();
+    Cnt.applyAdjustmentsToRegion();
+  }
+
+  void VisitParenExpr(const ParenExpr *E) {
+    mapToken(E->getLParen());
+    Visit(E->getSubExpr());
+    mapToken(E->getRParen());
+  }
+
+  void VisitBinaryOperator(const BinaryOperator *E) {
+    Visit(E->getLHS());
+    mapToken(E->getOperatorLoc());
+    Visit(E->getRHS());
+  }
+
+  void VisitUnaryOperator(const UnaryOperator *E) {
+    bool Postfix = E->isPostfix();
+    if (!Postfix)
+      mapToken(E->getOperatorLoc());
+    Visit(E->getSubExpr());
+    if (Postfix)
+      mapToken(E->getOperatorLoc());
+  }
+
+  void VisitMemberExpr(const MemberExpr *E) {
+    Visit(E->getBase());
+    mapToken(E->getMemberLoc());
+  }
+
+  void VisitCallExpr(const CallExpr *E) {
+    Visit(E->getCallee());
+    for (const auto &Arg : E->arguments())
+      Visit(Arg);
+    mapToken(E->getRParenLoc());
+  }
+
+  void VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
+    Visit(E->getLHS());
+    Visit(E->getRHS());
+    mapToken(E->getRBracketLoc());
+  }
+
+  void VisitCStyleCastExpr(const CStyleCastExpr *E) {
+    mapToken(E->getLParenLoc());
+    mapToken(E->getRParenLoc());
+    Visit(E->getSubExpr());
+  }
+
+  // Map literals as tokens so that the macros like #define PI 3.14
+  // won't generate coverage mapping regions.
+
+  void VisitIntegerLiteral(const IntegerLiteral *E) {
+    mapToken(E->getLocStart());
+  }
+
+  void VisitFloatingLiteral(const FloatingLiteral *E) {
+    mapToken(E->getLocStart());
+  }
+
+  void VisitCharacterLiteral(const CharacterLiteral *E) {
+    mapToken(E->getLocStart());
+  }
+
+  void VisitStringLiteral(const StringLiteral *E) {
+    mapToken(E->getLocStart());
+  }
+
+  void VisitImaginaryLiteral(const ImaginaryLiteral *E) {
+    mapToken(E->getLocStart());
+  }
+};
+}
+
+static bool isMachO(const CodeGenModule &CGM) {
+  return CGM.getTarget().getTriple().isOSBinFormatMachO();
+}
+
+static StringRef getCoverageSection(const CodeGenModule &CGM) {
+  return isMachO(CGM) ? "__DATA,__llvm_covmap" : "__llvm_covmap";
+}
+
+void CoverageMappingModuleGen::addFunctionMappingRecord(
+    llvm::GlobalVariable *FunctionName, unsigned FunctionNameSize,
+    const std::string &CoverageMapping) {
+  llvm::LLVMContext &Ctx = CGM.getLLVMContext();
+  auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
+  auto *Int8PtrTy = llvm::Type::getInt8PtrTy(Ctx);
+  if (!FunctionRecordTy) {
+    llvm::Type *FunctionRecordTypes[] = {Int8PtrTy, Int32Ty, Int32Ty};
+    FunctionRecordTy =
+        llvm::StructType::get(Ctx, makeArrayRef(FunctionRecordTypes));
+  }
+
+  llvm::Constant *FunctionRecordVals[] = {
+      llvm::ConstantExpr::getBitCast(FunctionName, Int8PtrTy),
+      llvm::ConstantInt::get(Int32Ty, FunctionNameSize),
+      llvm::ConstantInt::get(Int32Ty, CoverageMapping.size())};
+  FunctionRecords.push_back(llvm::ConstantStruct::get(
+      FunctionRecordTy, makeArrayRef(FunctionRecordVals)));
+  CoverageMappings += CoverageMapping;
+}
+
+void CoverageMappingModuleGen::emit() {
+  if (FunctionRecords.empty())
+    return;
+  llvm::LLVMContext &Ctx = CGM.getLLVMContext();
+  auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
+
+  // Create the filenames and merge them with coverage mappings
+  llvm::SmallVector<std::string, 16> FilenameStrs;
+  llvm::SmallVector<StringRef, 16> FilenameRefs;
+  FilenameStrs.resize(FileEntries.size());
+  FilenameRefs.resize(FileEntries.size());
+  for (const auto &Entry : FileEntries) {
+    llvm::SmallString<256> Path(Entry.first->getName());
+    llvm::sys::fs::make_absolute(Path);
+
+    auto I = Entry.second;
+    FilenameStrs[I] = std::move(std::string(Path.begin(), Path.end()));
+    FilenameRefs[I] = FilenameStrs[I];
+  }
+
+  std::string FilenamesAndCoverageMappings;
+  llvm::raw_string_ostream OS(FilenamesAndCoverageMappings);
+  CoverageFilenamesSectionWriter(FilenameRefs).write(OS);
+  OS << CoverageMappings;
+  size_t CoverageMappingSize = CoverageMappings.size();
+  size_t FilenamesSize = OS.str().size() - CoverageMappingSize;
+  // Append extra zeroes if necessary to ensure that the size of the filenames
+  // and coverage mappings is a multiple of 8.
+  if (size_t Rem = OS.str().size() % 8) {
+    CoverageMappingSize += 8 - Rem;
+    for (size_t I = 0, S = 8 - Rem; I < S; ++I)
+      OS << '\0';
+  }
+  auto *FilenamesAndMappingsVal =
+      llvm::ConstantDataArray::getString(Ctx, OS.str(), false);
+
+  // Create the deferred function records array
+  auto RecordsTy =
+      llvm::ArrayType::get(FunctionRecordTy, FunctionRecords.size());
+  auto RecordsVal = llvm::ConstantArray::get(RecordsTy, FunctionRecords);
+
+  // Create the coverage data record
+  llvm::Type *CovDataTypes[] = {Int32Ty,   Int32Ty,
+                                Int32Ty,   Int32Ty,
+                                RecordsTy, FilenamesAndMappingsVal->getType()};
+  auto CovDataTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataTypes));
+  llvm::Constant *TUDataVals[] = {
+      llvm::ConstantInt::get(Int32Ty, FunctionRecords.size()),
+      llvm::ConstantInt::get(Int32Ty, FilenamesSize),
+      llvm::ConstantInt::get(Int32Ty, CoverageMappingSize),
+      llvm::ConstantInt::get(Int32Ty,
+                             /*Version=*/CoverageMappingVersion1),
+      RecordsVal, FilenamesAndMappingsVal};
+  auto CovDataVal =
+      llvm::ConstantStruct::get(CovDataTy, makeArrayRef(TUDataVals));
+  auto CovData = new llvm::GlobalVariable(CGM.getModule(), CovDataTy, true,
+                                          llvm::GlobalValue::InternalLinkage,
+                                          CovDataVal,
+                                          "__llvm_coverage_mapping");
+
+  CovData->setSection(getCoverageSection(CGM));
+  CovData->setAlignment(8);
+
+  // Make sure the data doesn't get deleted.
+  CGM.addUsedGlobal(CovData);
+}
+
+unsigned CoverageMappingModuleGen::getFileID(const FileEntry *File) {
+  auto It = FileEntries.find(File);
+  if (It != FileEntries.end())
+    return It->second;
+  unsigned FileID = FileEntries.size();
+  FileEntries.insert(std::make_pair(File, FileID));
+  return FileID;
+}
+
+void CoverageMappingGen::emitCounterMapping(const Decl *D,
+                                            llvm::raw_ostream &OS) {
+  assert(CounterMap);
+  CounterCoverageMappingBuilder Walker(CVM, *CounterMap, NumRegionCounters, SM,
+                                       LangOpts);
+  Walker.VisitDecl(D);
+  Walker.write(OS);
+}
+
+void CoverageMappingGen::emitEmptyMapping(const Decl *D,
+                                          llvm::raw_ostream &OS) {
+  EmptyCoverageMappingBuilder Walker(CVM, SM, LangOpts);
+  Walker.VisitDecl(D);
+  Walker.write(OS);
+}

Added: cfe/trunk/lib/CodeGen/CoverageMappingGen.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CoverageMappingGen.h?rev=214752&view=auto
==============================================================================
--- cfe/trunk/lib/CodeGen/CoverageMappingGen.h (added)
+++ cfe/trunk/lib/CodeGen/CoverageMappingGen.h Mon Aug  4 13:41:51 2014
@@ -0,0 +1,117 @@
+//===---- CoverageMappingGen.h - Coverage mapping generation ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Instrumentation-based code coverage mapping generator
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_COVERAGEMAPPINGGEN_H
+#define CLANG_CODEGEN_COVERAGEMAPPINGGEN_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+
+class LangOptions;
+class SourceManager;
+class FileEntry;
+class Preprocessor;
+class Decl;
+class Stmt;
+
+/// \brief Stores additional source code information like skipped ranges which
+/// is required by the coverage mapping generator and is obtained from
+/// the preprocessor.
+class CoverageSourceInfo : public PPCallbacks {
+  std::vector<SourceRange> SkippedRanges;
+public:
+  ArrayRef<SourceRange> getSkippedRanges() const { return SkippedRanges; }
+
+  void SourceRangeSkipped(SourceRange Range) override;
+};
+
+namespace CodeGen {
+
+class CodeGenModule;
+
+/// \brief Organizes the cross-function state that is used while generating
+/// code coverage mapping data.
+class CoverageMappingModuleGen {
+  CodeGenModule &CGM;
+  CoverageSourceInfo &SourceInfo;
+  llvm::SmallDenseMap<const FileEntry *, unsigned, 8> FileEntries;
+  std::vector<llvm::Constant *> FunctionRecords;
+  llvm::StructType *FunctionRecordTy;
+  std::string CoverageMappings;
+
+public:
+  CoverageMappingModuleGen(CodeGenModule &CGM, CoverageSourceInfo &SourceInfo)
+      : CGM(CGM), SourceInfo(SourceInfo), FunctionRecordTy(nullptr) {}
+
+  CoverageSourceInfo &getSourceInfo() const {
+    return SourceInfo;
+  }
+
+  /// \brief Add a function's coverage mapping record to the collection of the
+  /// function mapping records.
+  void addFunctionMappingRecord(llvm::GlobalVariable *FunctionName,
+                                unsigned FunctionNameSize,
+                                const std::string &CoverageMapping);
+
+  /// \brief Emit the coverage mapping data for a translation unit.
+  void emit();
+
+  /// \brief Return the coverage mapping translation unit file id
+  /// for the given file.
+  unsigned getFileID(const FileEntry *File);
+};
+
+/// \brief Organizes the per-function state that is used while generating
+/// code coverage mapping data.
+class CoverageMappingGen {
+  CoverageMappingModuleGen &CVM;
+  SourceManager &SM;
+  const LangOptions &LangOpts;
+  llvm::DenseMap<const Stmt *, unsigned> *CounterMap;
+  unsigned NumRegionCounters;
+
+public:
+  CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager &SM,
+                     const LangOptions &LangOpts)
+      : CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(nullptr),
+        NumRegionCounters(0) {}
+
+  CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager &SM,
+                     const LangOptions &LangOpts,
+                     llvm::DenseMap<const Stmt *, unsigned> *CounterMap,
+                     unsigned NumRegionCounters)
+      : CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(CounterMap),
+        NumRegionCounters(NumRegionCounters) {}
+
+  /// \brief Emit the coverage mapping data which maps the regions of
+  /// code to counters that will be used to find the execution
+  /// counts for those regions.
+  void emitCounterMapping(const Decl *D, llvm::raw_ostream &OS);
+
+  /// \brief Emit the coverage mapping data for an unused function.
+  /// It creates mapping regions with the counter of zero.
+  void emitEmptyMapping(const Decl *D, llvm::raw_ostream &OS);
+};
+
+} // end namespace CodeGen
+} // end namespace clang
+
+#endif

Modified: cfe/trunk/lib/CodeGen/ModuleBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ModuleBuilder.cpp?rev=214752&r1=214751&r2=214752&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ModuleBuilder.cpp (original)
+++ cfe/trunk/lib/CodeGen/ModuleBuilder.cpp Mon Aug  4 13:41:51 2014
@@ -46,14 +46,18 @@ namespace {
       }
     };
 
+    CoverageSourceInfo *CoverageInfo;
+
   protected:
     std::unique_ptr<llvm::Module> M;
     std::unique_ptr<CodeGen::CodeGenModule> Builder;
 
   public:
     CodeGeneratorImpl(DiagnosticsEngine &diags, const std::string& ModuleName,
-                      const CodeGenOptions &CGO, llvm::LLVMContext& C)
+                      const CodeGenOptions &CGO, llvm::LLVMContext& C,
+                      CoverageSourceInfo *CoverageInfo = nullptr)
       : Diags(diags), CodeGenOpts(CGO), HandlingTopLevelDecls(0),
+        CoverageInfo(CoverageInfo),
         M(new llvm::Module(ModuleName, C)) {}
 
     virtual ~CodeGeneratorImpl() {}
@@ -86,7 +90,7 @@ namespace {
       M->setDataLayout(Ctx->getTargetInfo().getTargetDescription());
       TD.reset(new llvm::DataLayout(Ctx->getTargetInfo().getTargetDescription()));
       Builder.reset(new CodeGen::CodeGenModule(Context, CodeGenOpts, *M, *TD,
-                                               Diags));
+                                               Diags, CoverageInfo));
 
       for (size_t i = 0, e = CodeGenOpts.DependentLibraries.size(); i < e; ++i)
         HandleDependentLibrary(CodeGenOpts.DependentLibraries[i]);
@@ -136,6 +140,10 @@ namespace {
       //     void foo() { bar(); }
       //   } A;
       DeferredInlineMethodDefinitions.push_back(D);
+
+      // Always provide some coverage mapping
+      // even for the methods that aren't emitted.
+      Builder->AddDeferredUnusedCoverageMapping(D);
     }
 
     /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
@@ -221,6 +229,7 @@ CodeGenerator *clang::CreateLLVMCodeGen(
                                         const std::string& ModuleName,
                                         const CodeGenOptions &CGO,
                                         const TargetOptions &/*TO*/,
-                                        llvm::LLVMContext& C) {
-  return new CodeGeneratorImpl(Diags, ModuleName, CGO, C);
+                                        llvm::LLVMContext& C,
+                                        CoverageSourceInfo *CoverageInfo) {
+  return new CodeGeneratorImpl(Diags, ModuleName, CGO, C, CoverageInfo);
 }

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=214752&r1=214751&r2=214752&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Mon Aug  4 13:41:51 2014
@@ -3230,6 +3230,14 @@ void Clang::ConstructJob(Compilation &C,
       Args.hasArg(options::OPT_coverage))
     CmdArgs.push_back("-femit-coverage-data");
 
+  if (Args.hasArg(options::OPT_fcoverage_mapping) &&
+      !Args.hasArg(options::OPT_fprofile_instr_generate))
+    D.Diag(diag::err_drv_argument_only_allowed_with)
+      << "-fcoverage-mapping" << "-fprofile-instr-generate";
+
+  if (Args.hasArg(options::OPT_fcoverage_mapping))
+    CmdArgs.push_back("-fcoverage-mapping");
+
   if (C.getArgs().hasArg(options::OPT_c) ||
       C.getArgs().hasArg(options::OPT_S)) {
     if (Output.isFilename()) {

Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=214752&r1=214751&r2=214752&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Mon Aug  4 13:41:51 2014
@@ -403,6 +403,7 @@ static bool ParseCodeGenArgs(CodeGenOpti
   Opts.SampleProfileFile = Args.getLastArgValue(OPT_fprofile_sample_use_EQ);
   Opts.ProfileInstrGenerate = Args.hasArg(OPT_fprofile_instr_generate);
   Opts.InstrProfileInput = Args.getLastArgValue(OPT_fprofile_instr_use_EQ);
+  Opts.CoverageMapping = Args.hasArg(OPT_fcoverage_mapping);
   Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose);
   Opts.ObjCAutoRefCountExceptions = Args.hasArg(OPT_fobjc_arc_exceptions);
   Opts.CUDAIsDevice = Args.hasArg(OPT_fcuda_is_device);





More information about the cfe-commits mailing list