Ah, sorry - thanks :)
On Mon, Aug 4, 2014 at 12:10 PM, Alex L <[email protected]> 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 <[email protected]>: >> >> CMake build fixed in r214758 >> >> On Mon, Aug 4, 2014 at 11:41 AM, Alex Lorenz <[email protected]> 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 >> > [email protected] >> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > > _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
