From: Alex Lorenz Date: Fri, 8 Aug 2014 23:41:24 +0000 (+0000) Subject: Add a cc1 "dump-coverage-mapping" for testing coverage mapping. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a115a4d86203fa2101f8a59dc171b96393f95493;p=clang Add a cc1 "dump-coverage-mapping" for testing coverage mapping. Differential Revision: http://reviews.llvm.org/D4799 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@215258 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index c3685e0f30..ae3001c3d2 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -179,6 +179,8 @@ def coverage_version_EQ : Joined<["-"], "coverage-version=">, HelpText<"Four-byte version string for gcov files.">; def test_coverage : Flag<["-"], "test-coverage">, HelpText<"Do not generate coverage files or remove coverage changes from IR">; +def dump_coverage_mapping : Flag<["-"], "dump-coverage-mapping">, + HelpText<"Dump the coverage mapping records, for testing">; def fuse_register_sized_bitfield_access: Flag<["-"], "fuse-register-sized-bitfield-access">, HelpText<"Use register sized accesses to bit-fields, when possible.">; def relaxed_aliasing : Flag<["-"], "relaxed-aliasing">, diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index 3767b4244f..71795a2ed2 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -90,6 +90,8 @@ 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. +CODEGENOPT(DumpCoverageMapping , 1, 0) ///< Dump the generated coverage mapping + ///< regions. /// If -fpcc-struct-return or -freg-struct-return is specified. ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default) diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 5040965161..1f0dd73e65 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -3198,10 +3198,20 @@ void CodeGenModule::ClearUnusedCoverageMapping(const Decl *D) { } void CodeGenModule::EmitDeferredUnusedCoverageMappings() { + std::vector DeferredDecls; for (const auto I : DeferredEmptyCoverageMappingDecls) { if (!I.second) continue; - const auto *D = I.first; + DeferredDecls.push_back(I.first); + } + // Sort the declarations by their location to make sure that the tests get a + // predictable order for the coverage mapping for the unused declarations. + if (CodeGenOpts.DumpCoverageMapping) + std::sort(DeferredDecls.begin(), DeferredDecls.end(), + [] (const Decl *LHS, const Decl *RHS) { + return LHS->getLocStart() < RHS->getLocStart(); + }); + for (const auto *D : DeferredDecls) { switch (D->getKind()) { case Decl::CXXConversion: case Decl::CXXMethod: diff --git a/lib/CodeGen/CodeGenPGO.cpp b/lib/CodeGen/CodeGenPGO.cpp index e6dbad856c..7fb64b85a0 100644 --- a/lib/CodeGen/CodeGenPGO.cpp +++ b/lib/CodeGen/CodeGenPGO.cpp @@ -169,7 +169,7 @@ llvm::GlobalVariable *CodeGenPGO::buildDataVar() { // Create coverage mapping data variable. if (!CoverageMapping.empty()) CGM.getCoverageMapping()->addFunctionMappingRecord(Name, - getFuncName().size(), + getFuncName(), CoverageMapping); // Hide all these symbols so that we correctly get a copy for each diff --git a/lib/CodeGen/CoverageMappingGen.cpp b/lib/CodeGen/CoverageMappingGen.cpp index 526d30f20b..836d09f734 100644 --- a/lib/CodeGen/CoverageMappingGen.cpp +++ b/lib/CodeGen/CoverageMappingGen.cpp @@ -18,6 +18,7 @@ #include "llvm/ProfileData/InstrProfReader.h" #include "llvm/ProfileData/CoverageMapping.h" #include "llvm/ProfileData/CoverageMappingWriter.h" +#include "llvm/ProfileData/CoverageMappingReader.h" #include "llvm/Support/FileSystem.h" using namespace clang; @@ -1052,8 +1053,36 @@ static StringRef getCoverageSection(const CodeGenModule &CGM) { return isMachO(CGM) ? "__DATA,__llvm_covmap" : "__llvm_covmap"; } +static void dump(llvm::raw_ostream &OS, const CoverageMappingRecord &Function) { + OS << Function.FunctionName << ":\n"; + CounterMappingContext Ctx(Function.Expressions); + for (const auto &R : Function.MappingRegions) { + OS.indent(2); + switch (R.Kind) { + case CounterMappingRegion::CodeRegion: + break; + case CounterMappingRegion::ExpansionRegion: + OS << "Expansion,"; + break; + case CounterMappingRegion::SkippedRegion: + OS << "Skipped,"; + break; + } + + OS << "File " << R.FileID << ", " << R.LineStart << ":" + << R.ColumnStart << " -> " << R.LineEnd << ":" << R.ColumnEnd + << " = "; + Ctx.dump(R.Count); + OS << " (HasCodeBefore = " << R.HasCodeBefore; + if (R.Kind == CounterMappingRegion::ExpansionRegion) + OS << ", Expanded file = " << R.ExpandedFileID; + + OS << ")\n"; + } +} + void CoverageMappingModuleGen::addFunctionMappingRecord( - llvm::GlobalVariable *FunctionName, unsigned FunctionNameSize, + llvm::GlobalVariable *FunctionName, StringRef FunctionNameValue, const std::string &CoverageMapping) { llvm::LLVMContext &Ctx = CGM.getLLVMContext(); auto *Int32Ty = llvm::Type::getInt32Ty(Ctx); @@ -1066,11 +1095,33 @@ void CoverageMappingModuleGen::addFunctionMappingRecord( llvm::Constant *FunctionRecordVals[] = { llvm::ConstantExpr::getBitCast(FunctionName, Int8PtrTy), - llvm::ConstantInt::get(Int32Ty, FunctionNameSize), + llvm::ConstantInt::get(Int32Ty, FunctionNameValue.size()), llvm::ConstantInt::get(Int32Ty, CoverageMapping.size())}; FunctionRecords.push_back(llvm::ConstantStruct::get( FunctionRecordTy, makeArrayRef(FunctionRecordVals))); CoverageMappings += CoverageMapping; + + if (CGM.getCodeGenOpts().DumpCoverageMapping) { + // Dump the coverage mapping data for this function by decoding the + // encoded data. This allows us to dump the mapping regions which were + // also processed by the CoverageMappingWriter which performs + // additional minimization operations such as reducing the number of + // expressions. + std::vector Filenames; + std::vector Expressions; + std::vector Regions; + llvm::SmallVector FilenameRefs; + FilenameRefs.resize(FileEntries.size()); + for (const auto &Entry : FileEntries) + FilenameRefs[Entry.second] = Entry.first->getName(); + RawCoverageMappingReader Reader(FunctionNameValue, CoverageMapping, + FilenameRefs, + Filenames, Expressions, Regions); + CoverageMappingRecord FunctionRecord; + if (Reader.read(FunctionRecord)) + return; + dump(llvm::outs(), FunctionRecord); + } } void CoverageMappingModuleGen::emit() { diff --git a/lib/CodeGen/CoverageMappingGen.h b/lib/CodeGen/CoverageMappingGen.h index e77dedb925..5a73a47fee 100644 --- a/lib/CodeGen/CoverageMappingGen.h +++ b/lib/CodeGen/CoverageMappingGen.h @@ -68,7 +68,7 @@ public: /// \brief Add a function's coverage mapping record to the collection of the /// function mapping records. void addFunctionMappingRecord(llvm::GlobalVariable *FunctionName, - unsigned FunctionNameSize, + StringRef FunctionNameValue, const std::string &CoverageMapping); /// \brief Emit the coverage mapping data for a translation unit. diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 1a67e1376e..7b864bf31f 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -400,6 +400,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, 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.DumpCoverageMapping = Args.hasArg(OPT_dump_coverage_mapping); Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose); Opts.ObjCAutoRefCountExceptions = Args.hasArg(OPT_fobjc_arc_exceptions); Opts.CUDAIsDevice = Args.hasArg(OPT_fcuda_is_device);