Skip to content

Commit ee02499

Browse files
committedAug 4, 2014
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
1 parent 1193b5e commit ee02499

16 files changed

+1577
-54
lines changed
 

‎clang/include/clang/CodeGen/CodeGenABITypes.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class CXXRecordDecl;
3939
class CodeGenOptions;
4040
class DiagnosticsEngine;
4141
class ObjCMethodDecl;
42+
class CoverageSourceInfo;
4243

4344
namespace CodeGen {
4445
class CGFunctionInfo;
@@ -47,7 +48,8 @@ class CodeGenModule;
4748
class CodeGenABITypes
4849
{
4950
public:
50-
CodeGenABITypes(ASTContext &C, llvm::Module &M, const llvm::DataLayout &TD);
51+
CodeGenABITypes(ASTContext &C, llvm::Module &M, const llvm::DataLayout &TD,
52+
CoverageSourceInfo *CoverageInfo = nullptr);
5153
~CodeGenABITypes();
5254

5355
/// These methods all forward to methods in the private implementation class

‎clang/include/clang/CodeGen/ModuleBuilder.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ namespace llvm {
2424

2525
namespace clang {
2626
class DiagnosticsEngine;
27+
class CoverageSourceInfo;
2728
class LangOptions;
2829
class CodeGenOptions;
2930
class TargetOptions;
@@ -44,7 +45,8 @@ namespace clang {
4445
const std::string &ModuleName,
4546
const CodeGenOptions &CGO,
4647
const TargetOptions &TO,
47-
llvm::LLVMContext& C);
48+
llvm::LLVMContext& C,
49+
CoverageSourceInfo *CoverageInfo = nullptr);
4850
}
4951

5052
#endif

‎clang/include/clang/Driver/Options.td

+3
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,9 @@ def fprofile_instr_use : Flag<["-"], "fprofile-instr-use">, Group<f_Group>;
408408
def fprofile_instr_use_EQ : Joined<["-"], "fprofile-instr-use=">,
409409
Group<f_Group>, Flags<[CC1Option]>,
410410
HelpText<"Use instrumentation data for profile-guided optimization">;
411+
def fcoverage_mapping : Flag<["-"], "fcoverage-mapping">,
412+
Group<f_Group>, Flags<[CC1Option]>,
413+
HelpText<"Generate coverage mapping to enable code coverage analysis">;
411414

412415
def fblocks : Flag<["-"], "fblocks">, Group<f_Group>, Flags<[CC1Option]>,
413416
HelpText<"Enable the 'blocks' language feature">;

‎clang/include/clang/Frontend/CodeGenOptions.def

+2
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified
8888

8989
CODEGENOPT(ProfileInstrGenerate , 1, 0) ///< Instrument code to generate
9090
///< execution counts to use with PGO.
91+
CODEGENOPT(CoverageMapping , 1, 0) ///< Generate coverage mapping regions to
92+
///< enable code coverage analysis.
9193

9294
/// If -fpcc-struct-return or -freg-struct-return is specified.
9395
ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default)

‎clang/lib/CodeGen/CodeGenABITypes.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ using namespace CodeGen;
2626

2727
CodeGenABITypes::CodeGenABITypes(ASTContext &C,
2828
llvm::Module &M,
29-
const llvm::DataLayout &TD)
29+
const llvm::DataLayout &TD,
30+
CoverageSourceInfo *CoverageInfo)
3031
: CGO(new CodeGenOptions),
31-
CGM(new CodeGen::CodeGenModule(C, *CGO, M, TD, C.getDiagnostics())) {
32+
CGM(new CodeGen::CodeGenModule(C, *CGO, M, TD, C.getDiagnostics(),
33+
CoverageInfo)) {
3234
}
3335

3436
CodeGenABITypes::~CodeGenABITypes()

‎clang/lib/CodeGen/CodeGenAction.cpp

+14-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//
88
//===----------------------------------------------------------------------===//
99

10+
#include "CoverageMappingGen.h"
1011
#include "clang/CodeGen/CodeGenAction.h"
1112
#include "clang/AST/ASTConsumer.h"
1213
#include "clang/AST/ASTContext.h"
@@ -15,6 +16,7 @@
1516
#include "clang/Basic/FileManager.h"
1617
#include "clang/Basic/SourceManager.h"
1718
#include "clang/Basic/TargetInfo.h"
19+
#include "clang/Lex/Preprocessor.h"
1820
#include "clang/CodeGen/BackendUtil.h"
1921
#include "clang/CodeGen/ModuleBuilder.h"
2022
#include "clang/Frontend/CompilerInstance.h"
@@ -59,11 +61,13 @@ namespace clang {
5961
const TargetOptions &targetopts,
6062
const LangOptions &langopts, bool TimePasses,
6163
const std::string &infile, llvm::Module *LinkModule,
62-
raw_ostream *OS, LLVMContext &C)
64+
raw_ostream *OS, LLVMContext &C,
65+
CoverageSourceInfo *CoverageInfo = nullptr)
6366
: Diags(_Diags), Action(action), CodeGenOpts(compopts),
6467
TargetOpts(targetopts), LangOpts(langopts), AsmOutStream(OS),
6568
Context(), LLVMIRGeneration("LLVM IR Generation Time"),
66-
Gen(CreateLLVMCodeGen(Diags, infile, compopts, targetopts, C)),
69+
Gen(CreateLLVMCodeGen(Diags, infile, compopts,
70+
targetopts, C, CoverageInfo)),
6771
LinkModule(LinkModule) {
6872
llvm::TimePassesIsEnabled = TimePasses;
6973
}
@@ -636,10 +640,17 @@ ASTConsumer *CodeGenAction::CreateASTConsumer(CompilerInstance &CI,
636640
LinkModuleToUse = ModuleOrErr.get();
637641
}
638642

643+
CoverageSourceInfo *CoverageInfo = nullptr;
644+
// Add the preprocessor callback only when the coverage mapping is generated.
645+
if (CI.getCodeGenOpts().CoverageMapping) {
646+
CoverageInfo = new CoverageSourceInfo;
647+
CI.getPreprocessor().addPPCallbacks(CoverageInfo);
648+
}
639649
BEConsumer = new BackendConsumer(BA, CI.getDiagnostics(), CI.getCodeGenOpts(),
640650
CI.getTargetOpts(), CI.getLangOpts(),
641651
CI.getFrontendOpts().ShowTimers, InFile,
642-
LinkModuleToUse, OS.release(), *VMContext);
652+
LinkModuleToUse, OS.release(), *VMContext,
653+
CoverageInfo);
643654
return BEConsumer;
644655
}
645656

‎clang/lib/CodeGen/CodeGenFunction.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
829829
StartFunction(GD, ResTy, Fn, FnInfo, Args, Loc, BodyRange.getBegin());
830830

831831
// Generate the body of the function.
832+
PGO.checkGlobalDecl(GD);
832833
PGO.assignRegionCounters(GD.getDecl(), CurFn);
833834
if (isa<CXXDestructorDecl>(FD))
834835
EmitDestructorBody(Args);

‎clang/lib/CodeGen/CodeGenModule.cpp

+88-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "CGOpenMPRuntime.h"
2222
#include "CodeGenFunction.h"
2323
#include "CodeGenPGO.h"
24+
#include "CoverageMappingGen.h"
2425
#include "CodeGenTBAA.h"
2526
#include "TargetInfo.h"
2627
#include "clang/AST/ASTContext.h"
@@ -74,7 +75,8 @@ static CGCXXABI *createCXXABI(CodeGenModule &CGM) {
7475

7576
CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
7677
llvm::Module &M, const llvm::DataLayout &TD,
77-
DiagnosticsEngine &diags)
78+
DiagnosticsEngine &diags,
79+
CoverageSourceInfo *CoverageInfo)
7880
: Context(C), LangOpts(C.getLangOpts()), CodeGenOpts(CGO), TheModule(M),
7981
Diags(diags), TheDataLayout(TD), Target(C.getTargetInfo()),
8082
ABI(createCXXABI(*this)), VMContext(M.getContext()), TBAA(nullptr),
@@ -146,6 +148,11 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
146148
getDiags().Report(DiagID) << EC.message();
147149
}
148150
}
151+
152+
// If coverage mapping generation is enabled, create the
153+
// CoverageMappingModuleGen object.
154+
if (CodeGenOpts.CoverageMapping)
155+
CoverageMapping.reset(new CoverageMappingModuleGen(*this, *CoverageInfo));
149156
}
150157

151158
CodeGenModule::~CodeGenModule() {
@@ -344,6 +351,9 @@ void CodeGenModule::Release() {
344351
EmitCtorList(GlobalDtors, "llvm.global_dtors");
345352
EmitGlobalAnnotations();
346353
EmitStaticExternCAliases();
354+
EmitDeferredUnusedCoverageMappings();
355+
if (CoverageMapping)
356+
CoverageMapping->emit();
347357
emitLLVMUsed();
348358

349359
if (CodeGenOpts.Autolink &&
@@ -2989,6 +2999,9 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
29892999
return;
29903000

29913001
EmitGlobal(cast<FunctionDecl>(D));
3002+
// Always provide some coverage mapping
3003+
// even for the functions that aren't emitted.
3004+
AddDeferredUnusedCoverageMapping(D);
29923005
break;
29933006

29943007
case Decl::Var:
@@ -3138,6 +3151,80 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
31383151
}
31393152
}
31403153

3154+
void CodeGenModule::AddDeferredUnusedCoverageMapping(Decl *D) {
3155+
// Do we need to generate coverage mapping?
3156+
if (!CodeGenOpts.CoverageMapping)
3157+
return;
3158+
switch (D->getKind()) {
3159+
case Decl::CXXConversion:
3160+
case Decl::CXXMethod:
3161+
case Decl::Function:
3162+
case Decl::ObjCMethod:
3163+
case Decl::CXXConstructor:
3164+
case Decl::CXXDestructor: {
3165+
if (!cast<FunctionDecl>(D)->hasBody())
3166+
return;
3167+
auto I = DeferredEmptyCoverageMappingDecls.find(D);
3168+
if (I == DeferredEmptyCoverageMappingDecls.end())
3169+
DeferredEmptyCoverageMappingDecls[D] = true;
3170+
break;
3171+
}
3172+
default:
3173+
break;
3174+
};
3175+
}
3176+
3177+
void CodeGenModule::ClearUnusedCoverageMapping(const Decl *D) {
3178+
// Do we need to generate coverage mapping?
3179+
if (!CodeGenOpts.CoverageMapping)
3180+
return;
3181+
if (const auto *Fn = dyn_cast<FunctionDecl>(D)) {
3182+
if (Fn->isTemplateInstantiation())
3183+
ClearUnusedCoverageMapping(Fn->getTemplateInstantiationPattern());
3184+
}
3185+
auto I = DeferredEmptyCoverageMappingDecls.find(D);
3186+
if (I == DeferredEmptyCoverageMappingDecls.end())
3187+
DeferredEmptyCoverageMappingDecls[D] = false;
3188+
else
3189+
I->second = false;
3190+
}
3191+
3192+
void CodeGenModule::EmitDeferredUnusedCoverageMappings() {
3193+
for (const auto I : DeferredEmptyCoverageMappingDecls) {
3194+
if (!I.second)
3195+
continue;
3196+
const auto *D = I.first;
3197+
switch (D->getKind()) {
3198+
case Decl::CXXConversion:
3199+
case Decl::CXXMethod:
3200+
case Decl::Function:
3201+
case Decl::ObjCMethod: {
3202+
CodeGenPGO PGO(*this);
3203+
GlobalDecl GD(cast<FunctionDecl>(D));
3204+
PGO.emitEmptyCounterMapping(D, getMangledName(GD),
3205+
getFunctionLinkage(GD));
3206+
break;
3207+
}
3208+
case Decl::CXXConstructor: {
3209+
CodeGenPGO PGO(*this);
3210+
GlobalDecl GD(cast<CXXConstructorDecl>(D), Ctor_Base);
3211+
PGO.emitEmptyCounterMapping(D, getMangledName(GD),
3212+
getFunctionLinkage(GD));
3213+
break;
3214+
}
3215+
case Decl::CXXDestructor: {
3216+
CodeGenPGO PGO(*this);
3217+
GlobalDecl GD(cast<CXXDestructorDecl>(D), Dtor_Base);
3218+
PGO.emitEmptyCounterMapping(D, getMangledName(GD),
3219+
getFunctionLinkage(GD));
3220+
break;
3221+
}
3222+
default:
3223+
break;
3224+
};
3225+
}
3226+
}
3227+
31413228
/// Turns the given pointer into a constant.
31423229
static llvm::Constant *GetPointerConstant(llvm::LLVMContext &Context,
31433230
const void *Ptr) {

‎clang/lib/CodeGen/CodeGenModule.h

+24-1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class DiagnosticsEngine;
7373
class AnnotateAttr;
7474
class CXXDestructorDecl;
7575
class Module;
76+
class CoverageSourceInfo;
7677

7778
namespace CodeGen {
7879

@@ -87,6 +88,7 @@ class CGOpenMPRuntime;
8788
class CGCUDARuntime;
8889
class BlockFieldFlags;
8990
class FunctionArgList;
91+
class CoverageMappingModuleGen;
9092

9193
struct OrderGlobalInits {
9294
unsigned int priority;
@@ -477,10 +479,15 @@ class CodeGenModule : public CodeGenTypeCache {
477479
std::unique_ptr<SanitizerMetadata> SanitizerMD;
478480

479481
/// @}
482+
483+
llvm::DenseMap<const Decl *, bool> DeferredEmptyCoverageMappingDecls;
484+
485+
std::unique_ptr<CoverageMappingModuleGen> CoverageMapping;
480486
public:
481487
CodeGenModule(ASTContext &C, const CodeGenOptions &CodeGenOpts,
482488
llvm::Module &M, const llvm::DataLayout &TD,
483-
DiagnosticsEngine &Diags);
489+
DiagnosticsEngine &Diags,
490+
CoverageSourceInfo *CoverageInfo = nullptr);
484491

485492
~CodeGenModule();
486493

@@ -529,6 +536,10 @@ class CodeGenModule : public CodeGenTypeCache {
529536
InstrProfStats &getPGOStats() { return PGOStats; }
530537
llvm::IndexedInstrProfReader *getPGOReader() const { return PGOReader.get(); }
531538

539+
CoverageMappingModuleGen *getCoverageMapping() const {
540+
return CoverageMapping.get();
541+
}
542+
532543
llvm::Constant *getStaticLocalDeclAddress(const VarDecl *D) {
533544
return StaticLocalDeclMap[D];
534545
}
@@ -815,6 +826,18 @@ class CodeGenModule : public CodeGenTypeCache {
815826
/// Emit code for a single top level declaration.
816827
void EmitTopLevelDecl(Decl *D);
817828

829+
/// \brief Stored a deferred empty coverage mapping for an unused
830+
/// and thus uninstrumented top level declaration.
831+
void AddDeferredUnusedCoverageMapping(Decl *D);
832+
833+
/// \brief Remove the deferred empty coverage mapping as this
834+
/// declaration is actually instrumented.
835+
void ClearUnusedCoverageMapping(const Decl *D);
836+
837+
/// \brief Emit all the deferred coverage mappings
838+
/// for the uninstrumented functions.
839+
void EmitDeferredUnusedCoverageMappings();
840+
818841
/// Tell the consumer that this variable has been instantiated.
819842
void HandleCXXStaticMemberVarInstantiation(VarDecl *VD);
820843

0 commit comments

Comments
 (0)
Please sign in to comment.