diff options
Diffstat (limited to 'clang/lib/CodeGen/CoverageMappingGen.cpp')
-rw-r--r-- | clang/lib/CodeGen/CoverageMappingGen.cpp | 134 |
1 files changed, 55 insertions, 79 deletions
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 02840bf771c..bdecff39c88 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -13,8 +13,6 @@ #include "CoverageMappingGen.h" #include "CodeGenFunction.h" #include "clang/AST/StmtVisitor.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Lex/Lexer.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringExtras.h" @@ -26,10 +24,6 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" -// This selects the coverage mapping format defined when `InstrProfData.inc` -// is textually included. -#define COVMAP_V3 - using namespace clang; using namespace CodeGen; using namespace llvm::coverage; @@ -1278,6 +1272,12 @@ struct CounterCoverageMappingBuilder } }; +std::string getCoverageSection(const CodeGenModule &CGM) { + return llvm::getInstrProfSectionName( + llvm::IPSK_covmap, + CGM.getContext().getTargetInfo().getTriple().getObjectFormat()); +} + std::string normalizeFilename(StringRef Filename) { llvm::SmallString<256> Path(Filename); llvm::sys::fs::make_absolute(Path); @@ -1317,71 +1317,30 @@ static void dump(llvm::raw_ostream &OS, StringRef FunctionName, } } -static std::string getInstrProfSection(const CodeGenModule &CGM, - llvm::InstrProfSectKind SK) { - return llvm::getInstrProfSectionName( - SK, CGM.getContext().getTargetInfo().getTriple().getObjectFormat()); -} - -void CoverageMappingModuleGen::emitFunctionMappingRecord( - const FunctionInfo &Info, uint64_t FilenamesRef) { +void CoverageMappingModuleGen::addFunctionMappingRecord( + llvm::GlobalVariable *NamePtr, StringRef NameValue, uint64_t FuncHash, + const std::string &CoverageMapping, bool IsUsed) { llvm::LLVMContext &Ctx = CGM.getLLVMContext(); - - // Assign a name to the function record. This is used to merge duplicates. - std::string FuncRecordName = "__covrec_" + llvm::utohexstr(Info.NameHash); - - // A dummy description for a function included-but-not-used in a TU can be - // replaced by full description provided by a different TU. The two kinds of - // descriptions play distinct roles: therefore, assign them different names - // to prevent `linkonce_odr` merging. - if (Info.IsUsed) - FuncRecordName += "u"; - - // Create the function record type. - const uint64_t NameHash = Info.NameHash; - const uint64_t FuncHash = Info.FuncHash; - const std::string &CoverageMapping = Info.CoverageMapping; + if (!FunctionRecordTy) { #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType, - llvm::Type *FunctionRecordTypes[] = { -#include "llvm/ProfileData/InstrProfData.inc" - }; - auto *FunctionRecordTy = - llvm::StructType::get(Ctx, makeArrayRef(FunctionRecordTypes), - /*isPacked=*/true); + llvm::Type *FunctionRecordTypes[] = { + #include "llvm/ProfileData/InstrProfData.inc" + }; + FunctionRecordTy = + llvm::StructType::get(Ctx, makeArrayRef(FunctionRecordTypes), + /*isPacked=*/true); + } - // Create the function record constant. -#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Init, + #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Init, llvm::Constant *FunctionRecordVals[] = { #include "llvm/ProfileData/InstrProfData.inc" }; - auto *FuncRecordConstant = llvm::ConstantStruct::get( - FunctionRecordTy, makeArrayRef(FunctionRecordVals)); - - // Create the function record global. - auto *FuncRecord = new llvm::GlobalVariable( - CGM.getModule(), FunctionRecordTy, /*isConstant=*/true, - llvm::GlobalValue::LinkOnceODRLinkage, FuncRecordConstant, - FuncRecordName); - FuncRecord->setVisibility(llvm::GlobalValue::HiddenVisibility); - FuncRecord->setSection(getInstrProfSection(CGM, llvm::IPSK_covfun)); - FuncRecord->setAlignment(llvm::Align(8)); - if (CGM.supportsCOMDAT()) - FuncRecord->setComdat(CGM.getModule().getOrInsertComdat(FuncRecordName)); - - // Make sure the data doesn't get deleted. - CGM.addUsedGlobal(FuncRecord); -} - -void CoverageMappingModuleGen::addFunctionMappingRecord( - llvm::GlobalVariable *NamePtr, StringRef NameValue, uint64_t FuncHash, - const std::string &CoverageMapping, bool IsUsed) { - llvm::LLVMContext &Ctx = CGM.getLLVMContext(); - const uint64_t NameHash = llvm::IndexedInstrProf::ComputeHash(NameValue); - FunctionRecords.push_back({NameHash, FuncHash, CoverageMapping, IsUsed}); - + FunctionRecords.push_back(llvm::ConstantStruct::get( + FunctionRecordTy, makeArrayRef(FunctionRecordVals))); if (!IsUsed) FunctionNames.push_back( llvm::ConstantExpr::getBitCast(NamePtr, llvm::Type::getInt8PtrTy(Ctx))); + CoverageMappings.push_back(CoverageMapping); if (CGM.getCodeGenOpts().DumpCoverageMapping) { // Dump the coverage mapping data for this function by decoding the @@ -1426,22 +1385,37 @@ void CoverageMappingModuleGen::emit() { FilenameRefs[I] = FilenameStrs[I]; } - std::string Filenames; - { - llvm::raw_string_ostream OS(Filenames); - CoverageFilenamesSectionWriter(FilenameRefs).write(OS); + std::string FilenamesAndCoverageMappings; + llvm::raw_string_ostream OS(FilenamesAndCoverageMappings); + CoverageFilenamesSectionWriter(FilenameRefs).write(OS); + + // Stream the content of CoverageMappings to OS while keeping + // memory consumption under control. + size_t CoverageMappingSize = 0; + for (auto &S : CoverageMappings) { + CoverageMappingSize += S.size(); + OS << S; + S.clear(); + S.shrink_to_fit(); } - auto *FilenamesVal = - llvm::ConstantDataArray::getString(Ctx, Filenames, false); - const int64_t FilenamesRef = llvm::IndexedInstrProf::ComputeHash(Filenames); + CoverageMappings.clear(); + CoverageMappings.shrink_to_fit(); - // Emit the function records. - for (const FunctionInfo &Info : FunctionRecords) - emitFunctionMappingRecord(Info, FilenamesRef); + 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; + OS.write_zeros(8 - Rem); + } + 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); - const unsigned NRecords = 0; - const size_t FilenamesSize = Filenames.size(); - const unsigned CoverageMappingSize = 0; llvm::Type *CovDataHeaderTypes[] = { #define COVMAP_HEADER(Type, LLVMType, Name, Init) LLVMType, #include "llvm/ProfileData/InstrProfData.inc" @@ -1456,16 +1430,18 @@ void CoverageMappingModuleGen::emit() { CovDataHeaderTy, makeArrayRef(CovDataHeaderVals)); // Create the coverage data record - llvm::Type *CovDataTypes[] = {CovDataHeaderTy, FilenamesVal->getType()}; + llvm::Type *CovDataTypes[] = {CovDataHeaderTy, RecordsTy, + FilenamesAndMappingsVal->getType()}; auto CovDataTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataTypes)); - llvm::Constant *TUDataVals[] = {CovDataHeaderVal, FilenamesVal}; + llvm::Constant *TUDataVals[] = {CovDataHeaderVal, RecordsVal, + FilenamesAndMappingsVal}; auto CovDataVal = llvm::ConstantStruct::get(CovDataTy, makeArrayRef(TUDataVals)); auto CovData = new llvm::GlobalVariable( - CGM.getModule(), CovDataTy, true, llvm::GlobalValue::PrivateLinkage, + CGM.getModule(), CovDataTy, true, llvm::GlobalValue::InternalLinkage, CovDataVal, llvm::getCoverageMappingVarName()); - CovData->setSection(getInstrProfSection(CGM, llvm::IPSK_covmap)); + CovData->setSection(getCoverageSection(CGM)); CovData->setAlignment(llvm::Align(8)); // Make sure the data doesn't get deleted. |