diff options
author | Alex Lorenz <arphaman@gmail.com> | 2014-08-04 18:41:51 +0000 |
---|---|---|
committer | Alex Lorenz <arphaman@gmail.com> | 2014-08-04 18:41:51 +0000 |
commit | ee02499a8fb64f9710b4543f2f46c5305dcb11fc (patch) | |
tree | 65514c3a36a4efeb1f20869ef94c33b107632ac2 /clang/lib/CodeGen/CodeGenModule.cpp | |
parent | 1193b5e272db7aa969380e95503b2512d3f17270 (diff) | |
download | bcm5719-llvm-ee02499a8fb64f9710b4543f2f46c5305dcb11fc.tar.gz bcm5719-llvm-ee02499a8fb64f9710b4543f2f46c5305dcb11fc.zip |
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).
llvm-svn: 214752
Diffstat (limited to 'clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 89 |
1 files changed, 88 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 8b6aae21611..54c32200f52 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -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(CodeGenModule &CGM) { 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 &C, const CodeGenOptions &CGO, 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(Decl *D) { 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(Decl *D) { } } +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) { |