diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h index f97bbfd9e0d8..6e9e0af1db75 100644 --- a/llvm/include/llvm/ProfileData/InstrProf.h +++ b/llvm/include/llvm/ProfileData/InstrProf.h @@ -54,39 +54,29 @@ class MDNode; class Module; /// Return the name of data section containing profile counter variables. -inline StringRef getInstrProfCountersSectionName(bool AddSegment) { - return AddSegment ? "__DATA," INSTR_PROF_CNTS_SECT_NAME_STR - : INSTR_PROF_CNTS_SECT_NAME_STR; -} +/// If M is null, the target platform is assumed to be the same as +/// the host machine, and the segment prefix will not be added. +std::string getInstrProfCountersSectionName(const Module *M = nullptr); /// Return the name of data section containing names of instrumented -/// functions. -inline StringRef getInstrProfNameSectionName(bool AddSegment) { - return AddSegment ? "__DATA," INSTR_PROF_NAME_SECT_NAME_STR - : INSTR_PROF_NAME_SECT_NAME_STR; -} +/// functions. If M is null, the target platform is assumed to be the same as +/// the host machine, nor will segment prefix be added. +std::string getInstrProfNameSectionName(const Module *M = nullptr); /// Return the name of the data section containing per-function control -/// data. -inline StringRef getInstrProfDataSectionName(bool AddSegment) { - return AddSegment ? "__DATA," INSTR_PROF_DATA_SECT_NAME_STR - ",regular,live_support" - : INSTR_PROF_DATA_SECT_NAME_STR; -} +/// data. If M is null, the target platform is assumed to be the same as +/// the host machine, and the segment prefix will not be added. +std::string getInstrProfDataSectionName(const Module *M = nullptr); /// Return the name of data section containing pointers to value profile -/// counters/nodes. -inline StringRef getInstrProfValuesSectionName(bool AddSegment) { - return AddSegment ? "__DATA," INSTR_PROF_VALS_SECT_NAME_STR - : INSTR_PROF_VALS_SECT_NAME_STR; -} +/// counters/nodes. If M is null, the target platform is assumed to be +/// the same as the host machine, and the segment prefix will not be added. +std::string getInstrProfValuesSectionName(const Module *M = nullptr); /// Return the name of data section containing nodes holdling value -/// profiling data. -inline StringRef getInstrProfVNodesSectionName(bool AddSegment) { - return AddSegment ? "__DATA," INSTR_PROF_VNODES_SECT_NAME_STR - : INSTR_PROF_VNODES_SECT_NAME_STR; -} +/// profiling data. If M is null, the target platform is assumed to be +/// the same as the host machine, and the segment prefix will not be added. +std::string getInstrProfVNodesSectionName(const Module *M = nullptr); /// Return the name profile runtime entry point to do value profiling /// for a given site. @@ -101,10 +91,7 @@ inline StringRef getInstrProfValueRangeProfFuncName() { /// Return the name of the section containing function coverage mapping /// data. -inline StringRef getInstrProfCoverageSectionName(bool AddSegment) { - return AddSegment ? "__LLVM_COV," INSTR_PROF_COVMAP_SECT_NAME_STR - : INSTR_PROF_COVMAP_SECT_NAME_STR; -} +std::string getInstrProfCoverageSectionName(const Module *M = nullptr); /// Return the name prefix of variables containing instrumented function names. inline StringRef getInstrProfNameVarPrefix() { return "__profn_"; } diff --git a/llvm/include/llvm/ProfileData/InstrProfData.inc b/llvm/include/llvm/ProfileData/InstrProfData.inc index 6ef1625d81c4..949a50c0b3f9 100644 --- a/llvm/include/llvm/ProfileData/InstrProfData.inc +++ b/llvm/include/llvm/ProfileData/InstrProfData.inc @@ -246,6 +246,31 @@ COVMAP_HEADER(uint32_t, Int32Ty, Version, \ /* COVMAP_HEADER end. */ +#ifdef INSTR_PROF_SECT_ENTRY +#define INSTR_PROF_DATA_DEFINED +INSTR_PROF_SECT_ENTRY(IPSK_data, INSTR_PROF_DATA_SECT_NAME_STR, \ + INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON), \ + INSTR_PROF_QUOTE(INSTR_PROF_DATA_COFF), "__DATA,") +INSTR_PROF_SECT_ENTRY(IPSK_cnts, INSTR_PROF_CNTS_SECT_NAME_STR, \ + INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COMMON), \ + INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COFF), "__DATA,") +INSTR_PROF_SECT_ENTRY(IPSK_name, INSTR_PROF_NAME_SECT_NAME_STR, \ + INSTR_PROF_QUOTE(INSTR_PROF_NAME_COMMON), \ + INSTR_PROF_QUOTE(INSTR_PROF_NAME_COFF), "__DATA,") +INSTR_PROF_SECT_ENTRY(IPSK_vals, INSTR_PROF_VALS_SECT_NAME_STR, \ + INSTR_PROF_QUOTE(INSTR_PROF_VALS_COMMON), \ + INSTR_PROF_QUOTE(INSTR_PROF_VALS_COFF), "__DATA,") +INSTR_PROF_SECT_ENTRY(IPSK_vnodes, INSTR_PROF_VNODES_SECT_NAME_STR, \ + INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COMMON), \ + INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COFF), "__DATA,") +INSTR_PROF_SECT_ENTRY(IPSK_covmap, INSTR_PROF_COVMAP_SECT_NAME_STR, \ + INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COMMON), \ + INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COFF), "__LLVM_COV,") + +#undef INSTR_PROF_SECT_ENTRY +#endif + + #ifdef INSTR_PROF_VALUE_PROF_DATA #define INSTR_PROF_DATA_DEFINED @@ -622,17 +647,47 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, * specified via command line. */ #define INSTR_PROF_PROFILE_NAME_VAR __llvm_profile_filename +/* section name strings common to all targets other + than WIN32 */ +#define INSTR_PROF_DATA_COMMON __llvm_prf_data +#define INSTR_PROF_NAME_COMMON __llvm_prf_names +#define INSTR_PROF_CNTS_COMMON __llvm_prf_cnts +#define INSTR_PROF_VALS_COMMON __llvm_prf_vals +#define INSTR_PROF_VNODES_COMMON __llvm_prf_vnds +#define INSTR_PROF_COVMAP_COMMON __llvm_covmap +/* Win32 */ +#define INSTR_PROF_DATA_COFF .lprfd +#define INSTR_PROF_NAME_COFF .lprfn +#define INSTR_PROF_CNTS_COFF .lprfc +#define INSTR_PROF_VALS_COFF .lprfv +#define INSTR_PROF_VNODES_COFF .lprfnd +#define INSTR_PROF_COVMAP_COFF .lcovmap + +#ifdef _WIN32 /* Runtime section names and name strings. */ -#define INSTR_PROF_DATA_SECT_NAME __llvm_prf_data -#define INSTR_PROF_NAME_SECT_NAME __llvm_prf_names -#define INSTR_PROF_CNTS_SECT_NAME __llvm_prf_cnts +#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_DATA_COFF +#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_NAME_COFF +#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_CNTS_COFF /* Array of pointers. Each pointer points to a list * of value nodes associated with one value site. */ -#define INSTR_PROF_VALS_SECT_NAME __llvm_prf_vals +#define INSTR_PROF_VALS_SECT_NAME INSTR_PROF_VALS_COFF /* Value profile nodes section. */ -#define INSTR_PROF_VNODES_SECT_NAME __llvm_prf_vnds -#define INSTR_PROF_COVMAP_SECT_NAME __llvm_covmap +#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_VNODES_COFF +#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_COVMAP_COFF +#else +/* Runtime section names and name strings. */ +#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_DATA_COMMON +#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_NAME_COMMON +#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_CNTS_COMMON +/* Array of pointers. Each pointer points to a list + * of value nodes associated with one value site. + */ +#define INSTR_PROF_VALS_SECT_NAME INSTR_PROF_VALS_COMMON +/* Value profile nodes section. */ +#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_VNODES_COMMON +#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_COVMAP_COMMON +#endif #define INSTR_PROF_DATA_SECT_NAME_STR \ INSTR_PROF_QUOTE(INSTR_PROF_DATA_SECT_NAME) diff --git a/llvm/include/llvm/Transforms/InstrProfiling.h b/llvm/include/llvm/Transforms/InstrProfiling.h index e303dcf7acfe..6f2286f32ecf 100644 --- a/llvm/include/llvm/Transforms/InstrProfiling.h +++ b/llvm/include/llvm/Transforms/InstrProfiling.h @@ -67,16 +67,16 @@ private: bool isMachO() const; /// Get the section name for the counter variables. - StringRef getCountersSection() const; + std::string getCountersSection() const; /// Get the section name for the name variables. - StringRef getNameSection() const; + std::string getNameSection() const; /// Get the section name for the profile data variables. - StringRef getDataSection() const; + std::string getDataSection() const; /// Get the section name for the coverage mapping data. - StringRef getCoverageSection() const; + std::string getCoverageSection() const; /// Count the number of instrumented value sites for the function. void computeNumValueSiteCounts(InstrProfValueProfileInst *Ins); diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 78afeda67dbf..2de5d1b780ed 100644 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -133,7 +133,9 @@ getELFKindForNamedSection(StringRef Name, SectionKind K) { // // .section .eh_frame,"a",@progbits - if (Name == getInstrProfCoverageSectionName(false)) + // TODO: to support Win->ELF cross compilation with coverage properly, + // need to pass the module pointer to the following call. + if (Name == getInstrProfCoverageSectionName()) return SectionKind::getMetadata(); if (Name.empty() || Name[0] != '.') return K; diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp index 05c5b28d7a07..515f19a3b406 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp @@ -648,11 +648,15 @@ static Error loadBinaryFormat(MemoryBufferRef ObjectBuffer, : support::endianness::big; // Look for the sections that we are interested in. - auto NamesSection = lookupSection(*OF, getInstrProfNameSectionName(false)); + // TODO: with the current getInstrProfXXXSectionName interfaces, the + // the coverage reader host tool is limited to read coverage section on + // binaries with compatible profile section naming scheme as the host + // platform. Currently, COFF format binaries have different section + // naming scheme from the all the rest. + auto NamesSection = lookupSection(*OF, getInstrProfNameSectionName()); if (auto E = NamesSection.takeError()) return E; - auto CoverageSection = - lookupSection(*OF, getInstrProfCoverageSectionName(false)); + auto CoverageSection = lookupSection(*OF, getInstrProfCoverageSectionName()); if (auto E = CoverageSection.takeError()) return E; diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp index 0ec3fce4b237..d66d25eb190c 100644 --- a/llvm/lib/ProfileData/InstrProf.cpp +++ b/llvm/lib/ProfileData/InstrProf.cpp @@ -136,8 +136,92 @@ const std::error_category &llvm::instrprof_category() { return *ErrorCategory; } +namespace { + +enum InstrProfSectKind { +#define INSTR_PROF_SECT_ENTRY(Kind, SectName, SectNameCommon, SectNameCoff, \ + Prefix) \ + Kind, +#include "llvm/ProfileData/InstrProfData.inc" +}; + +const char *InstrProfSectName[] = { +#define INSTR_PROF_SECT_ENTRY(Kind, SectName, SectNameCommon, SectNameCoff, \ + Prefix) \ + SectName, +#include "llvm/ProfileData/InstrProfData.inc" +}; + +const char *InstrProfSectNameCommon[] = { +#define INSTR_PROF_SECT_ENTRY(Kind, SectName, SectNameCommon, SectNameCoff, \ + Prefix) \ + SectNameCommon, +#include "llvm/ProfileData/InstrProfData.inc" +}; + +const char *InstrProfSectNameCoff[] = { +#define INSTR_PROF_SECT_ENTRY(Kind, SectName, SectNameCommon, SectNameCoff, \ + Prefix) \ + SectNameCoff, +#include "llvm/ProfileData/InstrProfData.inc" +}; + +const char *InstrProfSectNamePrefix[] = { +#define INSTR_PROF_SECT_ENTRY(Kind, SectName, SectNameCommon, SectNameCoff, \ + Prefix) \ + Prefix, +#include "llvm/ProfileData/InstrProfData.inc" +}; + +std::string getInstrProfSectionName(const Module *M, InstrProfSectKind Kind) { + + if (!M) + return InstrProfSectName[Kind]; + + bool AddSegment = Triple(M->getTargetTriple()).isOSBinFormatMachO(); + std::string SectName; + if (Triple(M->getTargetTriple()).isOSBinFormatCOFF()) + SectName = InstrProfSectNameCoff[Kind]; + else + SectName = InstrProfSectNameCommon[Kind]; + + if (AddSegment) { + SectName = InstrProfSectNamePrefix[Kind] + SectName; + if (Kind == IPSK_data) { + SectName += ",regular,live_support"; + } + } + return SectName; +} + +} // namespace + namespace llvm { +std::string getInstrProfCountersSectionName(const Module *M) { + return getInstrProfSectionName(M, IPSK_cnts); +} + +std::string getInstrProfNameSectionName(const Module *M) { + return getInstrProfSectionName(M, IPSK_name); +} + +std::string getInstrProfDataSectionName(const Module *M) { + return getInstrProfSectionName(M, IPSK_data); +} + +std::string getInstrProfValuesSectionName(const Module *M) { + return getInstrProfSectionName(M, IPSK_vals); +} + +std::string getInstrProfVNodesSectionName(const Module *M) { + return getInstrProfSectionName(M, IPSK_vnodes); +} + +std::string getInstrProfCoverageSectionName(const Module *M) { + return getInstrProfSectionName(M, IPSK_covmap); +} + void SoftInstrProfErrors::addError(instrprof_error IE) { if (IE == instrprof_error::success) return; diff --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp index 1f8bcb9a330e..c47467f1a84c 100644 --- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -145,23 +145,23 @@ bool InstrProfiling::isMachO() const { } /// Get the section name for the counter variables. -StringRef InstrProfiling::getCountersSection() const { - return getInstrProfCountersSectionName(isMachO()); +std::string InstrProfiling::getCountersSection() const { + return getInstrProfCountersSectionName(M); } /// Get the section name for the name variables. -StringRef InstrProfiling::getNameSection() const { - return getInstrProfNameSectionName(isMachO()); +std::string InstrProfiling::getNameSection() const { + return getInstrProfNameSectionName(M); } /// Get the section name for the profile data variables. -StringRef InstrProfiling::getDataSection() const { - return getInstrProfDataSectionName(isMachO()); +std::string InstrProfiling::getDataSection() const { + return getInstrProfDataSectionName(M); } /// Get the section name for the coverage mapping data. -StringRef InstrProfiling::getCoverageSection() const { - return getInstrProfCoverageSectionName(isMachO()); +std::string InstrProfiling::getCoverageSection() const { + return getInstrProfCoverageSectionName(M); } static InstrProfIncrementInst *castToIncrementInst(Instruction *Instr) { @@ -462,7 +462,7 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) { Constant::getNullValue(ValuesTy), getVarName(Inc, getInstrProfValuesVarPrefix())); ValuesVar->setVisibility(NamePtr->getVisibility()); - ValuesVar->setSection(getInstrProfValuesSectionName(isMachO())); + ValuesVar->setSection(getInstrProfValuesSectionName(M)); ValuesVar->setAlignment(8); ValuesVar->setComdat(ProfileVarsComdat); ValuesPtrExpr = @@ -557,7 +557,7 @@ void InstrProfiling::emitVNodes() { auto *VNodesVar = new GlobalVariable( *M, VNodesTy, false, GlobalValue::PrivateLinkage, Constant::getNullValue(VNodesTy), getInstrProfVNodesVarName()); - VNodesVar->setSection(getInstrProfVNodesSectionName(isMachO())); + VNodesVar->setSection(getInstrProfVNodesSectionName(M)); UsedVars.push_back(VNodesVar); } diff --git a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp index 2ec6d09594de..c6a6f954d13d 100644 --- a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp @@ -280,8 +280,7 @@ static bool shouldInstrumentReadWriteFromAddress(Value *Addr) { if (GV->hasSection()) { StringRef SectionName = GV->getSection(); // Check if the global is in the PGO counters section. - if (SectionName.endswith(getInstrProfCountersSectionName( - /*AddSegment=*/false))) + if (SectionName.endswith(getInstrProfCountersSectionName())) return false; } diff --git a/llvm/test/Instrumentation/InstrProfiling/PR23499.ll b/llvm/test/Instrumentation/InstrProfiling/PR23499.ll index 8c4ef3712d06..101fad19950e 100644 --- a/llvm/test/Instrumentation/InstrProfiling/PR23499.ll +++ b/llvm/test/Instrumentation/InstrProfiling/PR23499.ll @@ -20,8 +20,8 @@ $_Z3barIvEvv = comdat any ; COFF-NOT: __profn__Z3barIvEvv -; COFF: @__profc__Z3barIvEvv = linkonce_odr hidden global [1 x i64] zeroinitializer, section "{{.*}}__llvm_prf_cnts", comdat, align 8 -; COFF: @__profd__Z3barIvEvv = linkonce_odr hidden global { i64, i64, i64*, i8*, i8*, i32, [2 x i16] } { i64 4947693190065689389, i64 0, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc__Z3barIvEvv, i32 0, i32 0), i8*{{.*}}, i8* null, i32 1, [2 x i16] zeroinitializer }, section "{{.*}}__llvm_prf_data{{.*}}", comdat($__profc__Z3barIvEvv), align 8 +; COFF: @__profc__Z3barIvEvv = linkonce_odr hidden global [1 x i64] zeroinitializer, section "{{.*}}prfc", comdat, align 8 +; COFF: @__profd__Z3barIvEvv = linkonce_odr hidden global { i64, i64, i64*, i8*, i8*, i32, [2 x i16] } { i64 4947693190065689389, i64 0, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc__Z3barIvEvv, i32 0, i32 0), i8*{{.*}}, i8* null, i32 1, [2 x i16] zeroinitializer }, section "{{.*}}prfd{{.*}}", comdat($__profc__Z3barIvEvv), align 8 declare void @llvm.instrprof.increment(i8*, i64, i32, i32) #1 diff --git a/llvm/tools/llvm-cov/TestingSupport.cpp b/llvm/tools/llvm-cov/TestingSupport.cpp index 72768f4fd583..a272aa5422e0 100644 --- a/llvm/tools/llvm-cov/TestingSupport.cpp +++ b/llvm/tools/llvm-cov/TestingSupport.cpp @@ -52,9 +52,14 @@ int convertForTestingMain(int argc, const char *argv[]) { StringRef Name; if (Section.getName(Name)) return 1; - if (Name == llvm::getInstrProfNameSectionName(false)) { + // TODO: with the current getInstrProfXXXSectionName interfaces, the + // the host tool is limited to read coverage section on + // binaries with compatible profile section naming scheme as the host + // platform. Currently, COFF format binaries have different section + // naming scheme from the all the rest. + if (Name == llvm::getInstrProfNameSectionName()) { ProfileNames = Section; - } else if (Name == llvm::getInstrProfCoverageSectionName(false)) { + } else if (Name == llvm::getInstrProfCoverageSectionName()) { CoverageMapping = Section; } else continue;