r214752 - Add coverage mapping generation.
Alex L
arphaman at gmail.com
Mon Aug 4 12:15:44 PDT 2014
2014-08-04 12:15 GMT-07:00 Alex L <arphaman at gmail.com>:
> My fix reverted in r214757.
>
That should have said r214759 of course.
>
>
> 2014-08-04 12:11 GMT-07:00 David Blaikie <dblaikie at gmail.com>:
>
>> Ah, sorry - thanks :)
>>
>> On Mon, Aug 4, 2014 at 12:10 PM, Alex L <arphaman at gmail.com> wrote:
>> > I actually fixed it in r214757, now there are two :)
>> > I will revert mine
>> >
>> >
>> > 2014-08-04 12:08 GMT-07:00 David Blaikie <dblaikie at gmail.com>:
>> >>
>> >> CMake build fixed in r214758
>> >>
>> >> On Mon, Aug 4, 2014 at 11:41 AM, Alex Lorenz <arphaman at gmail.com>
>> wrote:
>> >> > Author: arphaman
>> >> > Date: Mon Aug 4 13:41:51 2014
>> >> > New Revision: 214752
>> >> >
>> >> > URL: http://llvm.org/viewvc/llvm-project?rev=214752&view=rev
>> >> > Log:
>> >> > Add coverage mapping generation.
>> >> >
>> >> > This patch adds the '-fcoverage-mapping' option which
>> >> > allows clang to generate the coverage mapping information
>> >> > that can be used to provide code coverage analysis using
>> >> > the execution counts obtained from the instrumentation
>> >> > based profiling (-fprofile-instr-generate).
>> >> >
>> >> > Added:
>> >> > cfe/trunk/lib/CodeGen/CoverageMappingGen.cpp
>> >> > cfe/trunk/lib/CodeGen/CoverageMappingGen.h
>> >> > Modified:
>> >> > cfe/trunk/include/clang/CodeGen/CodeGenABITypes.h
>> >> > cfe/trunk/include/clang/CodeGen/ModuleBuilder.h
>> >> > cfe/trunk/include/clang/Driver/Options.td
>> >> > cfe/trunk/include/clang/Frontend/CodeGenOptions.def
>> >> > cfe/trunk/lib/CodeGen/CodeGenABITypes.cpp
>> >> > cfe/trunk/lib/CodeGen/CodeGenAction.cpp
>> >> > cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
>> >> > cfe/trunk/lib/CodeGen/CodeGenModule.cpp
>> >> > cfe/trunk/lib/CodeGen/CodeGenModule.h
>> >> > cfe/trunk/lib/CodeGen/CodeGenPGO.cpp
>> >> > cfe/trunk/lib/CodeGen/CodeGenPGO.h
>> >> > cfe/trunk/lib/CodeGen/ModuleBuilder.cpp
>> >> > cfe/trunk/lib/Driver/Tools.cpp
>> >> > cfe/trunk/lib/Frontend/CompilerInvocation.cpp
>> >> >
>> >> > Modified: cfe/trunk/include/clang/CodeGen/CodeGenABITypes.h
>> >> > URL:
>> >> >
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/CodeGen/CodeGenABITypes.h?rev=214752&r1=214751&r2=214752&view=diff
>> >> >
>> >> >
>> ==============================================================================
>> >> > --- cfe/trunk/include/clang/CodeGen/CodeGenABITypes.h (original)
>> >> > +++ cfe/trunk/include/clang/CodeGen/CodeGenABITypes.h Mon Aug 4
>> >> > 13:41:51 2014
>> >> > @@ -39,6 +39,7 @@ class CXXRecordDecl;
>> >> > class CodeGenOptions;
>> >> > class DiagnosticsEngine;
>> >> > class ObjCMethodDecl;
>> >> > +class CoverageSourceInfo;
>> >> >
>> >> > namespace CodeGen {
>> >> > class CGFunctionInfo;
>> >> > @@ -47,7 +48,8 @@ class CodeGenModule;
>> >> > class CodeGenABITypes
>> >> > {
>> >> > public:
>> >> > - CodeGenABITypes(ASTContext &C, llvm::Module &M, const
>> >> > llvm::DataLayout &TD);
>> >> > + CodeGenABITypes(ASTContext &C, llvm::Module &M, const
>> >> > llvm::DataLayout &TD,
>> >> > + CoverageSourceInfo *CoverageInfo = nullptr);
>> >> > ~CodeGenABITypes();
>> >> >
>> >> > /// These methods all forward to methods in the private
>> >> > implementation class
>> >> >
>> >> > Modified: cfe/trunk/include/clang/CodeGen/ModuleBuilder.h
>> >> > URL:
>> >> >
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/CodeGen/ModuleBuilder.h?rev=214752&r1=214751&r2=214752&view=diff
>> >> >
>> >> >
>> ==============================================================================
>> >> > --- cfe/trunk/include/clang/CodeGen/ModuleBuilder.h (original)
>> >> > +++ cfe/trunk/include/clang/CodeGen/ModuleBuilder.h Mon Aug 4
>> 13:41:51
>> >> > 2014
>> >> > @@ -24,6 +24,7 @@ namespace llvm {
>> >> >
>> >> > namespace clang {
>> >> > class DiagnosticsEngine;
>> >> > + class CoverageSourceInfo;
>> >> > class LangOptions;
>> >> > class CodeGenOptions;
>> >> > class TargetOptions;
>> >> > @@ -44,7 +45,8 @@ namespace clang {
>> >> > const std::string &ModuleName,
>> >> > const CodeGenOptions &CGO,
>> >> > const TargetOptions &TO,
>> >> > - llvm::LLVMContext& C);
>> >> > + llvm::LLVMContext& C,
>> >> > + CoverageSourceInfo *CoverageInfo
>> =
>> >> > nullptr);
>> >> > }
>> >> >
>> >> > #endif
>> >> >
>> >> > Modified: cfe/trunk/include/clang/Driver/Options.td
>> >> > URL:
>> >> >
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=214752&r1=214751&r2=214752&view=diff
>> >> >
>> >> >
>> ==============================================================================
>> >> > --- cfe/trunk/include/clang/Driver/Options.td (original)
>> >> > +++ cfe/trunk/include/clang/Driver/Options.td Mon Aug 4 13:41:51
>> 2014
>> >> > @@ -408,6 +408,9 @@ def fprofile_instr_use : Flag<["-"], "fp
>> >> > def fprofile_instr_use_EQ : Joined<["-"], "fprofile-instr-use=">,
>> >> > Group<f_Group>, Flags<[CC1Option]>,
>> >> > HelpText<"Use instrumentation data for profile-guided
>> >> > optimization">;
>> >> > +def fcoverage_mapping : Flag<["-"], "fcoverage-mapping">,
>> >> > + Group<f_Group>, Flags<[CC1Option]>,
>> >> > + HelpText<"Generate coverage mapping to enable code coverage
>> >> > analysis">;
>> >> >
>> >> > def fblocks : Flag<["-"], "fblocks">, Group<f_Group>,
>> >> > Flags<[CC1Option]>,
>> >> > HelpText<"Enable the 'blocks' language feature">;
>> >> >
>> >> > Modified: cfe/trunk/include/clang/Frontend/CodeGenOptions.def
>> >> > URL:
>> >> >
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/CodeGenOptions.def?rev=214752&r1=214751&r2=214752&view=diff
>> >> >
>> >> >
>> ==============================================================================
>> >> > --- cfe/trunk/include/clang/Frontend/CodeGenOptions.def (original)
>> >> > +++ cfe/trunk/include/clang/Frontend/CodeGenOptions.def Mon Aug 4
>> >> > 13:41:51 2014
>> >> > @@ -88,6 +88,8 @@ VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///
>> >> >
>> >> > CODEGENOPT(ProfileInstrGenerate , 1, 0) ///< Instrument code to
>> >> > generate
>> >> > ///< execution counts to use
>> >> > with PGO.
>> >> > +CODEGENOPT(CoverageMapping , 1, 0) ///< Generate coverage mapping
>> >> > regions to
>> >> > + ///< enable code coverage
>> analysis.
>> >> >
>> >> > /// If -fpcc-struct-return or -freg-struct-return is specified.
>> >> > ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind,
>> 2,
>> >> > SRCK_Default)
>> >> >
>> >> > Modified: cfe/trunk/lib/CodeGen/CodeGenABITypes.cpp
>> >> > URL:
>> >> >
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenABITypes.cpp?rev=214752&r1=214751&r2=214752&view=diff
>> >> >
>> >> >
>> ==============================================================================
>> >> > --- cfe/trunk/lib/CodeGen/CodeGenABITypes.cpp (original)
>> >> > +++ cfe/trunk/lib/CodeGen/CodeGenABITypes.cpp Mon Aug 4 13:41:51
>> 2014
>> >> > @@ -26,9 +26,11 @@ using namespace CodeGen;
>> >> >
>> >> > CodeGenABITypes::CodeGenABITypes(ASTContext &C,
>> >> > llvm::Module &M,
>> >> > - const llvm::DataLayout &TD)
>> >> > + const llvm::DataLayout &TD,
>> >> > + CoverageSourceInfo *CoverageInfo)
>> >> > : CGO(new CodeGenOptions),
>> >> > - CGM(new CodeGen::CodeGenModule(C, *CGO, M, TD,
>> C.getDiagnostics()))
>> >> > {
>> >> > + CGM(new CodeGen::CodeGenModule(C, *CGO, M, TD,
>> C.getDiagnostics(),
>> >> > + CoverageInfo)) {
>> >> > }
>> >> >
>> >> > CodeGenABITypes::~CodeGenABITypes()
>> >> >
>> >> > Modified: cfe/trunk/lib/CodeGen/CodeGenAction.cpp
>> >> > URL:
>> >> >
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenAction.cpp?rev=214752&r1=214751&r2=214752&view=diff
>> >> >
>> >> >
>> ==============================================================================
>> >> > --- cfe/trunk/lib/CodeGen/CodeGenAction.cpp (original)
>> >> > +++ cfe/trunk/lib/CodeGen/CodeGenAction.cpp Mon Aug 4 13:41:51 2014
>> >> > @@ -7,6 +7,7 @@
>> >> > //
>> >> >
>> >> >
>> //===----------------------------------------------------------------------===//
>> >> >
>> >> > +#include "CoverageMappingGen.h"
>> >> > #include "clang/CodeGen/CodeGenAction.h"
>> >> > #include "clang/AST/ASTConsumer.h"
>> >> > #include "clang/AST/ASTContext.h"
>> >> > @@ -15,6 +16,7 @@
>> >> > #include "clang/Basic/FileManager.h"
>> >> > #include "clang/Basic/SourceManager.h"
>> >> > #include "clang/Basic/TargetInfo.h"
>> >> > +#include "clang/Lex/Preprocessor.h"
>> >> > #include "clang/CodeGen/BackendUtil.h"
>> >> > #include "clang/CodeGen/ModuleBuilder.h"
>> >> > #include "clang/Frontend/CompilerInstance.h"
>> >> > @@ -59,11 +61,13 @@ namespace clang {
>> >> > const TargetOptions &targetopts,
>> >> > const LangOptions &langopts, bool TimePasses,
>> >> > const std::string &infile, llvm::Module
>> >> > *LinkModule,
>> >> > - raw_ostream *OS, LLVMContext &C)
>> >> > + raw_ostream *OS, LLVMContext &C,
>> >> > + CoverageSourceInfo *CoverageInfo = nullptr)
>> >> > : Diags(_Diags), Action(action), CodeGenOpts(compopts),
>> >> > TargetOpts(targetopts), LangOpts(langopts),
>> AsmOutStream(OS),
>> >> > Context(), LLVMIRGeneration("LLVM IR Generation Time"),
>> >> > - Gen(CreateLLVMCodeGen(Diags, infile, compopts, targetopts,
>> >> > C)),
>> >> > + Gen(CreateLLVMCodeGen(Diags, infile, compopts,
>> >> > + targetopts, C, CoverageInfo)),
>> >> > LinkModule(LinkModule) {
>> >> > llvm::TimePassesIsEnabled = TimePasses;
>> >> > }
>> >> > @@ -636,10 +640,17 @@ ASTConsumer *CodeGenAction::CreateASTCon
>> >> > LinkModuleToUse = ModuleOrErr.get();
>> >> > }
>> >> >
>> >> > + CoverageSourceInfo *CoverageInfo = nullptr;
>> >> > + // Add the preprocessor callback only when the coverage mapping is
>> >> > generated.
>> >> > + if (CI.getCodeGenOpts().CoverageMapping) {
>> >> > + CoverageInfo = new CoverageSourceInfo;
>> >> > + CI.getPreprocessor().addPPCallbacks(CoverageInfo);
>> >> > + }
>> >> > BEConsumer = new BackendConsumer(BA, CI.getDiagnostics(),
>> >> > CI.getCodeGenOpts(),
>> >> > CI.getTargetOpts(),
>> >> > CI.getLangOpts(),
>> >> > CI.getFrontendOpts().ShowTimers,
>> >> > InFile,
>> >> > - LinkModuleToUse, OS.release(),
>> >> > *VMContext);
>> >> > + LinkModuleToUse, OS.release(),
>> >> > *VMContext,
>> >> > + CoverageInfo);
>> >> > return BEConsumer;
>> >> > }
>> >> >
>> >> >
>> >> > Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
>> >> > URL:
>> >> >
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=214752&r1=214751&r2=214752&view=diff
>> >> >
>> >> >
>> ==============================================================================
>> >> > --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
>> >> > +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Mon Aug 4 13:41:51
>> 2014
>> >> > @@ -829,6 +829,7 @@ void CodeGenFunction::GenerateCode(Globa
>> >> > StartFunction(GD, ResTy, Fn, FnInfo, Args, Loc,
>> >> > BodyRange.getBegin());
>> >> >
>> >> > // Generate the body of the function.
>> >> > + PGO.checkGlobalDecl(GD);
>> >> > PGO.assignRegionCounters(GD.getDecl(), CurFn);
>> >> > if (isa<CXXDestructorDecl>(FD))
>> >> > EmitDestructorBody(Args);
>> >> >
>> >> > Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
>> >> > URL:
>> >> >
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=214752&r1=214751&r2=214752&view=diff
>> >> >
>> >> >
>> ==============================================================================
>> >> > --- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
>> >> > +++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Mon Aug 4 13:41:51 2014
>> >> > @@ -21,6 +21,7 @@
>> >> > #include "CGOpenMPRuntime.h"
>> >> > #include "CodeGenFunction.h"
>> >> > #include "CodeGenPGO.h"
>> >> > +#include "CoverageMappingGen.h"
>> >> > #include "CodeGenTBAA.h"
>> >> > #include "TargetInfo.h"
>> >> > #include "clang/AST/ASTContext.h"
>> >> > @@ -74,7 +75,8 @@ static CGCXXABI *createCXXABI(CodeGenMod
>> >> >
>> >> > CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions
>> &CGO,
>> >> > llvm::Module &M, const llvm::DataLayout
>> >> > &TD,
>> >> > - DiagnosticsEngine &diags)
>> >> > + DiagnosticsEngine &diags,
>> >> > + CoverageSourceInfo *CoverageInfo)
>> >> > : Context(C), LangOpts(C.getLangOpts()), CodeGenOpts(CGO),
>> >> > TheModule(M),
>> >> > Diags(diags), TheDataLayout(TD), Target(C.getTargetInfo()),
>> >> > ABI(createCXXABI(*this)), VMContext(M.getContext()),
>> >> > TBAA(nullptr),
>> >> > @@ -146,6 +148,11 @@ CodeGenModule::CodeGenModule(ASTContext
>> >> > getDiags().Report(DiagID) << EC.message();
>> >> > }
>> >> > }
>> >> > +
>> >> > + // If coverage mapping generation is enabled, create the
>> >> > + // CoverageMappingModuleGen object.
>> >> > + if (CodeGenOpts.CoverageMapping)
>> >> > + CoverageMapping.reset(new CoverageMappingModuleGen(*this,
>> >> > *CoverageInfo));
>> >> > }
>> >> >
>> >> > CodeGenModule::~CodeGenModule() {
>> >> > @@ -344,6 +351,9 @@ void CodeGenModule::Release() {
>> >> > EmitCtorList(GlobalDtors, "llvm.global_dtors");
>> >> > EmitGlobalAnnotations();
>> >> > EmitStaticExternCAliases();
>> >> > + EmitDeferredUnusedCoverageMappings();
>> >> > + if (CoverageMapping)
>> >> > + CoverageMapping->emit();
>> >> > emitLLVMUsed();
>> >> >
>> >> > if (CodeGenOpts.Autolink &&
>> >> > @@ -2989,6 +2999,9 @@ void CodeGenModule::EmitTopLevelDecl(Dec
>> >> > return;
>> >> >
>> >> > EmitGlobal(cast<FunctionDecl>(D));
>> >> > + // Always provide some coverage mapping
>> >> > + // even for the functions that aren't emitted.
>> >> > + AddDeferredUnusedCoverageMapping(D);
>> >> > break;
>> >> >
>> >> > case Decl::Var:
>> >> > @@ -3138,6 +3151,80 @@ void CodeGenModule::EmitTopLevelDecl(Dec
>> >> > }
>> >> > }
>> >> >
>> >> > +void CodeGenModule::AddDeferredUnusedCoverageMapping(Decl *D) {
>> >> > + // Do we need to generate coverage mapping?
>> >> > + if (!CodeGenOpts.CoverageMapping)
>> >> > + return;
>> >> > + switch (D->getKind()) {
>> >> > + case Decl::CXXConversion:
>> >> > + case Decl::CXXMethod:
>> >> > + case Decl::Function:
>> >> > + case Decl::ObjCMethod:
>> >> > + case Decl::CXXConstructor:
>> >> > + case Decl::CXXDestructor: {
>> >> > + if (!cast<FunctionDecl>(D)->hasBody())
>> >> > + return;
>> >> > + auto I = DeferredEmptyCoverageMappingDecls.find(D);
>> >> > + if (I == DeferredEmptyCoverageMappingDecls.end())
>> >> > + DeferredEmptyCoverageMappingDecls[D] = true;
>> >> > + break;
>> >> > + }
>> >> > + default:
>> >> > + break;
>> >> > + };
>> >> > +}
>> >> > +
>> >> > +void CodeGenModule::ClearUnusedCoverageMapping(const Decl *D) {
>> >> > + // Do we need to generate coverage mapping?
>> >> > + if (!CodeGenOpts.CoverageMapping)
>> >> > + return;
>> >> > + if (const auto *Fn = dyn_cast<FunctionDecl>(D)) {
>> >> > + if (Fn->isTemplateInstantiation())
>> >> > +
>> >> > ClearUnusedCoverageMapping(Fn->getTemplateInstantiationPattern());
>> >> > + }
>> >> > + auto I = DeferredEmptyCoverageMappingDecls.find(D);
>> >> > + if (I == DeferredEmptyCoverageMappingDecls.end())
>> >> > + DeferredEmptyCoverageMappingDecls[D] = false;
>> >> > + else
>> >> > + I->second = false;
>> >> > +}
>> >> > +
>> >> > +void CodeGenModule::EmitDeferredUnusedCoverageMappings() {
>> >> > + for (const auto I : DeferredEmptyCoverageMappingDecls) {
>> >> > + if (!I.second)
>> >> > + continue;
>> >> > + const auto *D = I.first;
>> >> > + switch (D->getKind()) {
>> >> > + case Decl::CXXConversion:
>> >> > + case Decl::CXXMethod:
>> >> > + case Decl::Function:
>> >> > + case Decl::ObjCMethod: {
>> >> > + CodeGenPGO PGO(*this);
>> >> > + GlobalDecl GD(cast<FunctionDecl>(D));
>> >> > + PGO.emitEmptyCounterMapping(D, getMangledName(GD),
>> >> > + getFunctionLinkage(GD));
>> >> > + break;
>> >> > + }
>> >> > + case Decl::CXXConstructor: {
>> >> > + CodeGenPGO PGO(*this);
>> >> > + GlobalDecl GD(cast<CXXConstructorDecl>(D), Ctor_Base);
>> >> > + PGO.emitEmptyCounterMapping(D, getMangledName(GD),
>> >> > + getFunctionLinkage(GD));
>> >> > + break;
>> >> > + }
>> >> > + case Decl::CXXDestructor: {
>> >> > + CodeGenPGO PGO(*this);
>> >> > + GlobalDecl GD(cast<CXXDestructorDecl>(D), Dtor_Base);
>> >> > + PGO.emitEmptyCounterMapping(D, getMangledName(GD),
>> >> > + getFunctionLinkage(GD));
>> >> > + break;
>> >> > + }
>> >> > + default:
>> >> > + break;
>> >> > + };
>> >> > + }
>> >> > +}
>> >> > +
>> >> > /// Turns the given pointer into a constant.
>> >> > static llvm::Constant *GetPointerConstant(llvm::LLVMContext
>> &Context,
>> >> > const void *Ptr) {
>> >> >
>> >> > Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
>> >> > URL:
>> >> >
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=214752&r1=214751&r2=214752&view=diff
>> >> >
>> >> >
>> ==============================================================================
>> >> > --- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
>> >> > +++ cfe/trunk/lib/CodeGen/CodeGenModule.h Mon Aug 4 13:41:51 2014
>> >> > @@ -73,6 +73,7 @@ class DiagnosticsEngine;
>> >> > class AnnotateAttr;
>> >> > class CXXDestructorDecl;
>> >> > class Module;
>> >> > +class CoverageSourceInfo;
>> >> >
>> >> > namespace CodeGen {
>> >> >
>> >> > @@ -87,6 +88,7 @@ class CGOpenMPRuntime;
>> >> > class CGCUDARuntime;
>> >> > class BlockFieldFlags;
>> >> > class FunctionArgList;
>> >> > +class CoverageMappingModuleGen;
>> >> >
>> >> > struct OrderGlobalInits {
>> >> > unsigned int priority;
>> >> > @@ -477,10 +479,15 @@ class CodeGenModule : public CodeGenType
>> >> > std::unique_ptr<SanitizerMetadata> SanitizerMD;
>> >> >
>> >> > /// @}
>> >> > +
>> >> > + llvm::DenseMap<const Decl *, bool>
>> DeferredEmptyCoverageMappingDecls;
>> >> > +
>> >> > + std::unique_ptr<CoverageMappingModuleGen> CoverageMapping;
>> >> > public:
>> >> > CodeGenModule(ASTContext &C, const CodeGenOptions &CodeGenOpts,
>> >> > llvm::Module &M, const llvm::DataLayout &TD,
>> >> > - DiagnosticsEngine &Diags);
>> >> > + DiagnosticsEngine &Diags,
>> >> > + CoverageSourceInfo *CoverageInfo = nullptr);
>> >> >
>> >> > ~CodeGenModule();
>> >> >
>> >> > @@ -529,6 +536,10 @@ public:
>> >> > InstrProfStats &getPGOStats() { return PGOStats; }
>> >> > llvm::IndexedInstrProfReader *getPGOReader() const { return
>> >> > PGOReader.get(); }
>> >> >
>> >> > + CoverageMappingModuleGen *getCoverageMapping() const {
>> >> > + return CoverageMapping.get();
>> >> > + }
>> >> > +
>> >> > llvm::Constant *getStaticLocalDeclAddress(const VarDecl *D) {
>> >> > return StaticLocalDeclMap[D];
>> >> > }
>> >> > @@ -815,6 +826,18 @@ public:
>> >> > /// Emit code for a single top level declaration.
>> >> > void EmitTopLevelDecl(Decl *D);
>> >> >
>> >> > + /// \brief Stored a deferred empty coverage mapping for an unused
>> >> > + /// and thus uninstrumented top level declaration.
>> >> > + void AddDeferredUnusedCoverageMapping(Decl *D);
>> >> > +
>> >> > + /// \brief Remove the deferred empty coverage mapping as this
>> >> > + /// declaration is actually instrumented.
>> >> > + void ClearUnusedCoverageMapping(const Decl *D);
>> >> > +
>> >> > + /// \brief Emit all the deferred coverage mappings
>> >> > + /// for the uninstrumented functions.
>> >> > + void EmitDeferredUnusedCoverageMappings();
>> >> > +
>> >> > /// Tell the consumer that this variable has been instantiated.
>> >> > void HandleCXXStaticMemberVarInstantiation(VarDecl *VD);
>> >> >
>> >> >
>> >> > Modified: cfe/trunk/lib/CodeGen/CodeGenPGO.cpp
>> >> > URL:
>> >> >
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenPGO.cpp?rev=214752&r1=214751&r2=214752&view=diff
>> >> >
>> >> >
>> ==============================================================================
>> >> > --- cfe/trunk/lib/CodeGen/CodeGenPGO.cpp (original)
>> >> > +++ cfe/trunk/lib/CodeGen/CodeGenPGO.cpp Mon Aug 4 13:41:51 2014
>> >> > @@ -13,6 +13,7 @@
>> >> >
>> >> > #include "CodeGenPGO.h"
>> >> > #include "CodeGenFunction.h"
>> >> > +#include "CoverageMappingGen.h"
>> >> > #include "clang/AST/RecursiveASTVisitor.h"
>> >> > #include "clang/AST/StmtVisitor.h"
>> >> > #include "llvm/IR/MDBuilder.h"
>> >> > @@ -24,8 +25,9 @@
>> >> > using namespace clang;
>> >> > using namespace CodeGen;
>> >> >
>> >> > -void CodeGenPGO::setFuncName(llvm::Function *Fn) {
>> >> > - RawFuncName = Fn->getName();
>> >> > +void CodeGenPGO::setFuncName(StringRef Name,
>> >> > + llvm::GlobalValue::LinkageTypes
>> Linkage) {
>> >> > + RawFuncName = Name;
>> >> >
>> >> > // Function names may be prefixed with a binary '1' to indicate
>> >> > // that the backend should not modify the symbols due to any
>> platform
>> >> > @@ -33,7 +35,7 @@ void CodeGenPGO::setFuncName(llvm::Funct
>> >> > if (RawFuncName[0] == '\1')
>> >> > RawFuncName = RawFuncName.substr(1);
>> >> >
>> >> > - if (!Fn->hasLocalLinkage()) {
>> >> > + if (!llvm::GlobalValue::isLocalLinkage(Linkage)) {
>> >> > PrefixedFuncName.reset(new std::string(RawFuncName));
>> >> > return;
>> >> > }
>> >> > @@ -49,6 +51,27 @@ void CodeGenPGO::setFuncName(llvm::Funct
>> >> > PrefixedFuncName->append(RawFuncName);
>> >> > }
>> >> >
>> >> > +void CodeGenPGO::setFuncName(llvm::Function *Fn) {
>> >> > + setFuncName(Fn->getName(), Fn->getLinkage());
>> >> > +}
>> >> > +
>> >> > +void CodeGenPGO::setVarLinkage(llvm::GlobalValue::LinkageTypes
>> Linkage)
>> >> > {
>> >> > + // Set the linkage for variables based on the function linkage.
>> >> > Usually, we
>> >> > + // want to match it, but available_externally and extern_weak both
>> >> > have the
>> >> > + // wrong semantics.
>> >> > + VarLinkage = Linkage;
>> >> > + switch (VarLinkage) {
>> >> > + case llvm::GlobalValue::ExternalWeakLinkage:
>> >> > + VarLinkage = llvm::GlobalValue::LinkOnceAnyLinkage;
>> >> > + break;
>> >> > + case llvm::GlobalValue::AvailableExternallyLinkage:
>> >> > + VarLinkage = llvm::GlobalValue::LinkOnceODRLinkage;
>> >> > + break;
>> >> > + default:
>> >> > + break;
>> >> > + }
>> >> > +}
>> >> > +
>> >> > static llvm::Function *getRegisterFunc(CodeGenModule &CGM) {
>> >> > return
>> >> > CGM.getModule().getFunction("__llvm_profile_register_functions");
>> >> > }
>> >> > @@ -120,37 +143,48 @@ llvm::GlobalVariable *CodeGenPGO::buildD
>> >> > auto *Int64Ty = llvm::Type::getInt64Ty(Ctx);
>> >> > auto *Int8PtrTy = llvm::Type::getInt8PtrTy(Ctx);
>> >> > auto *Int64PtrTy = llvm::Type::getInt64PtrTy(Ctx);
>> >> > - llvm::Type *DataTypes[] = {
>> >> > - Int32Ty, Int32Ty, Int64Ty, Int8PtrTy, Int64PtrTy
>> >> > - };
>> >> > - auto *DataTy = llvm::StructType::get(Ctx,
>> makeArrayRef(DataTypes));
>> >> > - llvm::Constant *DataVals[] = {
>> >> > - llvm::ConstantInt::get(Int32Ty, getFuncName().size()),
>> >> > - llvm::ConstantInt::get(Int32Ty, NumRegionCounters),
>> >> > - llvm::ConstantInt::get(Int64Ty, FunctionHash),
>> >> > - llvm::ConstantExpr::getBitCast(Name, Int8PtrTy),
>> >> > - llvm::ConstantExpr::getBitCast(RegionCounters, Int64PtrTy)
>> >> > - };
>> >> > - auto *Data =
>> >> > - new llvm::GlobalVariable(CGM.getModule(), DataTy, true,
>> VarLinkage,
>> >> > - llvm::ConstantStruct::get(DataTy,
>> >> > DataVals),
>> >> > - getFuncVarName("data"));
>> >> > -
>> >> > - // All the data should be packed into an array in its own section.
>> >> > - Data->setSection(getDataSection(CGM));
>> >> > - Data->setAlignment(8);
>> >> > + llvm::GlobalVariable *Data = nullptr;
>> >> > + if (RegionCounters) {
>> >> > + llvm::Type *DataTypes[] = {
>> >> > + Int32Ty, Int32Ty, Int64Ty, Int8PtrTy, Int64PtrTy
>> >> > + };
>> >> > + auto *DataTy = llvm::StructType::get(Ctx,
>> makeArrayRef(DataTypes));
>> >> > + llvm::Constant *DataVals[] = {
>> >> > + llvm::ConstantInt::get(Int32Ty, getFuncName().size()),
>> >> > + llvm::ConstantInt::get(Int32Ty, NumRegionCounters),
>> >> > + llvm::ConstantInt::get(Int64Ty, FunctionHash),
>> >> > + llvm::ConstantExpr::getBitCast(Name, Int8PtrTy),
>> >> > + llvm::ConstantExpr::getBitCast(RegionCounters, Int64PtrTy)
>> >> > + };
>> >> > + Data =
>> >> > + new llvm::GlobalVariable(CGM.getModule(), DataTy, true,
>> >> > VarLinkage,
>> >> > + llvm::ConstantStruct::get(DataTy,
>> >> > DataVals),
>> >> > + getFuncVarName("data"));
>> >> > +
>> >> > + // All the data should be packed into an array in its own
>> section.
>> >> > + Data->setSection(getDataSection(CGM));
>> >> > + Data->setAlignment(8);
>> >> > + }
>> >> > +
>> >> > + // Create coverage mapping data variable.
>> >> > + if (!CoverageMapping.empty())
>> >> > + CGM.getCoverageMapping()->addFunctionMappingRecord(Name,
>> >> > +
>> >> > getFuncName().size(),
>> >> > +
>> >> > CoverageMapping);
>> >> >
>> >> > // Hide all these symbols so that we correctly get a copy for each
>> >> > // executable. The profile format expects names and counters to
>> be
>> >> > // contiguous, so references into shared objects would be invalid.
>> >> > if (!llvm::GlobalValue::isLocalLinkage(VarLinkage)) {
>> >> > Name->setVisibility(llvm::GlobalValue::HiddenVisibility);
>> >> > - Data->setVisibility(llvm::GlobalValue::HiddenVisibility);
>> >> > -
>> RegionCounters->setVisibility(llvm::GlobalValue::HiddenVisibility);
>> >> > + if (Data) {
>> >> > + Data->setVisibility(llvm::GlobalValue::HiddenVisibility);
>> >> > +
>> >> > RegionCounters->setVisibility(llvm::GlobalValue::HiddenVisibility);
>> >> > + }
>> >> > }
>> >> >
>> >> > // Make sure the data doesn't get deleted.
>> >> > - CGM.addUsedGlobal(Data);
>> >> > + if (Data) CGM.addUsedGlobal(Data);
>> >> > return Data;
>> >> > }
>> >> >
>> >> > @@ -807,6 +841,20 @@ static void emitRuntimeHook(CodeGenModul
>> >> > CGM.addUsedGlobal(User);
>> >> > }
>> >> >
>> >> > +void CodeGenPGO::checkGlobalDecl(GlobalDecl GD) {
>> >> > + // Make sure we only emit coverage mapping for one
>> >> > constructor/destructor.
>> >> > + // Clang emits several functions for the constructor and the
>> >> > destructor of
>> >> > + // a class. Every function is instrumented, but we only want to
>> >> > provide
>> >> > + // coverage for one of them. Because of that we only emit the
>> >> > coverage mapping
>> >> > + // for the base constructor/destructor.
>> >> > + if ((isa<CXXConstructorDecl>(GD.getDecl()) &&
>> >> > + GD.getCtorType() != Ctor_Base) ||
>> >> > + (isa<CXXDestructorDecl>(GD.getDecl()) &&
>> >> > + GD.getDtorType() != Dtor_Base)) {
>> >> > + SkipCoverageMapping = true;
>> >> > + }
>> >> > +}
>> >> > +
>> >> > void CodeGenPGO::assignRegionCounters(const Decl *D, llvm::Function
>> >> > *Fn) {
>> >> > bool InstrumentRegions =
>> CGM.getCodeGenOpts().ProfileInstrGenerate;
>> >> > llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
>> >> > @@ -814,27 +862,16 @@ void CodeGenPGO::assignRegionCounters(co
>> >> > return;
>> >> > if (D->isImplicit())
>> >> > return;
>> >> > + CGM.ClearUnusedCoverageMapping(D);
>> >> > setFuncName(Fn);
>> >> > -
>> >> > - // Set the linkage for variables based on the function linkage.
>> >> > Usually, we
>> >> > - // want to match it, but available_externally and extern_weak both
>> >> > have the
>> >> > - // wrong semantics.
>> >> > - VarLinkage = Fn->getLinkage();
>> >> > - switch (VarLinkage) {
>> >> > - case llvm::GlobalValue::ExternalWeakLinkage:
>> >> > - VarLinkage = llvm::GlobalValue::LinkOnceAnyLinkage;
>> >> > - break;
>> >> > - case llvm::GlobalValue::AvailableExternallyLinkage:
>> >> > - VarLinkage = llvm::GlobalValue::LinkOnceODRLinkage;
>> >> > - break;
>> >> > - default:
>> >> > - break;
>> >> > - }
>> >> > + setVarLinkage(Fn->getLinkage());
>> >> >
>> >> > mapRegionCounters(D);
>> >> > if (InstrumentRegions) {
>> >> > emitRuntimeHook(CGM);
>> >> > emitCounterVariables();
>> >> > + if (CGM.getCodeGenOpts().CoverageMapping)
>> >> > + emitCounterRegionMapping(D);
>> >> > }
>> >> > if (PGOReader) {
>> >> > SourceManager &SM = CGM.getContext().getSourceManager();
>> >> > @@ -860,6 +897,45 @@ void CodeGenPGO::mapRegionCounters(const
>> >> > FunctionHash = Walker.Hash.finalize();
>> >> > }
>> >> >
>> >> > +void CodeGenPGO::emitCounterRegionMapping(const Decl *D) {
>> >> > + if (SkipCoverageMapping)
>> >> > + return;
>> >> > + // Don't map the functions inside the system headers
>> >> > + auto Loc = D->getBody()->getLocStart();
>> >> > + if (CGM.getContext().getSourceManager().isInSystemHeader(Loc))
>> >> > + return;
>> >> > +
>> >> > + llvm::raw_string_ostream OS(CoverageMapping);
>> >> > + CoverageMappingGen MappingGen(*CGM.getCoverageMapping(),
>> >> > + CGM.getContext().getSourceManager(),
>> >> > + CGM.getLangOpts(),
>> >> > RegionCounterMap.get(),
>> >> > + NumRegionCounters);
>> >> > + MappingGen.emitCounterMapping(D, OS);
>> >> > + OS.flush();
>> >> > +}
>> >> > +
>> >> > +void
>> >> > +CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef
>> FuncName,
>> >> > + llvm::GlobalValue::LinkageTypes
>> >> > Linkage) {
>> >> > + if (SkipCoverageMapping)
>> >> > + return;
>> >> > + setFuncName(FuncName, Linkage);
>> >> > + setVarLinkage(Linkage);
>> >> > +
>> >> > + // Don't map the functions inside the system headers
>> >> > + auto Loc = D->getBody()->getLocStart();
>> >> > + if (CGM.getContext().getSourceManager().isInSystemHeader(Loc))
>> >> > + return;
>> >> > +
>> >> > + llvm::raw_string_ostream OS(CoverageMapping);
>> >> > + CoverageMappingGen MappingGen(*CGM.getCoverageMapping(),
>> >> > + CGM.getContext().getSourceManager(),
>> >> > + CGM.getLangOpts());
>> >> > + MappingGen.emitEmptyMapping(D, OS);
>> >> > + OS.flush();
>> >> > + buildDataVar();
>> >> > +}
>> >> > +
>> >> > void CodeGenPGO::computeRegionCounts(const Decl *D) {
>> >> > StmtCountMap.reset(new llvm::DenseMap<const Stmt *, uint64_t>);
>> >> > ComputeRegionCounts Walker(*StmtCountMap, *this);
>> >> >
>> >> > Modified: cfe/trunk/lib/CodeGen/CodeGenPGO.h
>> >> > URL:
>> >> >
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenPGO.h?rev=214752&r1=214751&r2=214752&view=diff
>> >> >
>> >> >
>> ==============================================================================
>> >> > --- cfe/trunk/lib/CodeGen/CodeGenPGO.h (original)
>> >> > +++ cfe/trunk/lib/CodeGen/CodeGenPGO.h Mon Aug 4 13:41:51 2014
>> >> > @@ -42,11 +42,16 @@ private:
>> >> > std::unique_ptr<llvm::DenseMap<const Stmt *, uint64_t>>
>> StmtCountMap;
>> >> > std::unique_ptr<std::vector<uint64_t>> RegionCounts;
>> >> > uint64_t CurrentRegionCount;
>> >> > + std::string CoverageMapping;
>> >> > + /// \brief A flag that is set to true when this function doesn't
>> need
>> >> > + /// to have coverage mapping data.
>> >> > + bool SkipCoverageMapping;
>> >> >
>> >> > public:
>> >> > CodeGenPGO(CodeGenModule &CGM)
>> >> > : CGM(CGM), NumRegionCounters(0), FunctionHash(0),
>> >> > - RegionCounters(nullptr), CurrentRegionCount(0) {}
>> >> > + RegionCounters(nullptr), CurrentRegionCount(0),
>> >> > + SkipCoverageMapping(false) {}
>> >> >
>> >> > /// Whether or not we have PGO region data for the current
>> function.
>> >> > This is
>> >> > /// false both when we have no data at all and when our data has
>> been
>> >> > @@ -99,6 +104,8 @@ public:
>> >> > llvm::MDNode *createBranchWeights(ArrayRef<uint64_t> Weights);
>> >> > llvm::MDNode *createLoopWeights(const Stmt *Cond, RegionCounter
>> >> > &Cnt);
>> >> >
>> >> > + /// Check if we need to emit coverage mapping for a given
>> declaration
>> >> > + void checkGlobalDecl(GlobalDecl GD);
>> >> > /// Assign counters to regions and configure them for PGO of a
>> given
>> >> > /// function. Does nothing if instrumentation is not enabled and
>> >> > either
>> >> > /// generates global variables or associates PGO data with each of
>> >> > the
>> >> > @@ -111,9 +118,14 @@ public:
>> >> > void destroyRegionCounters();
>> >> > /// Emit static initialization code, if any.
>> >> > static llvm::Function *emitInitialization(CodeGenModule &CGM);
>> >> > -
>> >> > + /// Emit a coverage mapping range with a counter zero
>> >> > + /// for an unused declaration.
>> >> > + void emitEmptyCounterMapping(const Decl *D, StringRef FuncName,
>> >> > + llvm::GlobalValue::LinkageTypes
>> >> > Linkage);
>> >> > private:
>> >> > void setFuncName(llvm::Function *Fn);
>> >> > + void setFuncName(StringRef Name, llvm::GlobalValue::LinkageTypes
>> >> > Linkage);
>> >> > + void setVarLinkage(llvm::GlobalValue::LinkageTypes Linkage);
>> >> > void mapRegionCounters(const Decl *D);
>> >> > void computeRegionCounts(const Decl *D);
>> >> > void applyFunctionAttributes(llvm::IndexedInstrProfReader
>> *PGOReader,
>> >> > @@ -122,6 +134,7 @@ private:
>> >> > bool IsInMainFile);
>> >> > void emitCounterVariables();
>> >> > llvm::GlobalVariable *buildDataVar();
>> >> > + void emitCounterRegionMapping(const Decl *D);
>> >> >
>> >> > /// Emit code to increment the counter at the given index
>> >> > void emitCounterIncrement(CGBuilderTy &Builder, unsigned Counter);
>> >> >
>> >> > Added: cfe/trunk/lib/CodeGen/CoverageMappingGen.cpp
>> >> > URL:
>> >> >
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CoverageMappingGen.cpp?rev=214752&view=auto
>> >> >
>> >> >
>> ==============================================================================
>> >> > --- cfe/trunk/lib/CodeGen/CoverageMappingGen.cpp (added)
>> >> > +++ cfe/trunk/lib/CodeGen/CoverageMappingGen.cpp Mon Aug 4 13:41:51
>> >> > 2014
>> >> > @@ -0,0 +1,1166 @@
>> >> > +//===--- CoverageMappingGen.cpp - Coverage mapping generation ---*-
>> C++
>> >> > -*-===//
>> >> > +//
>> >> > +// The LLVM Compiler Infrastructure
>> >> > +//
>> >> > +// This file is distributed under the University of Illinois Open
>> >> > Source
>> >> > +// License. See LICENSE.TXT for details.
>> >> > +//
>> >> >
>> >> >
>> +//===----------------------------------------------------------------------===//
>> >> > +//
>> >> > +// Instrumentation-based code coverage mapping generator
>> >> > +//
>> >> >
>> >> >
>> +//===----------------------------------------------------------------------===//
>> >> > +
>> >> > +#include "CoverageMappingGen.h"
>> >> > +#include "CodeGenFunction.h"
>> >> > +#include "clang/AST/StmtVisitor.h"
>> >> > +#include "clang/Lex/Lexer.h"
>> >> > +#include "llvm/ProfileData/InstrProfReader.h"
>> >> > +#include "llvm/ProfileData/CoverageMapping.h"
>> >> > +#include "llvm/ProfileData/CoverageMappingWriter.h"
>> >> > +#include "llvm/Support/FileSystem.h"
>> >> > +
>> >> > +using namespace clang;
>> >> > +using namespace CodeGen;
>> >> > +using namespace llvm::coverage;
>> >> > +
>> >> > +void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range) {
>> >> > + SkippedRanges.push_back(Range);
>> >> > +}
>> >> > +
>> >> > +namespace {
>> >> > +
>> >> > +/// \brief A region of source code that can be mapped to a counter.
>> >> > +struct SourceMappingRegion {
>> >> > + enum RegionFlags {
>> >> > + /// \brief This region won't be emitted if it wasn't extended.
>> >> > + /// This is useful so that we won't emit source ranges for
>> single
>> >> > tokens
>> >> > + /// that we don't really care that much about, like:
>> >> > + /// the '(' token in #define MACRO (
>> >> > + IgnoreIfNotExtended = 0x0001,
>> >> > + };
>> >> > +
>> >> > + FileID File, MacroArgumentFile;
>> >> > +
>> >> > + Counter Count;
>> >> > +
>> >> > + /// \brief A statement that initiated the count of Zero.
>> >> > + ///
>> >> > + /// This initiator statement is useful to prevent merging of
>> >> > unreachable
>> >> > + /// regions with different statements that caused the counter to
>> >> > become
>> >> > + /// unreachable.
>> >> > + const Stmt *UnreachableInitiator;
>> >> > +
>> >> > + /// \brief A statement that separates certain mapping regions into
>> >> > groups.
>> >> > + ///
>> >> > + /// The group statement is sometimes useful when we are emitting
>> the
>> >> > source
>> >> > + /// regions not in their correct lexical order, e.g. the regions
>> for
>> >> > the
>> >> > + /// incrementation expression in the 'for' construct. By marking
>> the
>> >> > regions
>> >> > + /// in the incrementation expression with the group statement, we
>> >> > avoid the
>> >> > + /// merging of the regions from the incrementation expression and
>> the
>> >> > loop's
>> >> > + /// body.
>> >> > + const Stmt *Group;
>> >> > +
>> >> > + /// \brief The region's starting location.
>> >> > + SourceLocation LocStart;
>> >> > +
>> >> > + /// \brief The region's ending location.
>> >> > + SourceLocation LocEnd, AlternativeLocEnd;
>> >> > + unsigned Flags;
>> >> > + CounterMappingRegion::RegionKind Kind;
>> >> > +
>> >> > + SourceMappingRegion(FileID File, FileID MacroArgumentFile, Counter
>> >> > Count,
>> >> > + const Stmt *UnreachableInitiator, const Stmt
>> >> > *Group,
>> >> > + SourceLocation LocStart, SourceLocation
>> LocEnd,
>> >> > + unsigned Flags = 0,
>> >> > + CounterMappingRegion::RegionKind Kind =
>> >> > + CounterMappingRegion::CodeRegion)
>> >> > + : File(File), MacroArgumentFile(MacroArgumentFile),
>> Count(Count),
>> >> > + UnreachableInitiator(UnreachableInitiator), Group(Group),
>> >> > + LocStart(LocStart), LocEnd(LocEnd),
>> >> > AlternativeLocEnd(LocStart),
>> >> > + Flags(Flags), Kind(Kind) {}
>> >> > +
>> >> > + bool hasFlag(RegionFlags Flag) const { return (Flags & Flag) !=
>> 0; }
>> >> > +
>> >> > + void setFlag(RegionFlags Flag) { Flags |= Flag; }
>> >> > +
>> >> > + void clearFlag(RegionFlags Flag) { Flags &= ~Flag; }
>> >> > +
>> >> > + /// \brief Return true if two regions can be merged together.
>> >> > + bool isMergeable(SourceMappingRegion &R) {
>> >> > + return File == R.File && MacroArgumentFile ==
>> R.MacroArgumentFile
>> >> > &&
>> >> > + Count == R.Count && UnreachableInitiator ==
>> >> > R.UnreachableInitiator &&
>> >> > + Group == R.Group && Kind == R.Kind;
>> >> > + }
>> >> > +
>> >> > + /// \brief Merge two regions by extending the 'this' region to
>> cover
>> >> > the
>> >> > + /// given region.
>> >> > + void mergeByExtendingTo(SourceMappingRegion &R) {
>> >> > + LocEnd = R.LocEnd;
>> >> > + AlternativeLocEnd = R.LocStart;
>> >> > + if (hasFlag(IgnoreIfNotExtended))
>> >> > + clearFlag(IgnoreIfNotExtended);
>> >> > + }
>> >> > +};
>> >> > +
>> >> > +/// \brief The state of the coverage mapping builder.
>> >> > +struct SourceMappingState {
>> >> > + Counter CurrentRegionCount;
>> >> > + const Stmt *CurrentSourceGroup;
>> >> > + const Stmt *CurrentUnreachableRegionInitiator;
>> >> > +
>> >> > + SourceMappingState(Counter CurrentRegionCount, const Stmt
>> >> > *CurrentSourceGroup,
>> >> > + const Stmt *CurrentUnreachableRegionInitiator)
>> >> > + : CurrentRegionCount(CurrentRegionCount),
>> >> > + CurrentSourceGroup(CurrentSourceGroup),
>> >> > +
>> >> > CurrentUnreachableRegionInitiator(CurrentUnreachableRegionInitiator)
>> {}
>> >> > +};
>> >> > +
>> >> > +/// \brief Provides the common functionality for the different
>> >> > +/// coverage mapping region builders.
>> >> > +class CoverageMappingBuilder {
>> >> > +public:
>> >> > + CoverageMappingModuleGen &CVM;
>> >> > + SourceManager &SM;
>> >> > + const LangOptions &LangOpts;
>> >> > +
>> >> > +private:
>> >> > + struct FileInfo {
>> >> > + /// \brief The file id that will be used by the coverage mapping
>> >> > system.
>> >> > + unsigned CovMappingFileID;
>> >> > + const FileEntry *Entry;
>> >> > +
>> >> > + FileInfo(unsigned CovMappingFileID, const FileEntry *Entry)
>> >> > + : CovMappingFileID(CovMappingFileID), Entry(Entry) {}
>> >> > + };
>> >> > +
>> >> > + /// \brief This mapping maps clang's FileIDs to file ids used
>> >> > + /// by the coverage mapping system and clang's file entries.
>> >> > + llvm::SmallDenseMap<FileID, FileInfo, 8> FileIDMapping;
>> >> > +
>> >> > +public:
>> >> > + /// \brief The statement that corresponds to the current source
>> >> > group.
>> >> > + const Stmt *CurrentSourceGroup;
>> >> > +
>> >> > + /// \brief The statement the initiated the current unreachable
>> >> > region.
>> >> > + const Stmt *CurrentUnreachableRegionInitiator;
>> >> > +
>> >> > + /// \brief The coverage mapping regions for this function
>> >> > + llvm::SmallVector<CounterMappingRegion, 32> MappingRegions;
>> >> > + /// \brief The source mapping regions for this function.
>> >> > + llvm::SmallVector<SourceMappingRegion, 32> SourceRegions;
>> >> > +
>> >> > + CoverageMappingBuilder(CoverageMappingModuleGen &CVM,
>> SourceManager
>> >> > &SM,
>> >> > + const LangOptions &LangOpts)
>> >> > + : CVM(CVM), SM(SM), LangOpts(LangOpts),
>> >> > + CurrentSourceGroup(nullptr),
>> >> > + CurrentUnreachableRegionInitiator(nullptr) {}
>> >> > +
>> >> > + /// \brief Return the precise end location for the given token.
>> >> > + SourceLocation getPreciseTokenLocEnd(SourceLocation Loc) {
>> >> > + return Lexer::getLocForEndOfToken(SM.getSpellingLoc(Loc), 0, SM,
>> >> > LangOpts);
>> >> > + }
>> >> > +
>> >> > + /// \brief Create the mapping that maps from the function's file
>> ids
>> >> > to
>> >> > + /// the indices for the translation unit's filenames.
>> >> > + void createFileIDMapping(SmallVectorImpl<unsigned> &Mapping) {
>> >> > + Mapping.resize(FileIDMapping.size(), 0);
>> >> > + for (const auto &I : FileIDMapping)
>> >> > + Mapping[I.second.CovMappingFileID] =
>> >> > CVM.getFileID(I.second.Entry);
>> >> > + }
>> >> > +
>> >> > + /// \brief Get the coverage mapping file id that corresponds to
>> the
>> >> > given
>> >> > + /// clang file id. If such file id doesn't exist, it gets added to
>> >> > the
>> >> > + /// mapping that maps from clang's file ids to coverage mapping
>> file
>> >> > ids.
>> >> > + /// Return true if there was an error getting the coverage mapping
>> >> > file id.
>> >> > + /// An example of an when this function fails is when the region
>> >> > tries
>> >> > + /// to get a coverage file id for a location in a built-in macro.
>> >> > + bool getCoverageFileID(SourceLocation LocStart, FileID File,
>> >> > + FileID SpellingFile, unsigned &Result) {
>> >> > + auto Mapping = FileIDMapping.find(File);
>> >> > + if (Mapping != FileIDMapping.end()) {
>> >> > + Result = Mapping->second.CovMappingFileID;
>> >> > + return false;
>> >> > + }
>> >> > +
>> >> > + auto Entry = SM.getFileEntryForID(SpellingFile);
>> >> > + if (!Entry)
>> >> > + return true;
>> >> > +
>> >> > + Result = FileIDMapping.size();
>> >> > + FileIDMapping.insert(std::make_pair(File, FileInfo(Result,
>> >> > Entry)));
>> >> > + createFileExpansionRegion(LocStart, File);
>> >> > + return false;
>> >> > + }
>> >> > +
>> >> > + /// \brief Get the coverage mapping file id that corresponds to
>> the
>> >> > given
>> >> > + /// clang file id.
>> >> > + /// Return true if there was an error getting the coverage mapping
>> >> > file id.
>> >> > + bool getExistingCoverageFileID(FileID File, unsigned &Result) {
>> >> > + // Make sure that the file is valid.
>> >> > + if (File.isInvalid())
>> >> > + return true;
>> >> > + auto Mapping = FileIDMapping.find(File);
>> >> > + if (Mapping != FileIDMapping.end()) {
>> >> > + Result = Mapping->second.CovMappingFileID;
>> >> > + return false;
>> >> > + }
>> >> > + return true;
>> >> > + }
>> >> > +
>> >> > + /// \brief Return true if the given clang's file id has a
>> >> > corresponding
>> >> > + /// coverage file id.
>> >> > + bool hasExistingCoverageFileID(FileID File) const {
>> >> > + return FileIDMapping.count(File);
>> >> > + }
>> >> > +
>> >> > + /// \brief Gather all the regions that were skipped by the
>> >> > preprocessor
>> >> > + /// using the constructs like #if.
>> >> > + void gatherSkippedRegions() {
>> >> > + /// An array of the minimum lineStarts and the maximum lineEnds
>> >> > + /// for mapping regions from the appropriate source files.
>> >> > + llvm::SmallVector<std::pair<unsigned, unsigned>, 8>
>> FileLineRanges;
>> >> > + FileLineRanges.resize(
>> >> > + FileIDMapping.size(),
>> >> > + std::make_pair(std::numeric_limits<unsigned>::max(), 0));
>> >> > + for (const auto &R : MappingRegions) {
>> >> > + FileLineRanges[R.FileID].first =
>> >> > + std::min(FileLineRanges[R.FileID].first, R.LineStart);
>> >> > + FileLineRanges[R.FileID].second =
>> >> > + std::max(FileLineRanges[R.FileID].second, R.LineEnd);
>> >> > + }
>> >> > +
>> >> > + auto SkippedRanges = CVM.getSourceInfo().getSkippedRanges();
>> >> > + for (const auto &I : SkippedRanges) {
>> >> > + auto LocStart = I.getBegin();
>> >> > + auto LocEnd = I.getEnd();
>> >> > + auto FileStart = SM.getFileID(LocStart);
>> >> > + if (!hasExistingCoverageFileID(FileStart))
>> >> > + continue;
>> >> > + auto ActualFileStart =
>> >> > SM.getDecomposedSpellingLoc(LocStart).first;
>> >> > + if (ActualFileStart !=
>> SM.getDecomposedSpellingLoc(LocEnd).first)
>> >> > + // Ignore regions that span across multiple files.
>> >> > + continue;
>> >> > +
>> >> > + unsigned CovFileID;
>> >> > + if (getCoverageFileID(LocStart, FileStart, ActualFileStart,
>> >> > CovFileID))
>> >> > + continue;
>> >> > + unsigned LineStart = SM.getSpellingLineNumber(LocStart);
>> >> > + unsigned ColumnStart = SM.getSpellingColumnNumber(LocStart);
>> >> > + unsigned LineEnd = SM.getSpellingLineNumber(LocEnd);
>> >> > + unsigned ColumnEnd = SM.getSpellingColumnNumber(LocEnd);
>> >> > + CounterMappingRegion Region(Counter(), CovFileID, LineStart,
>> >> > ColumnStart,
>> >> > + LineEnd, ColumnEnd, false,
>> >> > +
>> CounterMappingRegion::SkippedRegion);
>> >> > + // Make sure that we only collect the regions that are inside
>> >> > + // the souce code of this function.
>> >> > + if (Region.LineStart >= FileLineRanges[CovFileID].first &&
>> >> > + Region.LineEnd <= FileLineRanges[CovFileID].second)
>> >> > + MappingRegions.push_back(Region);
>> >> > + }
>> >> > + }
>> >> > +
>> >> > + /// \brief Create a mapping region that correponds to an
>> expansion of
>> >> > + /// a macro or an embedded include.
>> >> > + void createFileExpansionRegion(SourceLocation Loc, FileID
>> >> > ExpandedFile) {
>> >> > + SourceLocation LocStart;
>> >> > + if (Loc.isMacroID())
>> >> > + LocStart = SM.getImmediateExpansionRange(Loc).first;
>> >> > + else {
>> >> > + LocStart = SM.getIncludeLoc(ExpandedFile);
>> >> > + if (LocStart.isInvalid())
>> >> > + return; // This file has no expansion region.
>> >> > + }
>> >> > +
>> >> > + auto File = SM.getFileID(LocStart);
>> >> > + auto SpellingFile = SM.getDecomposedSpellingLoc(LocStart).first;
>> >> > + unsigned CovFileID, ExpandedFileID;
>> >> > + if (getExistingCoverageFileID(ExpandedFile, ExpandedFileID))
>> >> > + return;
>> >> > + if (getCoverageFileID(LocStart, File, SpellingFile, CovFileID))
>> >> > + return;
>> >> > + unsigned LineStart = SM.getSpellingLineNumber(LocStart);
>> >> > + unsigned ColumnStart = SM.getSpellingColumnNumber(LocStart);
>> >> > + unsigned LineEnd = LineStart;
>> >> > + // Compute the end column manually as Lexer::getLocForEndOfToken
>> >> > doesn't
>> >> > + // give the correct result in all cases.
>> >> > + unsigned ColumnEnd =
>> >> > + ColumnStart +
>> >> > + Lexer::MeasureTokenLength(SM.getSpellingLoc(LocStart), SM,
>> >> > LangOpts);
>> >> > +
>> >> > + MappingRegions.push_back(CounterMappingRegion(
>> >> > + Counter(), CovFileID, LineStart, ColumnStart, LineEnd,
>> >> > ColumnEnd,
>> >> > + false, CounterMappingRegion::ExpansionRegion));
>> >> > + MappingRegions.back().ExpandedFileID = ExpandedFileID;
>> >> > + }
>> >> > +
>> >> > + /// \brief Enter a source region group that is identified by the
>> >> > given
>> >> > + /// statement.
>> >> > + /// It's not possible to enter a group when there is already
>> >> > + /// another group present.
>> >> > + void beginSourceRegionGroup(const Stmt *Group) {
>> >> > + assert(!CurrentSourceGroup);
>> >> > + CurrentSourceGroup = Group;
>> >> > + }
>> >> > +
>> >> > + /// \brief Exit the current source region group.
>> >> > + void endSourceRegionGroup() { CurrentSourceGroup = nullptr; }
>> >> > +
>> >> > + /// \brief Brings a region that has the same counter and file to
>> the
>> >> > back
>> >> > + /// of the source regions array.
>> >> > + void bringSimilarRegionBack(Counter Count, FileID File,
>> >> > + FileID MacroArgumentFile,
>> >> > + const Stmt *UnreachableInitiator,
>> >> > + const Stmt *SourceGroup) {
>> >> > + for (size_t I = SourceRegions.size(); I != 0;) {
>> >> > + --I;
>> >> > + if (SourceRegions[I].Count == Count && SourceRegions[I].File
>> ==
>> >> > File &&
>> >> > + SourceRegions[I].MacroArgumentFile == MacroArgumentFile &&
>> >> > + SourceRegions[I].UnreachableInitiator ==
>> UnreachableInitiator
>> >> > &&
>> >> > + SourceRegions[I].Group == SourceGroup) {
>> >> > + if (I != SourceRegions.size() - 1)
>> >> > + std::swap(SourceRegions[I], SourceRegions.back());
>> >> > + return;
>> >> > + }
>> >> > + }
>> >> > + }
>> >> > +
>> >> > + /// \brief Associate a counter with a given source code range.
>> >> > + void mapSourceCodeRange(SourceLocation LocStart, SourceLocation
>> >> > LocEnd,
>> >> > + Counter Count, const Stmt
>> >> > *UnreachableInitiator,
>> >> > + const Stmt *SourceGroup, unsigned Flags =
>> 0,
>> >> > + FileID MacroArgumentFile = FileID()) {
>> >> > + if (SM.isMacroArgExpansion(LocStart)) {
>> >> > + // Map the code range with the macro argument's value.
>> >> > + mapSourceCodeRange(SM.getImmediateSpellingLoc(LocStart),
>> >> > + SM.getImmediateSpellingLoc(LocEnd), Count,
>> >> > + UnreachableInitiator, SourceGroup, Flags,
>> >> > + SM.getFileID(LocStart));
>> >> > + // Map the code range where the macro argument is referenced.
>> >> > + SourceLocation
>> >> > RefLocStart(SM.getImmediateExpansionRange(LocStart).first);
>> >> > + SourceLocation RefLocEnd(RefLocStart);
>> >> > + if (SM.isMacroArgExpansion(RefLocStart))
>> >> > + mapSourceCodeRange(RefLocStart, RefLocEnd, Count,
>> >> > UnreachableInitiator,
>> >> > + SourceGroup, 0,
>> SM.getFileID(RefLocStart));
>> >> > + else
>> >> > + mapSourceCodeRange(RefLocStart, RefLocEnd, Count,
>> >> > UnreachableInitiator,
>> >> > + SourceGroup);
>> >> > + return;
>> >> > + }
>> >> > + auto File = SM.getFileID(LocStart);
>> >> > + // Make sure that the file id is valid.
>> >> > + if (File.isInvalid())
>> >> > + return;
>> >> > + bringSimilarRegionBack(Count, File, MacroArgumentFile,
>> >> > UnreachableInitiator,
>> >> > + SourceGroup);
>> >> > + SourceMappingRegion R(File, MacroArgumentFile, Count,
>> >> > UnreachableInitiator,
>> >> > + SourceGroup, LocStart, LocEnd, Flags);
>> >> > + if (SourceRegions.empty() ||
>> !SourceRegions.back().isMergeable(R))
>> >> > {
>> >> > + SourceRegions.push_back(R);
>> >> > + return;
>> >> > + }
>> >> > + SourceRegions.back().mergeByExtendingTo(R);
>> >> > + }
>> >> > +
>> >> > + void mapSourceCodeRange(SourceLocation LocStart, SourceLocation
>> >> > LocEnd,
>> >> > + Counter Count, unsigned Flags = 0) {
>> >> > + mapSourceCodeRange(LocStart, LocEnd, Count,
>> >> > + CurrentUnreachableRegionInitiator,
>> >> > CurrentSourceGroup,
>> >> > + Flags);
>> >> > + }
>> >> > +
>> >> > + void mapSourceCodeRange(const SourceMappingState &State,
>> >> > + SourceLocation LocStart, SourceLocation
>> >> > LocEnd,
>> >> > + unsigned Flags = 0) {
>> >> > + mapSourceCodeRange(LocStart, LocEnd, State.CurrentRegionCount,
>> >> > + State.CurrentUnreachableRegionInitiator,
>> >> > + State.CurrentSourceGroup, Flags);
>> >> > + }
>> >> > +
>> >> > + /// \brief Generate the coverage counter mapping regions from
>> >> > collected
>> >> > + /// source regions.
>> >> > + void emitSourceRegions() {
>> >> > + for (const auto &R : SourceRegions) {
>> >> > + SourceLocation LocStart = R.LocStart;
>> >> > + SourceLocation LocEnd = R.LocEnd;
>> >> > + if (SM.getFileID(LocEnd) != R.File)
>> >> > + LocEnd = R.AlternativeLocEnd;
>> >> > +
>> >> > + if (R.hasFlag(SourceMappingRegion::IgnoreIfNotExtended) &&
>> >> > + LocStart == LocEnd)
>> >> > + continue;
>> >> > +
>> >> > + LocEnd = getPreciseTokenLocEnd(LocEnd);
>> >> > + unsigned LineStart = SM.getSpellingLineNumber(LocStart);
>> >> > + unsigned ColumnStart = SM.getSpellingColumnNumber(LocStart);
>> >> > + unsigned LineEnd = SM.getSpellingLineNumber(LocEnd);
>> >> > + unsigned ColumnEnd = SM.getSpellingColumnNumber(LocEnd);
>> >> > +
>> >> > + auto SpellingFile =
>> >> > SM.getDecomposedSpellingLoc(R.LocStart).first;
>> >> > + unsigned CovFileID;
>> >> > + if (getCoverageFileID(R.LocStart, R.File, SpellingFile,
>> >> > CovFileID))
>> >> > + continue;
>> >> > +
>> >> > + assert(LineStart <= LineEnd);
>> >> > + MappingRegions.push_back(CounterMappingRegion(
>> >> > + R.Count, CovFileID, LineStart, ColumnStart, LineEnd,
>> >> > ColumnEnd,
>> >> > + false, CounterMappingRegion::CodeRegion));
>> >> > + }
>> >> > + }
>> >> > +};
>> >> > +
>> >> > +/// \brief Creates unreachable coverage regions for the functions
>> that
>> >> > +/// are not emitted.
>> >> > +struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder {
>> >> > + EmptyCoverageMappingBuilder(CoverageMappingModuleGen &CVM,
>> >> > SourceManager &SM,
>> >> > + const LangOptions &LangOpts)
>> >> > + : CoverageMappingBuilder(CVM, SM, LangOpts) {}
>> >> > +
>> >> > + void VisitDecl(const Decl *D) {
>> >> > + if (!D->hasBody())
>> >> > + return;
>> >> > + auto Body = D->getBody();
>> >> > + mapSourceCodeRange(Body->getLocStart(), Body->getLocEnd(),
>> >> > Counter());
>> >> > + }
>> >> > +
>> >> > + /// \brief Write the mapping data to the output stream
>> >> > + void write(llvm::raw_ostream &OS) {
>> >> > + emitSourceRegions();
>> >> > + SmallVector<unsigned, 16> FileIDMapping;
>> >> > + createFileIDMapping(FileIDMapping);
>> >> > +
>> >> > + CoverageMappingWriter Writer(
>> >> > + FileIDMapping, ArrayRef<CounterExpression>(),
>> MappingRegions);
>> >> > + Writer.write(OS);
>> >> > + }
>> >> > +};
>> >> > +
>> >> > +/// \brief A StmtVisitor that creates coverage mapping regions which
>> >> > map
>> >> > +/// from the source code locations to the PGO counters.
>> >> > +struct CounterCoverageMappingBuilder
>> >> > + : public CoverageMappingBuilder,
>> >> > + public ConstStmtVisitor<CounterCoverageMappingBuilder> {
>> >> > + /// \brief The map of statements to count values.
>> >> > + llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
>> >> > +
>> >> > + Counter CurrentRegionCount;
>> >> > +
>> >> > + CounterExpressionBuilder Builder;
>> >> > +
>> >> > + /// \brief Return a counter that represents the
>> >> > + /// expression that subracts rhs from lhs.
>> >> > + Counter subtractCounters(Counter LHS, Counter RHS) {
>> >> > + return Builder.subtract(LHS, RHS);
>> >> > + }
>> >> > +
>> >> > + /// \brief Return a counter that represents the
>> >> > + /// the exression that adds lhs and rhs.
>> >> > + Counter addCounters(Counter LHS, Counter RHS) {
>> >> > + return Builder.add(LHS, RHS);
>> >> > + }
>> >> > +
>> >> > + /// \brief Return the region counter for the given statement.
>> >> > + /// This should only be called on statements that have a dedicated
>> >> > counter.
>> >> > + unsigned getRegionCounter(const Stmt *S) { return CounterMap[S]; }
>> >> > +
>> >> > + /// \brief Return the region count for the counter at the given
>> >> > index.
>> >> > + Counter getRegionCount(unsigned CounterId) {
>> >> > + return Counter::getCounter(CounterId);
>> >> > + }
>> >> > +
>> >> > + /// \brief Return the counter value of the current region.
>> >> > + Counter getCurrentRegionCount() { return CurrentRegionCount; }
>> >> > +
>> >> > + /// \brief Set the counter value for the current region.
>> >> > + /// This is used to keep track of changes to the most recent
>> counter
>> >> > + /// from control flow and non-local exits.
>> >> > + void setCurrentRegionCount(Counter Count) {
>> >> > + CurrentRegionCount = Count;
>> >> > + CurrentUnreachableRegionInitiator = nullptr;
>> >> > + }
>> >> > +
>> >> > + /// \brief Indicate that the current region is never reached,
>> >> > + /// and thus should have a counter value of zero.
>> >> > + /// This is important so that subsequent regions can correctly
>> track
>> >> > + /// their parent counts.
>> >> > + void setCurrentRegionUnreachable(const Stmt *Initiator) {
>> >> > + CurrentRegionCount = Counter::getZero();
>> >> > + CurrentUnreachableRegionInitiator = Initiator;
>> >> > + }
>> >> > +
>> >> > + /// \brief A counter for a particular region.
>> >> > + /// This is the primary interface through
>> >> > + /// which the coverage mapping builder manages counters and their
>> >> > values.
>> >> > + class RegionMapper {
>> >> > + CounterCoverageMappingBuilder &Mapping;
>> >> > + Counter Count;
>> >> > + Counter ParentCount;
>> >> > + Counter RegionCount;
>> >> > + Counter Adjust;
>> >> > +
>> >> > + public:
>> >> > + RegionMapper(CounterCoverageMappingBuilder *Mapper, const Stmt
>> *S)
>> >> > + : Mapping(*Mapper),
>> >> > +
>> Count(Mapper->getRegionCount(Mapper->getRegionCounter(S))),
>> >> > + ParentCount(Mapper->getCurrentRegionCount()) {}
>> >> > +
>> >> > + /// Get the value of the counter. In most cases this is the
>> number
>> >> > of times
>> >> > + /// the region of the counter was entered, but for switch labels
>> >> > it's the
>> >> > + /// number of direct jumps to that label.
>> >> > + Counter getCount() const { return Count; }
>> >> > +
>> >> > + /// Get the value of the counter with adjustments applied.
>> >> > Adjustments occur
>> >> > + /// when control enters or leaves the region abnormally; i.e.,
>> if
>> >> > there is a
>> >> > + /// jump to a label within the region, or if the function can
>> >> > return from
>> >> > + /// within the region. The adjusted count, then, is the value of
>> >> > the counter
>> >> > + /// at the end of the region.
>> >> > + Counter getAdjustedCount() const {
>> >> > + return Mapping.addCounters(Count, Adjust);
>> >> > + }
>> >> > +
>> >> > + /// Get the value of the counter in this region's parent, i.e.,
>> the
>> >> > region
>> >> > + /// that was active when this region began. This is useful for
>> >> > deriving
>> >> > + /// counts in implicitly counted regions, like the false case
>> of a
>> >> > condition
>> >> > + /// or the normal exits of a loop.
>> >> > + Counter getParentCount() const { return ParentCount; }
>> >> > +
>> >> > + /// Activate the counter by emitting an increment and starting
>> to
>> >> > track
>> >> > + /// adjustments. If AddIncomingFallThrough is true, the current
>> >> > region count
>> >> > + /// will be added to the counter for the purposes of tracking
>> the
>> >> > region.
>> >> > + void beginRegion(bool AddIncomingFallThrough = false) {
>> >> > + RegionCount = Count;
>> >> > + if (AddIncomingFallThrough)
>> >> > + RegionCount =
>> >> > + Mapping.addCounters(RegionCount,
>> >> > Mapping.getCurrentRegionCount());
>> >> > + Mapping.setCurrentRegionCount(RegionCount);
>> >> > + }
>> >> > +
>> >> > + /// For counters on boolean branches, begins tracking
>> adjustments
>> >> > for the
>> >> > + /// uncounted path.
>> >> > + void beginElseRegion() {
>> >> > + RegionCount = Mapping.subtractCounters(ParentCount, Count);
>> >> > + Mapping.setCurrentRegionCount(RegionCount);
>> >> > + }
>> >> > +
>> >> > + /// Reset the current region count.
>> >> > + void setCurrentRegionCount(Counter CurrentCount) {
>> >> > + RegionCount = CurrentCount;
>> >> > + Mapping.setCurrentRegionCount(RegionCount);
>> >> > + }
>> >> > +
>> >> > + /// Adjust for non-local control flow after emitting a
>> >> > subexpression or
>> >> > + /// substatement. This must be called to account for constructs
>> >> > such as
>> >> > + /// gotos,
>> >> > + /// labels, and returns, so that we can ensure that our region's
>> >> > count is
>> >> > + /// correct in the code that follows.
>> >> > + void adjustForControlFlow() {
>> >> > + Adjust = Mapping.addCounters(
>> >> > + Adjust,
>> >> > Mapping.subtractCounters(Mapping.getCurrentRegionCount(),
>> >> > + RegionCount));
>> >> > + // Reset the region count in case this is called again later.
>> >> > + RegionCount = Mapping.getCurrentRegionCount();
>> >> > + }
>> >> > +
>> >> > + /// Commit all adjustments to the current region. If the region
>> is
>> >> > a loop,
>> >> > + /// the LoopAdjust value should be the count of all the breaks
>> and
>> >> > continues
>> >> > + /// from the loop, to compensate for those counts being deducted
>> >> > from the
>> >> > + /// adjustments for the body of the loop.
>> >> > + void applyAdjustmentsToRegion() {
>> >> > + Mapping.setCurrentRegionCount(Mapping.addCounters(ParentCount,
>> >> > Adjust));
>> >> > + }
>> >> > + void applyAdjustmentsToRegion(Counter LoopAdjust) {
>> >> > + Mapping.setCurrentRegionCount(Mapping.addCounters(
>> >> > + Mapping.addCounters(ParentCount, Adjust), LoopAdjust));
>> >> > + }
>> >> > + };
>> >> > +
>> >> > + /// \brief Keep counts of breaks and continues inside loops.
>> >> > + struct BreakContinue {
>> >> > + Counter BreakCount;
>> >> > + Counter ContinueCount;
>> >> > + };
>> >> > + SmallVector<BreakContinue, 8> BreakContinueStack;
>> >> > +
>> >> > + CounterCoverageMappingBuilder(
>> >> > + CoverageMappingModuleGen &CVM,
>> >> > + llvm::DenseMap<const Stmt *, unsigned> &CounterMap,
>> >> > + unsigned NumRegionCounters, SourceManager &SM,
>> >> > + const LangOptions &LangOpts)
>> >> > + : CoverageMappingBuilder(CVM, SM, LangOpts),
>> >> > CounterMap(CounterMap),
>> >> > + Builder(NumRegionCounters) {}
>> >> > +
>> >> > + /// \brief Write the mapping data to the output stream
>> >> > + void write(llvm::raw_ostream &OS) {
>> >> > + emitSourceRegions();
>> >> > + llvm::SmallVector<unsigned, 8> VirtualFileMapping;
>> >> > + createFileIDMapping(VirtualFileMapping);
>> >> > + gatherSkippedRegions();
>> >> > +
>> >> > + CoverageMappingWriter Writer(
>> >> > + VirtualFileMapping, Builder.getExpressions(),
>> MappingRegions);
>> >> > + Writer.write(OS);
>> >> > + }
>> >> > +
>> >> > + /// \brief Return the current source mapping state.
>> >> > + SourceMappingState getCurrentState() const {
>> >> > + return SourceMappingState(CurrentRegionCount,
>> CurrentSourceGroup,
>> >> > + CurrentUnreachableRegionInitiator);
>> >> > + }
>> >> > +
>> >> > + /// \brief Associate the source code range with the current region
>> >> > count.
>> >> > + void mapSourceCodeRange(SourceLocation LocStart, SourceLocation
>> >> > LocEnd,
>> >> > + unsigned Flags = 0) {
>> >> > + CoverageMappingBuilder::mapSourceCodeRange(LocStart, LocEnd,
>> >> > + CurrentRegionCount,
>> >> > Flags);
>> >> > + }
>> >> > +
>> >> > + void mapSourceCodeRange(SourceLocation LocStart) {
>> >> > + CoverageMappingBuilder::mapSourceCodeRange(LocStart, LocStart,
>> >> > + CurrentRegionCount);
>> >> > + }
>> >> > +
>> >> > + /// \brief Associate the source range of a token with the current
>> >> > region
>> >> > + /// count.
>> >> > + /// Ignore the source range for this token if it produces a
>> distinct
>> >> > + /// mapping region with no other source ranges.
>> >> > + void mapToken(SourceLocation LocStart) {
>> >> > + CoverageMappingBuilder::mapSourceCodeRange(
>> >> > + LocStart, LocStart, CurrentRegionCount,
>> >> > + SourceMappingRegion::IgnoreIfNotExtended);
>> >> > + }
>> >> > +
>> >> > + void mapToken(const SourceMappingState &State, SourceLocation
>> >> > LocStart) {
>> >> > + CoverageMappingBuilder::mapSourceCodeRange(
>> >> > + State, LocStart, LocStart,
>> >> > SourceMappingRegion::IgnoreIfNotExtended);
>> >> > + }
>> >> > +
>> >> > + void VisitStmt(const Stmt *S) {
>> >> > + mapSourceCodeRange(S->getLocStart());
>> >> > + for (Stmt::const_child_range I = S->children(); I; ++I) {
>> >> > + if (*I)
>> >> > + this->Visit(*I);
>> >> > + }
>> >> > + }
>> >> > +
>> >> > + /// \brief If the given statement is a compound statement,
>> >> > + /// map '}' with the same count as '{'.
>> >> > + void VisitSubStmtRBraceState(const Stmt *S) {
>> >> > + if (!isa<CompoundStmt>(S))
>> >> > + return Visit(S);
>> >> > + const auto *CS = cast<CompoundStmt>(S);
>> >> > + auto State = getCurrentState();
>> >> > + mapSourceCodeRange(CS->getLBracLoc());
>> >> > + for (Stmt::const_child_range I = S->children(); I; ++I) {
>> >> > + if (*I)
>> >> > + this->Visit(*I);
>> >> > + }
>> >> > + CoverageMappingBuilder::mapSourceCodeRange(State,
>> >> > CS->getRBracLoc(),
>> >> > + CS->getRBracLoc());
>> >> > + }
>> >> > +
>> >> > + void VisitDecl(const Decl *D) {
>> >> > + if (!D->hasBody())
>> >> > + return;
>> >> > + // Counter tracks entry to the function body.
>> >> > + auto Body = D->getBody();
>> >> > + RegionMapper Cnt(this, Body);
>> >> > + Cnt.beginRegion();
>> >> > + VisitSubStmtRBraceState(Body);
>> >> > + }
>> >> > +
>> >> > + void VisitDeclStmt(const DeclStmt *S) {
>> >> > + mapSourceCodeRange(S->getLocStart());
>> >> > + for (Stmt::const_child_range I = static_cast<const Stmt
>> >> > *>(S)->children();
>> >> > + I; ++I) {
>> >> > + if (*I)
>> >> > + this->Visit(*I);
>> >> > + }
>> >> > + }
>> >> > +
>> >> > + void VisitCompoundStmt(const CompoundStmt *S) {
>> >> > + mapSourceCodeRange(S->getLBracLoc());
>> >> > + for (Stmt::const_child_range I = S->children(); I; ++I) {
>> >> > + if (*I)
>> >> > + this->Visit(*I);
>> >> > + }
>> >> > + mapSourceCodeRange(S->getRBracLoc(), S->getRBracLoc());
>> >> > + }
>> >> > +
>> >> > + void VisitReturnStmt(const ReturnStmt *S) {
>> >> > + mapSourceCodeRange(S->getLocStart());
>> >> > + if (S->getRetValue())
>> >> > + Visit(S->getRetValue());
>> >> > + setCurrentRegionUnreachable(S);
>> >> > + }
>> >> > +
>> >> > + void VisitGotoStmt(const GotoStmt *S) {
>> >> > + mapSourceCodeRange(S->getLocStart());
>> >> > + mapToken(S->getLabelLoc());
>> >> > + setCurrentRegionUnreachable(S);
>> >> > + }
>> >> > +
>> >> > + void VisitLabelStmt(const LabelStmt *S) {
>> >> > + // Counter tracks the block following the label.
>> >> > + RegionMapper Cnt(this, S);
>> >> > + Cnt.beginRegion();
>> >> > + mapSourceCodeRange(S->getLocStart());
>> >> > + // Can't map the ':' token as its location isn't known.
>> >> > + Visit(S->getSubStmt());
>> >> > + }
>> >> > +
>> >> > + void VisitBreakStmt(const BreakStmt *S) {
>> >> > + mapSourceCodeRange(S->getLocStart());
>> >> > + assert(!BreakContinueStack.empty() && "break not in a loop or
>> >> > switch!");
>> >> > + BreakContinueStack.back().BreakCount = addCounters(
>> >> > + BreakContinueStack.back().BreakCount,
>> getCurrentRegionCount());
>> >> > + setCurrentRegionUnreachable(S);
>> >> > + }
>> >> > +
>> >> > + void VisitContinueStmt(const ContinueStmt *S) {
>> >> > + mapSourceCodeRange(S->getLocStart());
>> >> > + assert(!BreakContinueStack.empty() && "continue stmt not in a
>> >> > loop!");
>> >> > + BreakContinueStack.back().ContinueCount = addCounters(
>> >> > + BreakContinueStack.back().ContinueCount,
>> >> > getCurrentRegionCount());
>> >> > + setCurrentRegionUnreachable(S);
>> >> > + }
>> >> > +
>> >> > + void VisitWhileStmt(const WhileStmt *S) {
>> >> > + mapSourceCodeRange(S->getLocStart());
>> >> > + // Counter tracks the body of the loop.
>> >> > + RegionMapper Cnt(this, S);
>> >> > + BreakContinueStack.push_back(BreakContinue());
>> >> > + // Visit the body region first so the break/continue adjustments
>> >> > can be
>> >> > + // included when visiting the condition.
>> >> > + Cnt.beginRegion();
>> >> > + VisitSubStmtRBraceState(S->getBody());
>> >> > + Cnt.adjustForControlFlow();
>> >> > +
>> >> > + // ...then go back and propagate counts through the condition.
>> The
>> >> > count
>> >> > + // at the start of the condition is the sum of the incoming
>> edges,
>> >> > + // the backedge from the end of the loop body, and the edges
>> from
>> >> > + // continue statements.
>> >> > + BreakContinue BC = BreakContinueStack.pop_back_val();
>> >> > + Cnt.setCurrentRegionCount(
>> >> > + addCounters(Cnt.getParentCount(),
>> >> > + addCounters(Cnt.getAdjustedCount(),
>> >> > BC.ContinueCount)));
>> >> > + beginSourceRegionGroup(S->getCond());
>> >> > + Visit(S->getCond());
>> >> > + endSourceRegionGroup();
>> >> > + Cnt.adjustForControlFlow();
>> >> > + Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount,
>> >> > BC.ContinueCount));
>> >> > + }
>> >> > +
>> >> > + void VisitDoStmt(const DoStmt *S) {
>> >> > + mapSourceCodeRange(S->getLocStart());
>> >> > + // Counter tracks the body of the loop.
>> >> > + RegionMapper Cnt(this, S);
>> >> > + BreakContinueStack.push_back(BreakContinue());
>> >> > + Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
>> >> > + VisitSubStmtRBraceState(S->getBody());
>> >> > + Cnt.adjustForControlFlow();
>> >> > +
>> >> > + BreakContinue BC = BreakContinueStack.pop_back_val();
>> >> > + // The count at the start of the condition is equal to the
>> count at
>> >> > the
>> >> > + // end of the body. The adjusted count does not include either
>> the
>> >> > + // fall-through count coming into the loop or the continue
>> count,
>> >> > so add
>> >> > + // both of those separately. This is coincidentally the same
>> >> > equation as
>> >> > + // with while loops but for different reasons.
>> >> > + Cnt.setCurrentRegionCount(
>> >> > + addCounters(Cnt.getParentCount(),
>> >> > + addCounters(Cnt.getAdjustedCount(),
>> >> > BC.ContinueCount)));
>> >> > + Visit(S->getCond());
>> >> > + Cnt.adjustForControlFlow();
>> >> > + Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount,
>> >> > BC.ContinueCount));
>> >> > + }
>> >> > +
>> >> > + void VisitForStmt(const ForStmt *S) {
>> >> > + mapSourceCodeRange(S->getLocStart());
>> >> > + if (S->getInit())
>> >> > + Visit(S->getInit());
>> >> > +
>> >> > + // Counter tracks the body of the loop.
>> >> > + RegionMapper Cnt(this, S);
>> >> > + BreakContinueStack.push_back(BreakContinue());
>> >> > + // Visit the body region first. (This is basically the same as a
>> >> > while
>> >> > + // loop; see further comments in VisitWhileStmt.)
>> >> > + Cnt.beginRegion();
>> >> > + VisitSubStmtRBraceState(S->getBody());
>> >> > + Cnt.adjustForControlFlow();
>> >> > +
>> >> > + // The increment is essentially part of the body but it needs to
>> >> > include
>> >> > + // the count for all the continue statements.
>> >> > + if (S->getInc()) {
>> >> > + Cnt.setCurrentRegionCount(addCounters(
>> >> > + getCurrentRegionCount(),
>> >> > BreakContinueStack.back().ContinueCount));
>> >> > + beginSourceRegionGroup(S->getInc());
>> >> > + Visit(S->getInc());
>> >> > + endSourceRegionGroup();
>> >> > + Cnt.adjustForControlFlow();
>> >> > + }
>> >> > +
>> >> > + BreakContinue BC = BreakContinueStack.pop_back_val();
>> >> > +
>> >> > + // ...then go back and propagate counts through the condition.
>> >> > + if (S->getCond()) {
>> >> > + Cnt.setCurrentRegionCount(
>> >> > + addCounters(addCounters(Cnt.getParentCount(),
>> >> > Cnt.getAdjustedCount()),
>> >> > + BC.ContinueCount));
>> >> > + beginSourceRegionGroup(S->getCond());
>> >> > + Visit(S->getCond());
>> >> > + endSourceRegionGroup();
>> >> > + Cnt.adjustForControlFlow();
>> >> > + }
>> >> > + Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount,
>> >> > BC.ContinueCount));
>> >> > + }
>> >> > +
>> >> > + void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
>> >> > + mapSourceCodeRange(S->getLocStart());
>> >> > + Visit(S->getRangeStmt());
>> >> > + Visit(S->getBeginEndStmt());
>> >> > + // Counter tracks the body of the loop.
>> >> > + RegionMapper Cnt(this, S);
>> >> > + BreakContinueStack.push_back(BreakContinue());
>> >> > + // Visit the body region first. (This is basically the same as a
>> >> > while
>> >> > + // loop; see further comments in VisitWhileStmt.)
>> >> > + Cnt.beginRegion();
>> >> > + VisitSubStmtRBraceState(S->getBody());
>> >> > + Cnt.adjustForControlFlow();
>> >> > + BreakContinue BC = BreakContinueStack.pop_back_val();
>> >> > + Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount,
>> >> > BC.ContinueCount));
>> >> > + }
>> >> > +
>> >> > + void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
>> >> > + mapSourceCodeRange(S->getLocStart());
>> >> > + Visit(S->getElement());
>> >> > + // Counter tracks the body of the loop.
>> >> > + RegionMapper Cnt(this, S);
>> >> > + BreakContinueStack.push_back(BreakContinue());
>> >> > + VisitSubStmtRBraceState(S->getBody());
>> >> > + BreakContinue BC = BreakContinueStack.pop_back_val();
>> >> > + Cnt.adjustForControlFlow();
>> >> > + Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount,
>> >> > BC.ContinueCount));
>> >> > + }
>> >> > +
>> >> > + void VisitSwitchStmt(const SwitchStmt *S) {
>> >> > + mapSourceCodeRange(S->getLocStart());
>> >> > + Visit(S->getCond());
>> >> > + BreakContinueStack.push_back(BreakContinue());
>> >> > + // Map the '}' for the body to have the same count as the
>> regions
>> >> > after
>> >> > + // the switch.
>> >> > + SourceLocation RBracLoc;
>> >> > + if (const auto *CS = dyn_cast<CompoundStmt>(S->getBody())) {
>> >> > + mapSourceCodeRange(CS->getLBracLoc());
>> >> > + setCurrentRegionUnreachable(S);
>> >> > + for (Stmt::const_child_range I = CS->children(); I; ++I) {
>> >> > + if (*I)
>> >> > + this->Visit(*I);
>> >> > + }
>> >> > + RBracLoc = CS->getRBracLoc();
>> >> > + } else {
>> >> > + setCurrentRegionUnreachable(S);
>> >> > + Visit(S->getBody());
>> >> > + }
>> >> > + // If the switch is inside a loop, add the continue counts.
>> >> > + BreakContinue BC = BreakContinueStack.pop_back_val();
>> >> > + if (!BreakContinueStack.empty())
>> >> > + BreakContinueStack.back().ContinueCount = addCounters(
>> >> > + BreakContinueStack.back().ContinueCount,
>> BC.ContinueCount);
>> >> > + // Counter tracks the exit block of the switch.
>> >> > + RegionMapper ExitCnt(this, S);
>> >> > + ExitCnt.beginRegion();
>> >> > + if (RBracLoc.isValid())
>> >> > + mapSourceCodeRange(RBracLoc);
>> >> > + }
>> >> > +
>> >> > + void VisitCaseStmt(const CaseStmt *S) {
>> >> > + // Counter for this particular case. This counts only jumps from
>> >> > the
>> >> > + // switch header and does not include fallthrough from the case
>> >> > before
>> >> > + // this one.
>> >> > + RegionMapper Cnt(this, S);
>> >> > + Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
>> >> > + mapSourceCodeRange(S->getLocStart());
>> >> > + mapToken(S->getColonLoc());
>> >> > + Visit(S->getSubStmt());
>> >> > + }
>> >> > +
>> >> > + void VisitDefaultStmt(const DefaultStmt *S) {
>> >> > + // Counter for this default case. This does not include
>> fallthrough
>> >> > from
>> >> > + // the previous case.
>> >> > + RegionMapper Cnt(this, S);
>> >> > + Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
>> >> > + mapSourceCodeRange(S->getLocStart());
>> >> > + mapToken(S->getColonLoc());
>> >> > + Visit(S->getSubStmt());
>> >> > + }
>> >> > +
>> >> > + void VisitIfStmt(const IfStmt *S) {
>> >> > + mapSourceCodeRange(S->getLocStart());
>> >> > + Visit(S->getCond());
>> >> > + mapToken(S->getElseLoc());
>> >> > +
>> >> > + // Counter tracks the "then" part of an if statement. The count
>> for
>> >> > + // the "else" part, if it exists, will be calculated from this
>> >> > counter.
>> >> > + RegionMapper Cnt(this, S);
>> >> > + Cnt.beginRegion();
>> >> > + VisitSubStmtRBraceState(S->getThen());
>> >> > + Cnt.adjustForControlFlow();
>> >> > +
>> >> > + if (S->getElse()) {
>> >> > + Cnt.beginElseRegion();
>> >> > + VisitSubStmtRBraceState(S->getElse());
>> >> > + Cnt.adjustForControlFlow();
>> >> > + }
>> >> > + Cnt.applyAdjustmentsToRegion();
>> >> > + }
>> >> > +
>> >> > + void VisitCXXTryStmt(const CXXTryStmt *S) {
>> >> > + mapSourceCodeRange(S->getLocStart());
>> >> > + Visit(S->getTryBlock());
>> >> > + for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
>> >> > + Visit(S->getHandler(I));
>> >> > + // Counter tracks the continuation block of the try statement.
>> >> > + RegionMapper Cnt(this, S);
>> >> > + Cnt.beginRegion();
>> >> > + }
>> >> > +
>> >> > + void VisitCXXCatchStmt(const CXXCatchStmt *S) {
>> >> > + mapSourceCodeRange(S->getLocStart());
>> >> > + // Counter tracks the catch statement's handler block.
>> >> > + RegionMapper Cnt(this, S);
>> >> > + Cnt.beginRegion();
>> >> > + VisitSubStmtRBraceState(S->getHandlerBlock());
>> >> > + }
>> >> > +
>> >> > + void VisitAbstractConditionalOperator(const
>> >> > AbstractConditionalOperator *E) {
>> >> > + Visit(E->getCond());
>> >> > + mapToken(E->getQuestionLoc());
>> >> > + auto State = getCurrentState();
>> >> > +
>> >> > + // Counter tracks the "true" part of a conditional operator. The
>> >> > + // count in the "false" part will be calculated from this
>> counter.
>> >> > + RegionMapper Cnt(this, E);
>> >> > + Cnt.beginRegion();
>> >> > + Visit(E->getTrueExpr());
>> >> > + Cnt.adjustForControlFlow();
>> >> > +
>> >> > + mapToken(State, E->getColonLoc());
>> >> > +
>> >> > + Cnt.beginElseRegion();
>> >> > + Visit(E->getFalseExpr());
>> >> > + Cnt.adjustForControlFlow();
>> >> > +
>> >> > + Cnt.applyAdjustmentsToRegion();
>> >> > + }
>> >> > +
>> >> > + void VisitBinLAnd(const BinaryOperator *E) {
>> >> > + Visit(E->getLHS());
>> >> > + mapToken(E->getOperatorLoc());
>> >> > + // Counter tracks the right hand side of a logical and operator.
>> >> > + RegionMapper Cnt(this, E);
>> >> > + Cnt.beginRegion();
>> >> > + Visit(E->getRHS());
>> >> > + Cnt.adjustForControlFlow();
>> >> > + Cnt.applyAdjustmentsToRegion();
>> >> > + }
>> >> > +
>> >> > + void VisitBinLOr(const BinaryOperator *E) {
>> >> > + Visit(E->getLHS());
>> >> > + mapToken(E->getOperatorLoc());
>> >> > + // Counter tracks the right hand side of a logical or operator.
>> >> > + RegionMapper Cnt(this, E);
>> >> > + Cnt.beginRegion();
>> >> > + Visit(E->getRHS());
>> >> > + Cnt.adjustForControlFlow();
>> >> > + Cnt.applyAdjustmentsToRegion();
>> >> > + }
>> >> > +
>> >> > + void VisitParenExpr(const ParenExpr *E) {
>> >> > + mapToken(E->getLParen());
>> >> > + Visit(E->getSubExpr());
>> >> > + mapToken(E->getRParen());
>> >> > + }
>> >> > +
>> >> > + void VisitBinaryOperator(const BinaryOperator *E) {
>> >> > + Visit(E->getLHS());
>> >> > + mapToken(E->getOperatorLoc());
>> >> > + Visit(E->getRHS());
>> >> > + }
>> >> > +
>> >> > + void VisitUnaryOperator(const UnaryOperator *E) {
>> >> > + bool Postfix = E->isPostfix();
>> >> > + if (!Postfix)
>> >> > + mapToken(E->getOperatorLoc());
>> >> > + Visit(E->getSubExpr());
>> >> > + if (Postfix)
>> >> > + mapToken(E->getOperatorLoc());
>> >> > + }
>> >> > +
>> >> > + void VisitMemberExpr(const MemberExpr *E) {
>> >> > + Visit(E->getBase());
>> >> > + mapToken(E->getMemberLoc());
>> >> > + }
>> >> > +
>> >> > + void VisitCallExpr(const CallExpr *E) {
>> >> > + Visit(E->getCallee());
>> >> > + for (const auto &Arg : E->arguments())
>> >> > + Visit(Arg);
>> >> > + mapToken(E->getRParenLoc());
>> >> > + }
>> >> > +
>> >> > + void VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
>> >> > + Visit(E->getLHS());
>> >> > + Visit(E->getRHS());
>> >> > + mapToken(E->getRBracketLoc());
>> >> > + }
>> >> > +
>> >> > + void VisitCStyleCastExpr(const CStyleCastExpr *E) {
>> >> > + mapToken(E->getLParenLoc());
>> >> > + mapToken(E->getRParenLoc());
>> >> > + Visit(E->getSubExpr());
>> >> > + }
>> >> > +
>> >> > + // Map literals as tokens so that the macros like #define PI 3.14
>> >> > + // won't generate coverage mapping regions.
>> >> > +
>> >> > + void VisitIntegerLiteral(const IntegerLiteral *E) {
>> >> > + mapToken(E->getLocStart());
>> >> > + }
>> >> > +
>> >> > + void VisitFloatingLiteral(const FloatingLiteral *E) {
>> >> > + mapToken(E->getLocStart());
>> >> > + }
>> >> > +
>> >> > + void VisitCharacterLiteral(const CharacterLiteral *E) {
>> >> > + mapToken(E->getLocStart());
>> >> > + }
>> >> > +
>> >> > + void VisitStringLiteral(const StringLiteral *E) {
>> >> > + mapToken(E->getLocStart());
>> >> > + }
>> >> > +
>> >> > + void VisitImaginaryLiteral(const ImaginaryLiteral *E) {
>> >> > + mapToken(E->getLocStart());
>> >> > + }
>> >> > +};
>> >> > +}
>> >> > +
>> >> > +static bool isMachO(const CodeGenModule &CGM) {
>> >> > + return CGM.getTarget().getTriple().isOSBinFormatMachO();
>> >> > +}
>> >> > +
>> >> > +static StringRef getCoverageSection(const CodeGenModule &CGM) {
>> >> > + return isMachO(CGM) ? "__DATA,__llvm_covmap" : "__llvm_covmap";
>> >> > +}
>> >> > +
>> >> > +void CoverageMappingModuleGen::addFunctionMappingRecord(
>> >> > + llvm::GlobalVariable *FunctionName, unsigned FunctionNameSize,
>> >> > + const std::string &CoverageMapping) {
>> >> > + llvm::LLVMContext &Ctx = CGM.getLLVMContext();
>> >> > + auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
>> >> > + auto *Int8PtrTy = llvm::Type::getInt8PtrTy(Ctx);
>> >> > + if (!FunctionRecordTy) {
>> >> > + llvm::Type *FunctionRecordTypes[] = {Int8PtrTy, Int32Ty,
>> Int32Ty};
>> >> > + FunctionRecordTy =
>> >> > + llvm::StructType::get(Ctx,
>> makeArrayRef(FunctionRecordTypes));
>> >> > + }
>> >> > +
>> >> > + llvm::Constant *FunctionRecordVals[] = {
>> >> > + llvm::ConstantExpr::getBitCast(FunctionName, Int8PtrTy),
>> >> > + llvm::ConstantInt::get(Int32Ty, FunctionNameSize),
>> >> > + llvm::ConstantInt::get(Int32Ty, CoverageMapping.size())};
>> >> > + FunctionRecords.push_back(llvm::ConstantStruct::get(
>> >> > + FunctionRecordTy, makeArrayRef(FunctionRecordVals)));
>> >> > + CoverageMappings += CoverageMapping;
>> >> > +}
>> >> > +
>> >> > +void CoverageMappingModuleGen::emit() {
>> >> > + if (FunctionRecords.empty())
>> >> > + return;
>> >> > + llvm::LLVMContext &Ctx = CGM.getLLVMContext();
>> >> > + auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
>> >> > +
>> >> > + // Create the filenames and merge them with coverage mappings
>> >> > + llvm::SmallVector<std::string, 16> FilenameStrs;
>> >> > + llvm::SmallVector<StringRef, 16> FilenameRefs;
>> >> > + FilenameStrs.resize(FileEntries.size());
>> >> > + FilenameRefs.resize(FileEntries.size());
>> >> > + for (const auto &Entry : FileEntries) {
>> >> > + llvm::SmallString<256> Path(Entry.first->getName());
>> >> > + llvm::sys::fs::make_absolute(Path);
>> >> > +
>> >> > + auto I = Entry.second;
>> >> > + FilenameStrs[I] = std::move(std::string(Path.begin(),
>> Path.end()));
>> >> > + FilenameRefs[I] = FilenameStrs[I];
>> >> > + }
>> >> > +
>> >> > + std::string FilenamesAndCoverageMappings;
>> >> > + llvm::raw_string_ostream OS(FilenamesAndCoverageMappings);
>> >> > + CoverageFilenamesSectionWriter(FilenameRefs).write(OS);
>> >> > + OS << CoverageMappings;
>> >> > + size_t CoverageMappingSize = CoverageMappings.size();
>> >> > + size_t FilenamesSize = OS.str().size() - CoverageMappingSize;
>> >> > + // Append extra zeroes if necessary to ensure that the size of the
>> >> > filenames
>> >> > + // and coverage mappings is a multiple of 8.
>> >> > + if (size_t Rem = OS.str().size() % 8) {
>> >> > + CoverageMappingSize += 8 - Rem;
>> >> > + for (size_t I = 0, S = 8 - Rem; I < S; ++I)
>> >> > + OS << '\0';
>> >> > + }
>> >> > + auto *FilenamesAndMappingsVal =
>> >> > + llvm::ConstantDataArray::getString(Ctx, OS.str(), false);
>> >> > +
>> >> > + // Create the deferred function records array
>> >> > + auto RecordsTy =
>> >> > + llvm::ArrayType::get(FunctionRecordTy,
>> FunctionRecords.size());
>> >> > + auto RecordsVal = llvm::ConstantArray::get(RecordsTy,
>> >> > FunctionRecords);
>> >> > +
>> >> > + // Create the coverage data record
>> >> > + llvm::Type *CovDataTypes[] = {Int32Ty, Int32Ty,
>> >> > + Int32Ty, Int32Ty,
>> >> > + RecordsTy,
>> >> > FilenamesAndMappingsVal->getType()};
>> >> > + auto CovDataTy = llvm::StructType::get(Ctx,
>> >> > makeArrayRef(CovDataTypes));
>> >> > + llvm::Constant *TUDataVals[] = {
>> >> > + llvm::ConstantInt::get(Int32Ty, FunctionRecords.size()),
>> >> > + llvm::ConstantInt::get(Int32Ty, FilenamesSize),
>> >> > + llvm::ConstantInt::get(Int32Ty, CoverageMappingSize),
>> >> > + llvm::ConstantInt::get(Int32Ty,
>> >> > + /*Version=*/CoverageMappingVersion1),
>> >> > + RecordsVal, FilenamesAndMappingsVal};
>> >> > + auto CovDataVal =
>> >> > + llvm::ConstantStruct::get(CovDataTy,
>> makeArrayRef(TUDataVals));
>> >> > + auto CovData = new llvm::GlobalVariable(CGM.getModule(),
>> CovDataTy,
>> >> > true,
>> >> > +
>> >> > llvm::GlobalValue::InternalLinkage,
>> >> > + CovDataVal,
>> >> > +
>> "__llvm_coverage_mapping");
>> >> > +
>> >> > + CovData->setSection(getCoverageSection(CGM));
>> >> > + CovData->setAlignment(8);
>> >> > +
>> >> > + // Make sure the data doesn't get deleted.
>> >> > + CGM.addUsedGlobal(CovData);
>> >> > +}
>> >> > +
>> >> > +unsigned CoverageMappingModuleGen::getFileID(const FileEntry *File)
>> {
>> >> > + auto It = FileEntries.find(File);
>> >> > + if (It != FileEntries.end())
>> >> > + return It->second;
>> >> > + unsigned FileID = FileEntries.size();
>> >> > + FileEntries.insert(std::make_pair(File, FileID));
>> >> > + return FileID;
>> >> > +}
>> >> > +
>> >> > +void CoverageMappingGen::emitCounterMapping(const Decl *D,
>> >> > + llvm::raw_ostream &OS) {
>> >> > + assert(CounterMap);
>> >> > + CounterCoverageMappingBuilder Walker(CVM, *CounterMap,
>> >> > NumRegionCounters, SM,
>> >> > + LangOpts);
>> >> > + Walker.VisitDecl(D);
>> >> > + Walker.write(OS);
>> >> > +}
>> >> > +
>> >> > +void CoverageMappingGen::emitEmptyMapping(const Decl *D,
>> >> > + llvm::raw_ostream &OS) {
>> >> > + EmptyCoverageMappingBuilder Walker(CVM, SM, LangOpts);
>> >> > + Walker.VisitDecl(D);
>> >> > + Walker.write(OS);
>> >> > +}
>> >> >
>> >> > Added: cfe/trunk/lib/CodeGen/CoverageMappingGen.h
>> >> > URL:
>> >> >
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CoverageMappingGen.h?rev=214752&view=auto
>> >> >
>> >> >
>> ==============================================================================
>> >> > --- cfe/trunk/lib/CodeGen/CoverageMappingGen.h (added)
>> >> > +++ cfe/trunk/lib/CodeGen/CoverageMappingGen.h Mon Aug 4 13:41:51
>> 2014
>> >> > @@ -0,0 +1,117 @@
>> >> > +//===---- CoverageMappingGen.h - Coverage mapping generation ----*-
>> C++
>> >> > -*-===//
>> >> > +//
>> >> > +// The LLVM Compiler Infrastructure
>> >> > +//
>> >> > +// This file is distributed under the University of Illinois Open
>> >> > Source
>> >> > +// License. See LICENSE.TXT for details.
>> >> > +//
>> >> >
>> >> >
>> +//===----------------------------------------------------------------------===//
>> >> > +//
>> >> > +// Instrumentation-based code coverage mapping generator
>> >> > +//
>> >> >
>> >> >
>> +//===----------------------------------------------------------------------===//
>> >> > +
>> >> > +#ifndef CLANG_CODEGEN_COVERAGEMAPPINGGEN_H
>> >> > +#define CLANG_CODEGEN_COVERAGEMAPPINGGEN_H
>> >> > +
>> >> > +#include "clang/Basic/LLVM.h"
>> >> > +#include "clang/Basic/SourceLocation.h"
>> >> > +#include "clang/Lex/PPCallbacks.h"
>> >> > +#include "clang/Frontend/CodeGenOptions.h"
>> >> > +#include "llvm/ADT/StringMap.h"
>> >> > +#include "llvm/ADT/DenseMap.h"
>> >> > +#include "llvm/IR/GlobalValue.h"
>> >> > +#include "llvm/Support/raw_ostream.h"
>> >> > +
>> >> > +namespace clang {
>> >> > +
>> >> > +class LangOptions;
>> >> > +class SourceManager;
>> >> > +class FileEntry;
>> >> > +class Preprocessor;
>> >> > +class Decl;
>> >> > +class Stmt;
>> >> > +
>> >> > +/// \brief Stores additional source code information like skipped
>> >> > ranges which
>> >> > +/// is required by the coverage mapping generator and is obtained
>> from
>> >> > +/// the preprocessor.
>> >> > +class CoverageSourceInfo : public PPCallbacks {
>> >> > + std::vector<SourceRange> SkippedRanges;
>> >> > +public:
>> >> > + ArrayRef<SourceRange> getSkippedRanges() const { return
>> >> > SkippedRanges; }
>> >> > +
>> >> > + void SourceRangeSkipped(SourceRange Range) override;
>> >> > +};
>> >> > +
>> >> > +namespace CodeGen {
>> >> > +
>> >> > +class CodeGenModule;
>> >> > +
>> >> > +/// \brief Organizes the cross-function state that is used while
>> >> > generating
>> >> > +/// code coverage mapping data.
>> >> > +class CoverageMappingModuleGen {
>> >> > + CodeGenModule &CGM;
>> >> > + CoverageSourceInfo &SourceInfo;
>> >> > + llvm::SmallDenseMap<const FileEntry *, unsigned, 8> FileEntries;
>> >> > + std::vector<llvm::Constant *> FunctionRecords;
>> >> > + llvm::StructType *FunctionRecordTy;
>> >> > + std::string CoverageMappings;
>> >> > +
>> >> > +public:
>> >> > + CoverageMappingModuleGen(CodeGenModule &CGM, CoverageSourceInfo
>> >> > &SourceInfo)
>> >> > + : CGM(CGM), SourceInfo(SourceInfo), FunctionRecordTy(nullptr)
>> {}
>> >> > +
>> >> > + CoverageSourceInfo &getSourceInfo() const {
>> >> > + return SourceInfo;
>> >> > + }
>> >> > +
>> >> > + /// \brief Add a function's coverage mapping record to the
>> collection
>> >> > of the
>> >> > + /// function mapping records.
>> >> > + void addFunctionMappingRecord(llvm::GlobalVariable *FunctionName,
>> >> > + unsigned FunctionNameSize,
>> >> > + const std::string &CoverageMapping);
>> >> > +
>> >> > + /// \brief Emit the coverage mapping data for a translation unit.
>> >> > + void emit();
>> >> > +
>> >> > + /// \brief Return the coverage mapping translation unit file id
>> >> > + /// for the given file.
>> >> > + unsigned getFileID(const FileEntry *File);
>> >> > +};
>> >> > +
>> >> > +/// \brief Organizes the per-function state that is used while
>> >> > generating
>> >> > +/// code coverage mapping data.
>> >> > +class CoverageMappingGen {
>> >> > + CoverageMappingModuleGen &CVM;
>> >> > + SourceManager &SM;
>> >> > + const LangOptions &LangOpts;
>> >> > + llvm::DenseMap<const Stmt *, unsigned> *CounterMap;
>> >> > + unsigned NumRegionCounters;
>> >> > +
>> >> > +public:
>> >> > + CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager
>> &SM,
>> >> > + const LangOptions &LangOpts)
>> >> > + : CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(nullptr),
>> >> > + NumRegionCounters(0) {}
>> >> > +
>> >> > + CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager
>> &SM,
>> >> > + const LangOptions &LangOpts,
>> >> > + llvm::DenseMap<const Stmt *, unsigned>
>> >> > *CounterMap,
>> >> > + unsigned NumRegionCounters)
>> >> > + : CVM(CVM), SM(SM), LangOpts(LangOpts),
>> CounterMap(CounterMap),
>> >> > + NumRegionCounters(NumRegionCounters) {}
>> >> > +
>> >> > + /// \brief Emit the coverage mapping data which maps the regions
>> of
>> >> > + /// code to counters that will be used to find the execution
>> >> > + /// counts for those regions.
>> >> > + void emitCounterMapping(const Decl *D, llvm::raw_ostream &OS);
>> >> > +
>> >> > + /// \brief Emit the coverage mapping data for an unused function.
>> >> > + /// It creates mapping regions with the counter of zero.
>> >> > + void emitEmptyMapping(const Decl *D, llvm::raw_ostream &OS);
>> >> > +};
>> >> > +
>> >> > +} // end namespace CodeGen
>> >> > +} // end namespace clang
>> >> > +
>> >> > +#endif
>> >> >
>> >> > Modified: cfe/trunk/lib/CodeGen/ModuleBuilder.cpp
>> >> > URL:
>> >> >
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ModuleBuilder.cpp?rev=214752&r1=214751&r2=214752&view=diff
>> >> >
>> >> >
>> ==============================================================================
>> >> > --- cfe/trunk/lib/CodeGen/ModuleBuilder.cpp (original)
>> >> > +++ cfe/trunk/lib/CodeGen/ModuleBuilder.cpp Mon Aug 4 13:41:51 2014
>> >> > @@ -46,14 +46,18 @@ namespace {
>> >> > }
>> >> > };
>> >> >
>> >> > + CoverageSourceInfo *CoverageInfo;
>> >> > +
>> >> > protected:
>> >> > std::unique_ptr<llvm::Module> M;
>> >> > std::unique_ptr<CodeGen::CodeGenModule> Builder;
>> >> >
>> >> > public:
>> >> > CodeGeneratorImpl(DiagnosticsEngine &diags, const std::string&
>> >> > ModuleName,
>> >> > - const CodeGenOptions &CGO, llvm::LLVMContext&
>> C)
>> >> > + const CodeGenOptions &CGO, llvm::LLVMContext&
>> C,
>> >> > + CoverageSourceInfo *CoverageInfo = nullptr)
>> >> > : Diags(diags), CodeGenOpts(CGO), HandlingTopLevelDecls(0),
>> >> > + CoverageInfo(CoverageInfo),
>> >> > M(new llvm::Module(ModuleName, C)) {}
>> >> >
>> >> > virtual ~CodeGeneratorImpl() {}
>> >> > @@ -86,7 +90,7 @@ namespace {
>> >> > M->setDataLayout(Ctx->getTargetInfo().getTargetDescription());
>> >> > TD.reset(new
>> >> > llvm::DataLayout(Ctx->getTargetInfo().getTargetDescription()));
>> >> > Builder.reset(new CodeGen::CodeGenModule(Context, CodeGenOpts,
>> >> > *M, *TD,
>> >> > - Diags));
>> >> > + Diags,
>> CoverageInfo));
>> >> >
>> >> > for (size_t i = 0, e = CodeGenOpts.DependentLibraries.size();
>> i <
>> >> > e; ++i)
>> >> > HandleDependentLibrary(CodeGenOpts.DependentLibraries[i]);
>> >> > @@ -136,6 +140,10 @@ namespace {
>> >> > // void foo() { bar(); }
>> >> > // } A;
>> >> > DeferredInlineMethodDefinitions.push_back(D);
>> >> > +
>> >> > + // Always provide some coverage mapping
>> >> > + // even for the methods that aren't emitted.
>> >> > + Builder->AddDeferredUnusedCoverageMapping(D);
>> >> > }
>> >> >
>> >> > /// HandleTagDeclDefinition - This callback is invoked each
>> time a
>> >> > TagDecl
>> >> > @@ -221,6 +229,7 @@ CodeGenerator *clang::CreateLLVMCodeGen(
>> >> > const std::string&
>> ModuleName,
>> >> > const CodeGenOptions &CGO,
>> >> > const TargetOptions &/*TO*/,
>> >> > - llvm::LLVMContext& C) {
>> >> > - return new CodeGeneratorImpl(Diags, ModuleName, CGO, C);
>> >> > + llvm::LLVMContext& C,
>> >> > + CoverageSourceInfo
>> >> > *CoverageInfo) {
>> >> > + return new CodeGeneratorImpl(Diags, ModuleName, CGO, C,
>> >> > CoverageInfo);
>> >> > }
>> >> >
>> >> > Modified: cfe/trunk/lib/Driver/Tools.cpp
>> >> > URL:
>> >> >
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=214752&r1=214751&r2=214752&view=diff
>> >> >
>> >> >
>> ==============================================================================
>> >> > --- cfe/trunk/lib/Driver/Tools.cpp (original)
>> >> > +++ cfe/trunk/lib/Driver/Tools.cpp Mon Aug 4 13:41:51 2014
>> >> > @@ -3230,6 +3230,14 @@ void Clang::ConstructJob(Compilation &C,
>> >> > Args.hasArg(options::OPT_coverage))
>> >> > CmdArgs.push_back("-femit-coverage-data");
>> >> >
>> >> > + if (Args.hasArg(options::OPT_fcoverage_mapping) &&
>> >> > + !Args.hasArg(options::OPT_fprofile_instr_generate))
>> >> > + D.Diag(diag::err_drv_argument_only_allowed_with)
>> >> > + << "-fcoverage-mapping" << "-fprofile-instr-generate";
>> >> > +
>> >> > + if (Args.hasArg(options::OPT_fcoverage_mapping))
>> >> > + CmdArgs.push_back("-fcoverage-mapping");
>> >> > +
>> >> > if (C.getArgs().hasArg(options::OPT_c) ||
>> >> > C.getArgs().hasArg(options::OPT_S)) {
>> >> > if (Output.isFilename()) {
>> >> >
>> >> > Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
>> >> > URL:
>> >> >
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=214752&r1=214751&r2=214752&view=diff
>> >> >
>> >> >
>> ==============================================================================
>> >> > --- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
>> >> > +++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Mon Aug 4 13:41:51
>> >> > 2014
>> >> > @@ -403,6 +403,7 @@ static bool ParseCodeGenArgs(CodeGenOpti
>> >> > Opts.SampleProfileFile =
>> >> > Args.getLastArgValue(OPT_fprofile_sample_use_EQ);
>> >> > Opts.ProfileInstrGenerate =
>> Args.hasArg(OPT_fprofile_instr_generate);
>> >> > Opts.InstrProfileInput =
>> >> > Args.getLastArgValue(OPT_fprofile_instr_use_EQ);
>> >> > + Opts.CoverageMapping = Args.hasArg(OPT_fcoverage_mapping);
>> >> > Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose);
>> >> > Opts.ObjCAutoRefCountExceptions =
>> >> > Args.hasArg(OPT_fobjc_arc_exceptions);
>> >> > Opts.CUDAIsDevice = Args.hasArg(OPT_fcuda_is_device);
>> >> >
>> >> >
>> >> > _______________________________________________
>> >> > cfe-commits mailing list
>> >> > cfe-commits at cs.uiuc.edu
>> >> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>> >
>> >
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140804/88abde63/attachment.html>
More information about the cfe-commits
mailing list