<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">2014-08-04 12:15 GMT-07:00 Alex L <span dir="ltr"><<a href="mailto:arphaman@gmail.com" target="_blank">arphaman@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr">My fix reverted in r214757.<br></div></blockquote><div><br></div><div>That should have said r214759 of course.<br> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr"></div><div class="gmail_extra"><br><br><div class="gmail_quote">2014-08-04 12:11 GMT-07:00 David Blaikie <span dir="ltr"><<a href="mailto:dblaikie@gmail.com" target="_blank">dblaikie@gmail.com</a>></span>:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Ah, sorry - thanks :)<br>
<div><div><br>
On Mon, Aug 4, 2014 at 12:10 PM, Alex L <<a href="mailto:arphaman@gmail.com" target="_blank">arphaman@gmail.com</a>> wrote:<br>
> I actually fixed it in r214757, now there are two :)<br>
> I will revert mine<br>
><br>
><br>
> 2014-08-04 12:08 GMT-07:00 David Blaikie <<a href="mailto:dblaikie@gmail.com" target="_blank">dblaikie@gmail.com</a>>:<br>
>><br>
>> CMake build fixed in  r214758<br>
>><br>
>> On Mon, Aug 4, 2014 at 11:41 AM, Alex Lorenz <<a href="mailto:arphaman@gmail.com" target="_blank">arphaman@gmail.com</a>> wrote:<br>
>> > Author: arphaman<br>
>> > Date: Mon Aug  4 13:41:51 2014<br>
>> > New Revision: 214752<br>
>> ><br>
>> > URL: <a href="http://llvm.org/viewvc/llvm-project?rev=214752&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=214752&view=rev</a><br>
>> > Log:<br>
>> > Add coverage mapping generation.<br>
>> ><br>
>> > This patch adds the '-fcoverage-mapping' option which<br>
>> > allows clang to generate the coverage mapping information<br>
>> > that can be used to provide code coverage analysis using<br>
>> > the execution counts obtained from the instrumentation<br>
>> > based profiling (-fprofile-instr-generate).<br>
>> ><br>
>> > Added:<br>
>> >     cfe/trunk/lib/CodeGen/CoverageMappingGen.cpp<br>
>> >     cfe/trunk/lib/CodeGen/CoverageMappingGen.h<br>
>> > Modified:<br>
>> >     cfe/trunk/include/clang/CodeGen/CodeGenABITypes.h<br>
>> >     cfe/trunk/include/clang/CodeGen/ModuleBuilder.h<br>
>> >     cfe/trunk/include/clang/Driver/Options.td<br>
>> >     cfe/trunk/include/clang/Frontend/CodeGenOptions.def<br>
>> >     cfe/trunk/lib/CodeGen/CodeGenABITypes.cpp<br>
>> >     cfe/trunk/lib/CodeGen/CodeGenAction.cpp<br>
>> >     cfe/trunk/lib/CodeGen/CodeGenFunction.cpp<br>
>> >     cfe/trunk/lib/CodeGen/CodeGenModule.cpp<br>
>> >     cfe/trunk/lib/CodeGen/CodeGenModule.h<br>
>> >     cfe/trunk/lib/CodeGen/CodeGenPGO.cpp<br>
>> >     cfe/trunk/lib/CodeGen/CodeGenPGO.h<br>
>> >     cfe/trunk/lib/CodeGen/ModuleBuilder.cpp<br>
>> >     cfe/trunk/lib/Driver/Tools.cpp<br>
>> >     cfe/trunk/lib/Frontend/CompilerInvocation.cpp<br>
>> ><br>
>> > Modified: cfe/trunk/include/clang/CodeGen/CodeGenABITypes.h<br>
>> > URL:<br>
>> > <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/CodeGen/CodeGenABITypes.h?rev=214752&r1=214751&r2=214752&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/CodeGen/CodeGenABITypes.h?rev=214752&r1=214751&r2=214752&view=diff</a><br>


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


>> ><br>
>> > ==============================================================================<br>
>> > --- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)<br>
</div></div>>> > +++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Mon Aug  4 13:41:51<br>
>> > 2014<br>
<div><div>>> > @@ -403,6 +403,7 @@ static bool ParseCodeGenArgs(CodeGenOpti<br>
>> >    Opts.SampleProfileFile =<br>
>> > Args.getLastArgValue(OPT_fprofile_sample_use_EQ);<br>
>> >    Opts.ProfileInstrGenerate = Args.hasArg(OPT_fprofile_instr_generate);<br>
>> >    Opts.InstrProfileInput =<br>
>> > Args.getLastArgValue(OPT_fprofile_instr_use_EQ);<br>
>> > +  Opts.CoverageMapping = Args.hasArg(OPT_fcoverage_mapping);<br>
>> >    Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose);<br>
>> >    Opts.ObjCAutoRefCountExceptions =<br>
>> > Args.hasArg(OPT_fobjc_arc_exceptions);<br>
>> >    Opts.CUDAIsDevice = Args.hasArg(OPT_fcuda_is_device);<br>
>> ><br>
>> ><br>
>> > _______________________________________________<br>
>> > cfe-commits mailing list<br>
>> > <a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank">cfe-commits@cs.uiuc.edu</a><br>
>> > <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
><br>
><br>
</div></div></blockquote></div><br></div>
</blockquote></div><br></div></div>