summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CodeGenModule.cpp
diff options
context:
space:
mode:
authorAlex Lorenz <arphaman@gmail.com>2014-08-04 18:41:51 +0000
committerAlex Lorenz <arphaman@gmail.com>2014-08-04 18:41:51 +0000
commitee02499a8fb64f9710b4543f2f46c5305dcb11fc (patch)
tree65514c3a36a4efeb1f20869ef94c33b107632ac2 /clang/lib/CodeGen/CodeGenModule.cpp
parent1193b5e272db7aa969380e95503b2512d3f17270 (diff)
downloadbcm5719-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.cpp89
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) {
OpenPOWER on IntegriCloud