diff options
| author | Michael Kruse <llvm-project@meinersbur.de> | 2025-01-03 10:22:51 +0100 |
|---|---|---|
| committer | Michael Kruse <llvm-project@meinersbur.de> | 2025-01-03 10:22:51 +0100 |
| commit | 38500d63e14ce340236840f60d356cdefb56a52c (patch) | |
| tree | 17edbec446ce9b50d2f215a483b83afb293a635d /llvm/tools | |
| parent | 1a3d5daaef7a6a63448a497da3eff7fc9e23df26 (diff) | |
| parent | 27f30029741ecf023baece7b3dde1ff9011ffefc (diff) | |
Merge branch 'main' into users/meinersbur/flang_runtime_split-headersusers/meinersbur/flang_runtime_split-headers
Diffstat (limited to 'llvm/tools')
61 files changed, 1092 insertions, 534 deletions
diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp index 2ace7180b008..913077eb0b06 100644 --- a/llvm/tools/dsymutil/dsymutil.cpp +++ b/llvm/tools/dsymutil/dsymutil.cpp @@ -64,12 +64,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Options.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Options.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -80,7 +81,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class DsymutilOptTable : public opt::GenericOptTable { public: - DsymutilOptTable() : opt::GenericOptTable(InfoTable) {} + DsymutilOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; } // namespace @@ -832,15 +834,15 @@ int dsymutil_main(int argc, char **argv, const llvm::ToolContext &) { return EXIT_FAILURE; if (NeedsTempFiles) { - const bool Fat64 = Options.LinkOpts.Fat64; + bool Fat64 = Options.LinkOpts.Fat64; if (!Fat64) { // Universal Mach-O files can't have an archicture slice that starts // beyond the 4GB boundary. "lipo" can create a 64 bit universal - // header, but not all tools can parse these files so we want to return - // an error if the file can't be encoded as a file with a 32 bit + // header, but older tools may not support these files so we want to + // emit a warning if the file can't be encoded as a file with a 32 bit // universal header. To detect this, we check the size of each // architecture's skinny Mach-O file and add up the offsets. If they - // exceed 4GB, then we return an error. + // exceed 4GB, we emit a warning. // First we compute the right offset where the first architecture will // fit followin the 32 bit universal header. The 32 bit universal header @@ -859,13 +861,15 @@ int dsymutil_main(int argc, char **argv, const llvm::ToolContext &) { if (!stat) break; if (FileOffset > UINT32_MAX) { - WithColor::error() - << formatv("the universal binary has a slice with a starting " - "offset ({0:x}) that exceeds 4GB and will produce " - "an invalid Mach-O file. Use the -fat64 flag to " - "generate a universal binary with a 64-bit header " - "but note that not all tools support this format.", - FileOffset); + Fat64 = true; + WithColor::warning() << formatv( + "the universal binary has a slice with a starting offset " + "({0:x}) that exceeds 4GB. To avoid producing an invalid " + "Mach-O file, a universal binary with a 64-bit header will be " + "generated, which may not be supported by older tools. Use the " + "-fat64 flag to force a 64-bit header and silence this " + "warning.", + FileOffset); return EXIT_FAILURE; } FileOffset += stat->getSize(); diff --git a/llvm/tools/llc/llc.cpp b/llvm/tools/llc/llc.cpp index 150dd50ef293..3694ff79b543 100644 --- a/llvm/tools/llc/llc.cpp +++ b/llvm/tools/llc/llc.cpp @@ -549,7 +549,7 @@ static int compileModule(char **argv, LLVMContext &Context) { TheTarget = TargetRegistry::lookupTarget(codegen::getMArch(), TheTriple, Error); if (!TheTarget) { - WithColor::error(errs(), argv[0]) << Error; + WithColor::error(errs(), argv[0]) << Error << "\n"; exit(1); } @@ -592,7 +592,7 @@ static int compileModule(char **argv, LLVMContext &Context) { TheTarget = TargetRegistry::lookupTarget(codegen::getMArch(), TheTriple, Error); if (!TheTarget) { - WithColor::error(errs(), argv[0]) << Error; + WithColor::error(errs(), argv[0]) << Error << "\n"; return 1; } diff --git a/llvm/tools/llvm-cgdata/llvm-cgdata.cpp b/llvm/tools/llvm-cgdata/llvm-cgdata.cpp index d33459b194c9..9e3800f5bfbb 100644 --- a/llvm/tools/llvm-cgdata/llvm-cgdata.cpp +++ b/llvm/tools/llvm-cgdata/llvm-cgdata.cpp @@ -51,12 +51,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -67,7 +68,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class CGDataOptTable : public opt::GenericOptTable { public: - CGDataOptTable() : GenericOptTable(InfoTable) {} + CGDataOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; } // end anonymous namespace diff --git a/llvm/tools/llvm-config/CMakeLists.txt b/llvm/tools/llvm-config/CMakeLists.txt index e02bda1ead50..02c2532dba77 100644 --- a/llvm/tools/llvm-config/CMakeLists.txt +++ b/llvm/tools/llvm-config/CMakeLists.txt @@ -89,7 +89,9 @@ if(LLVM_ENABLE_MODULES) endif() # Add the dependency on the generation step. -add_file_dependencies(${CMAKE_CURRENT_SOURCE_DIR}/llvm-config.cpp ${BUILDVARIABLES_OBJPATH}) +set_property(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/llvm-config.cpp + APPEND PROPERTY OBJECT_DEPENDS ${BUILDVARIABLES_OBJPATH} +) if(CMAKE_CROSSCOMPILING) if (LLVM_NATIVE_TOOL_DIR AND NOT LLVM_CONFIG_PATH) diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp index d06fd86fe52a..921f283deedc 100644 --- a/llvm/tools/llvm-cov/CodeCoverage.cpp +++ b/llvm/tools/llvm-cov/CodeCoverage.cpp @@ -1013,12 +1013,22 @@ int CodeCoverageTool::doShow(int argc, const char **argv, cl::desc("Show directory coverage"), cl::cat(ViewCategory)); + cl::opt<bool> ShowCreatedTime("show-created-time", cl::Optional, + cl::desc("Show created time for each page."), + cl::init(true), cl::cat(ViewCategory)); + cl::opt<std::string> ShowOutputDirectory( "output-dir", cl::init(""), cl::desc("Directory in which coverage information is written out")); cl::alias ShowOutputDirectoryA("o", cl::desc("Alias for --output-dir"), cl::aliasopt(ShowOutputDirectory)); + cl::opt<bool> BinaryCounters( + "binary-counters", cl::Optional, + cl::desc("Show binary counters (1/0) in lines and branches instead of " + "integer execution counts"), + cl::cat(ViewCategory)); + cl::opt<uint32_t> TabSize( "tab-size", cl::init(2), cl::desc( @@ -1096,6 +1106,7 @@ int CodeCoverageTool::doShow(int argc, const char **argv, ViewOpts.ShowFunctionInstantiations = ShowInstantiations; ViewOpts.ShowDirectoryCoverage = ShowDirectoryCoverage; ViewOpts.ShowOutputDirectory = ShowOutputDirectory; + ViewOpts.BinaryCounters = BinaryCounters; ViewOpts.TabSize = TabSize; ViewOpts.ProjectTitle = ProjectTitle; @@ -1112,12 +1123,15 @@ int CodeCoverageTool::doShow(int argc, const char **argv, return 1; } - auto ModifiedTime = Status.getLastModificationTime(); - std::string ModifiedTimeStr = to_string(ModifiedTime); - size_t found = ModifiedTimeStr.rfind(':'); - ViewOpts.CreatedTimeStr = (found != std::string::npos) - ? "Created: " + ModifiedTimeStr.substr(0, found) - : "Created: " + ModifiedTimeStr; + if (ShowCreatedTime) { + auto ModifiedTime = Status.getLastModificationTime(); + std::string ModifiedTimeStr = to_string(ModifiedTime); + size_t found = ModifiedTimeStr.rfind(':'); + ViewOpts.CreatedTimeStr = + (found != std::string::npos) + ? "Created: " + ModifiedTimeStr.substr(0, found) + : "Created: " + ModifiedTimeStr; + } auto Coverage = load(); if (!Coverage) diff --git a/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp b/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp index 58e7918d3927..5c002a694f66 100644 --- a/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp +++ b/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp @@ -16,8 +16,9 @@ using namespace llvm; using namespace coverage; -static void sumBranches(size_t &NumBranches, size_t &CoveredBranches, - const ArrayRef<CountedRegion> &Branches) { +static auto sumBranches(const ArrayRef<CountedRegion> &Branches) { + size_t NumBranches = 0; + size_t CoveredBranches = 0; for (const auto &BR : Branches) { if (!BR.TrueFolded) { // "True" Condition Branches. @@ -32,20 +33,22 @@ static void sumBranches(size_t &NumBranches, size_t &CoveredBranches, ++CoveredBranches; } } + return BranchCoverageInfo(CoveredBranches, NumBranches); } -static void sumBranchExpansions(size_t &NumBranches, size_t &CoveredBranches, - const CoverageMapping &CM, - ArrayRef<ExpansionRecord> Expansions) { +static BranchCoverageInfo +sumBranchExpansions(const CoverageMapping &CM, + ArrayRef<ExpansionRecord> Expansions) { + BranchCoverageInfo BranchCoverage; for (const auto &Expansion : Expansions) { auto CE = CM.getCoverageForExpansion(Expansion); - sumBranches(NumBranches, CoveredBranches, CE.getBranches()); - sumBranchExpansions(NumBranches, CoveredBranches, CM, CE.getExpansions()); + BranchCoverage += sumBranches(CE.getBranches()); + BranchCoverage += sumBranchExpansions(CM, CE.getExpansions()); } + return BranchCoverage; } -static std::pair<size_t, size_t> -sumMCDCPairs(const ArrayRef<MCDCRecord> &Records) { +auto sumMCDCPairs(const ArrayRef<MCDCRecord> &Records) { size_t NumPairs = 0, CoveredPairs = 0; for (const auto &Record : Records) { const auto NumConditions = Record.getNumConditions(); @@ -56,15 +59,14 @@ sumMCDCPairs(const ArrayRef<MCDCRecord> &Records) { ++CoveredPairs; } } - return {NumPairs, CoveredPairs}; + return MCDCCoverageInfo(CoveredPairs, NumPairs); } -FunctionCoverageSummary -FunctionCoverageSummary::get(const CoverageMapping &CM, - const coverage::FunctionRecord &Function) { +static std::pair<RegionCoverageInfo, LineCoverageInfo> +sumRegions(ArrayRef<CountedRegion> CodeRegions, const CoverageData &CD) { // Compute the region coverage. size_t NumCodeRegions = 0, CoveredRegions = 0; - for (auto &CR : Function.CountedRegions) { + for (auto &CR : CodeRegions) { if (CR.Kind != CounterMappingRegion::CodeRegion) continue; ++NumCodeRegions; @@ -74,7 +76,6 @@ FunctionCoverageSummary::get(const CoverageMapping &CM, // Compute the line coverage size_t NumLines = 0, CoveredLines = 0; - CoverageData CD = CM.getCoverageForFunction(Function); for (const auto &LCS : getLineCoverageStats(CD)) { if (!LCS.isMapped()) continue; @@ -83,20 +84,31 @@ FunctionCoverageSummary::get(const CoverageMapping &CM, ++CoveredLines; } + return {RegionCoverageInfo(CoveredRegions, NumCodeRegions), + LineCoverageInfo(CoveredLines, NumLines)}; +} + +CoverageDataSummary::CoverageDataSummary(const CoverageData &CD, + ArrayRef<CountedRegion> CodeRegions) { + std::tie(RegionCoverage, LineCoverage) = sumRegions(CodeRegions, CD); + BranchCoverage = sumBranches(CD.getBranches()); + MCDCCoverage = sumMCDCPairs(CD.getMCDCRecords()); +} + +FunctionCoverageSummary +FunctionCoverageSummary::get(const CoverageMapping &CM, + const coverage::FunctionRecord &Function) { + CoverageData CD = CM.getCoverageForFunction(Function); + + auto Summary = + FunctionCoverageSummary(Function.Name, Function.ExecutionCount); + + Summary += CoverageDataSummary(CD, Function.CountedRegions); + // Compute the branch coverage, including branches from expansions. - size_t NumBranches = 0, CoveredBranches = 0; - sumBranches(NumBranches, CoveredBranches, CD.getBranches()); - sumBranchExpansions(NumBranches, CoveredBranches, CM, CD.getExpansions()); + Summary.BranchCoverage += sumBranchExpansions(CM, CD.getExpansions()); - size_t NumPairs = 0, CoveredPairs = 0; - std::tie(NumPairs, CoveredPairs) = sumMCDCPairs(CD.getMCDCRecords()); - - return FunctionCoverageSummary( - Function.Name, Function.ExecutionCount, - RegionCoverageInfo(CoveredRegions, NumCodeRegions), - LineCoverageInfo(CoveredLines, NumLines), - BranchCoverageInfo(CoveredBranches, NumBranches), - MCDCCoverageInfo(CoveredPairs, NumPairs)); + return Summary; } FunctionCoverageSummary @@ -111,8 +123,7 @@ FunctionCoverageSummary::get(const InstantiationGroup &Group, << Group.getColumn(); } - FunctionCoverageSummary Summary(Name); - Summary.ExecutionCount = Group.getTotalExecutionCount(); + FunctionCoverageSummary Summary(Name, Group.getTotalExecutionCount()); Summary.RegionCoverage = Summaries[0].RegionCoverage; Summary.LineCoverage = Summaries[0].LineCoverage; Summary.BranchCoverage = Summaries[0].BranchCoverage; diff --git a/llvm/tools/llvm-cov/CoverageSummaryInfo.h b/llvm/tools/llvm-cov/CoverageSummaryInfo.h index 64c2c8406cf3..d9210676c41b 100644 --- a/llvm/tools/llvm-cov/CoverageSummaryInfo.h +++ b/llvm/tools/llvm-cov/CoverageSummaryInfo.h @@ -223,26 +223,32 @@ public: } }; -/// A summary of function's code coverage. -struct FunctionCoverageSummary { - std::string Name; - uint64_t ExecutionCount; +struct CoverageDataSummary { RegionCoverageInfo RegionCoverage; LineCoverageInfo LineCoverage; BranchCoverageInfo BranchCoverage; MCDCCoverageInfo MCDCCoverage; - FunctionCoverageSummary(const std::string &Name) - : Name(Name), ExecutionCount(0) {} + CoverageDataSummary() = default; + CoverageDataSummary(const coverage::CoverageData &CD, + ArrayRef<coverage::CountedRegion> CodeRegions); - FunctionCoverageSummary(const std::string &Name, uint64_t ExecutionCount, - const RegionCoverageInfo &RegionCoverage, - const LineCoverageInfo &LineCoverage, - const BranchCoverageInfo &BranchCoverage, - const MCDCCoverageInfo &MCDCCoverage) - : Name(Name), ExecutionCount(ExecutionCount), - RegionCoverage(RegionCoverage), LineCoverage(LineCoverage), - BranchCoverage(BranchCoverage), MCDCCoverage(MCDCCoverage) {} + auto &operator+=(const CoverageDataSummary &RHS) { + RegionCoverage += RHS.RegionCoverage; + LineCoverage += RHS.LineCoverage; + BranchCoverage += RHS.BranchCoverage; + MCDCCoverage += RHS.MCDCCoverage; + return *this; + } +}; + +/// A summary of function's code coverage. +struct FunctionCoverageSummary : CoverageDataSummary { + std::string Name; + uint64_t ExecutionCount; + + FunctionCoverageSummary(const std::string &Name, uint64_t ExecutionCount = 0) + : Name(Name), ExecutionCount(ExecutionCount) {} /// Compute the code coverage summary for the given function coverage /// mapping record. @@ -257,12 +263,8 @@ struct FunctionCoverageSummary { }; /// A summary of file's code coverage. -struct FileCoverageSummary { +struct FileCoverageSummary : CoverageDataSummary { StringRef Name; - RegionCoverageInfo RegionCoverage; - LineCoverageInfo LineCoverage; - BranchCoverageInfo BranchCoverage; - MCDCCoverageInfo MCDCCoverage; FunctionCoverageInfo FunctionCoverage; FunctionCoverageInfo InstantiationCoverage; @@ -270,11 +272,8 @@ struct FileCoverageSummary { FileCoverageSummary(StringRef Name) : Name(Name) {} FileCoverageSummary &operator+=(const FileCoverageSummary &RHS) { - RegionCoverage += RHS.RegionCoverage; - LineCoverage += RHS.LineCoverage; + *static_cast<CoverageDataSummary *>(this) += RHS; FunctionCoverage += RHS.FunctionCoverage; - BranchCoverage += RHS.BranchCoverage; - MCDCCoverage += RHS.MCDCCoverage; InstantiationCoverage += RHS.InstantiationCoverage; return *this; } diff --git a/llvm/tools/llvm-cov/CoverageViewOptions.h b/llvm/tools/llvm-cov/CoverageViewOptions.h index 6925cffd8246..81e69c3814e3 100644 --- a/llvm/tools/llvm-cov/CoverageViewOptions.h +++ b/llvm/tools/llvm-cov/CoverageViewOptions.h @@ -9,8 +9,8 @@ #ifndef LLVM_COV_COVERAGEVIEWOPTIONS_H #define LLVM_COV_COVERAGEVIEWOPTIONS_H -#include "llvm/Config/llvm-config.h" #include "RenderingSupport.h" +#include "llvm/Config/llvm-config.h" #include <vector> namespace llvm { @@ -45,6 +45,7 @@ struct CoverageViewOptions { bool SkipExpansions; bool SkipFunctions; bool SkipBranches; + bool BinaryCounters; OutputFormat Format; BranchOutputType ShowBranches; std::string ShowOutputDirectory; diff --git a/llvm/tools/llvm-cov/SourceCoverageView.h b/llvm/tools/llvm-cov/SourceCoverageView.h index 2b1570d399dd..cff32b756ee3 100644 --- a/llvm/tools/llvm-cov/SourceCoverageView.h +++ b/llvm/tools/llvm-cov/SourceCoverageView.h @@ -180,6 +180,8 @@ class SourceCoverageView { /// on display. std::vector<InstantiationView> InstantiationSubViews; + bool BinaryCounters; + /// Get the first uncovered line number for the source file. unsigned getFirstUncoveredLineNo(); @@ -266,6 +268,14 @@ protected: /// digits. static std::string formatCount(uint64_t N); + uint64_t BinaryCount(uint64_t N) const { + return (N && BinaryCounters ? 1 : N); + } + + std::string formatBinaryCount(uint64_t N) const { + return formatCount(BinaryCount(N)); + } + /// Check if region marker output is expected for a line. bool shouldRenderRegionMarkers(const LineCoverageStats &LCS) const; @@ -276,7 +286,9 @@ protected: const CoverageViewOptions &Options, CoverageData &&CoverageInfo) : SourceName(SourceName), File(File), Options(Options), - CoverageInfo(std::move(CoverageInfo)) {} + CoverageInfo(std::move(CoverageInfo)), + BinaryCounters(Options.BinaryCounters || + CoverageInfo.getSingleByteCoverage()) {} public: static std::unique_ptr<SourceCoverageView> diff --git a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp index 0175deb1c848..c94d3853fc01 100644 --- a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp +++ b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp @@ -90,40 +90,38 @@ const char *BeginHeader = const char *JSForCoverage = R"javascript( - function next_uncovered(selector, reverse, scroll_selector) { function visit_element(element) { element.classList.add("seen"); element.classList.add("selected"); - - if (!scroll_selector) { - scroll_selector = "tr:has(.selected) td.line-number" - } - - const scroll_to = document.querySelector(scroll_selector); - if (scroll_to) { - scroll_to.scrollIntoView({behavior: "smooth", block: "center", inline: "end"}); - } - + + if (!scroll_selector) { + scroll_selector = "tr:has(.selected) td.line-number" + } + + const scroll_to = document.querySelector(scroll_selector); + if (scroll_to) { + scroll_to.scrollIntoView({behavior: "smooth", block: "center", inline: "end"}); + } } - + function select_one() { if (!reverse) { const previously_selected = document.querySelector(".selected"); - + if (previously_selected) { previously_selected.classList.remove("selected"); } - + return document.querySelector(selector + ":not(.seen)"); - } else { + } else { const previously_selected = document.querySelector(".selected"); - + if (previously_selected) { previously_selected.classList.remove("selected"); previously_selected.classList.remove("seen"); } - + const nodes = document.querySelectorAll(selector + ".seen"); if (nodes) { const last = nodes[nodes.length - 1]; // last @@ -133,54 +131,52 @@ function next_uncovered(selector, reverse, scroll_selector) { } } } - + function reset_all() { if (!reverse) { const all_seen = document.querySelectorAll(selector + ".seen"); - + if (all_seen) { all_seen.forEach(e => e.classList.remove("seen")); } } else { const all_seen = document.querySelectorAll(selector + ":not(.seen)"); - + if (all_seen) { all_seen.forEach(e => e.classList.add("seen")); } } - + } - + const uncovered = select_one(); if (uncovered) { visit_element(uncovered); } else { reset_all(); - - + const uncovered = select_one(); - + if (uncovered) { visit_element(uncovered); } } } -function next_line(reverse) { +function next_line(reverse) { next_uncovered("td.uncovered-line", reverse) } -function next_region(reverse) { +function next_region(reverse) { next_uncovered("span.red.region", reverse); } -function next_branch(reverse) { +function next_branch(reverse) { next_uncovered("span.red.branch", reverse); } document.addEventListener("keypress", function(event) { - console.log(event); const reverse = event.shiftKey; if (event.code == "KeyL") { next_line(reverse); @@ -191,7 +187,6 @@ document.addEventListener("keypress", function(event) { if (event.code == "KeyR") { next_region(reverse); } - }); )javascript"; @@ -1024,19 +1019,22 @@ void SourceCoverageViewHTML::renderLine(raw_ostream &OS, LineRef L, // Just consider the segments which start *and* end on this line. for (unsigned I = 0, E = Segments.size() - 1; I < E; ++I) { const auto *CurSeg = Segments[I]; + auto CurSegCount = BinaryCount(CurSeg->Count); + auto LCSCount = BinaryCount(LCS.getExecutionCount()); if (!CurSeg->IsRegionEntry) continue; - if (CurSeg->Count == LCS.getExecutionCount()) + if (CurSegCount == LCSCount) continue; Snippets[I + 1] = - tag("div", Snippets[I + 1] + tag("span", formatCount(CurSeg->Count), - "tooltip-content"), + tag("div", + Snippets[I + 1] + + tag("span", formatCount(CurSegCount), "tooltip-content"), "tooltip"); if (getOptions().Debug) errs() << "Marker at " << CurSeg->Line << ":" << CurSeg->Col << " = " - << formatCount(CurSeg->Count) << "\n"; + << formatCount(CurSegCount) << "\n"; } } @@ -1056,7 +1054,7 @@ void SourceCoverageViewHTML::renderLineCoverageColumn( raw_ostream &OS, const LineCoverageStats &Line) { std::string Count; if (Line.isMapped()) - Count = tag("pre", formatCount(Line.getExecutionCount())); + Count = tag("pre", formatBinaryCount(Line.getExecutionCount())); std::string CoverageClass = (Line.getExecutionCount() > 0) ? "covered-line" @@ -1101,20 +1099,31 @@ void SourceCoverageViewHTML::renderBranchView(raw_ostream &OS, BranchView &BRV, if (getOptions().Debug) errs() << "Branch at line " << BRV.getLine() << '\n'; + auto BranchCount = [&](StringRef Label, uint64_t Count, bool Folded, + double Total) { + if (Folded) + return std::string{"Folded"}; + + std::string Str; + raw_string_ostream OS(Str); + + OS << tag("span", Label, (Count ? "None" : "red branch")) << ": "; + if (getOptions().ShowBranchCounts) + OS << tag("span", formatBinaryCount(Count), + (Count ? "covered-line" : "uncovered-line")); + else + OS << format("%0.2f", (Total != 0 ? 100.0 * Count / Total : 0.0)) << "%"; + + return Str; + }; + OS << BeginExpansionDiv; OS << BeginPre; for (const auto &R : BRV.Regions) { - // Calculate TruePercent and False Percent. - double TruePercent = 0.0; - double FalsePercent = 0.0; - // FIXME: It may overflow when the data is too large, but I have not - // encountered it in actual use, and not sure whether to use __uint128_t. - uint64_t Total = R.ExecutionCount + R.FalseExecutionCount; - - if (!getOptions().ShowBranchCounts && Total != 0) { - TruePercent = ((double)(R.ExecutionCount) / (double)Total) * 100.0; - FalsePercent = ((double)(R.FalseExecutionCount) / (double)Total) * 100.0; - } + // This can be `double` since it is only used as a denominator. + // FIXME: It is still inaccurate if Count is greater than (1LL << 53). + double Total = + static_cast<double>(R.ExecutionCount) + R.FalseExecutionCount; // Display Line + Column. std::string LineNoStr = utostr(uint64_t(R.LineStart)); @@ -1133,40 +1142,9 @@ void SourceCoverageViewHTML::renderBranchView(raw_ostream &OS, BranchView &BRV, continue; } - // Display TrueCount or TruePercent. - std::string TrueColor = - (R.TrueFolded || R.ExecutionCount ? "None" : "red branch"); - std::string TrueCovClass = - (R.TrueFolded || R.ExecutionCount > 0 ? "covered-line" - : "uncovered-line"); - - if (R.TrueFolded) - OS << "Folded, "; - else { - OS << tag("span", "True", TrueColor) << ": "; - if (getOptions().ShowBranchCounts) - OS << tag("span", formatCount(R.ExecutionCount), TrueCovClass) << ", "; - else - OS << format("%0.2f", TruePercent) << "%, "; - } - - // Display FalseCount or FalsePercent. - std::string FalseColor = - (R.FalseFolded || R.FalseExecutionCount ? "None" : "red branch"); - std::string FalseCovClass = - (R.FalseFolded || R.FalseExecutionCount > 0 ? "covered-line" - : "uncovered-line"); - - if (R.FalseFolded) - OS << "Folded]\n"; - else { - OS << tag("span", "False", FalseColor) << ": "; - if (getOptions().ShowBranchCounts) - OS << tag("span", formatCount(R.FalseExecutionCount), FalseCovClass) - << "]\n"; - else - OS << format("%0.2f", FalsePercent) << "%]\n"; - } + OS << BranchCount("True", R.ExecutionCount, R.TrueFolded, Total) << ", " + << BranchCount("False", R.FalseExecutionCount, R.FalseFolded, Total) + << "]\n"; } OS << EndPre; OS << EndExpansionDiv; diff --git a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp index 444f33dac108..765f8bbbd8d1 100644 --- a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp +++ b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp @@ -216,7 +216,7 @@ void SourceCoverageViewText::renderLineCoverageColumn( OS.indent(LineCoverageColumnWidth) << '|'; return; } - std::string C = formatCount(Line.getExecutionCount()); + std::string C = formatBinaryCount(Line.getExecutionCount()); OS.indent(LineCoverageColumnWidth - C.size()); colored_ostream(OS, raw_ostream::MAGENTA, Line.hasMultipleRegions() && getOptions().Colors) @@ -263,7 +263,7 @@ void SourceCoverageViewText::renderRegionMarkers(raw_ostream &OS, if (getOptions().Debug) errs() << "Marker at " << S->Line << ":" << S->Col << " = " - << formatCount(S->Count) << "\n"; + << formatBinaryCount(S->Count) << "\n"; } OS << '\n'; } @@ -294,17 +294,32 @@ void SourceCoverageViewText::renderBranchView(raw_ostream &OS, BranchView &BRV, if (getOptions().Debug) errs() << "Branch at line " << BRV.getLine() << '\n'; + auto BranchCount = [&](StringRef Label, uint64_t Count, bool Folded, + double Total) { + if (Folded) + return std::string{"Folded"}; + + std::string Str; + raw_string_ostream OS(Str); + + colored_ostream(OS, raw_ostream::RED, getOptions().Colors && !Count, + /*Bold=*/false, /*BG=*/true) + << Label; + + if (getOptions().ShowBranchCounts) + OS << ": " << formatBinaryCount(Count); + else + OS << ": " << format("%0.2f", (Total != 0 ? 100.0 * Count / Total : 0.0)) + << "%"; + + return Str; + }; + for (const auto &R : BRV.Regions) { - double TruePercent = 0.0; - double FalsePercent = 0.0; - // FIXME: It may overflow when the data is too large, but I have not - // encountered it in actual use, and not sure whether to use __uint128_t. - uint64_t Total = R.ExecutionCount + R.FalseExecutionCount; - - if (!getOptions().ShowBranchCounts && Total != 0) { - TruePercent = ((double)(R.ExecutionCount) / (double)Total) * 100.0; - FalsePercent = ((double)(R.FalseExecutionCount) / (double)Total) * 100.0; - } + // This can be `double` since it is only used as a denominator. + // FIXME: It is still inaccurate if Count is greater than (1LL << 53). + double Total = + static_cast<double>(R.ExecutionCount) + R.FalseExecutionCount; renderLinePrefix(OS, ViewDepth); OS << " Branch (" << R.LineStart << ":" << R.ColumnStart << "): ["; @@ -314,33 +329,9 @@ void SourceCoverageViewText::renderBranchView(raw_ostream &OS, BranchView &BRV, continue; } - if (R.TrueFolded) - OS << "Folded, "; - else { - colored_ostream(OS, raw_ostream::RED, - getOptions().Colors && !R.ExecutionCount, - /*Bold=*/false, /*BG=*/true) - << "True"; - - if (getOptions().ShowBranchCounts) - OS << ": " << formatCount(R.ExecutionCount) << ", "; - else - OS << ": " << format("%0.2f", TruePercent) << "%, "; - } - - if (R.FalseFolded) - OS << "Folded]\n"; - else { - colored_ostream(OS, raw_ostream::RED, - getOptions().Colors && !R.FalseExecutionCount, - /*Bold=*/false, /*BG=*/true) - << "False"; - - if (getOptions().ShowBranchCounts) - OS << ": " << formatCount(R.FalseExecutionCount) << "]\n"; - else - OS << ": " << format("%0.2f", FalsePercent) << "%]\n"; - } + OS << BranchCount("True", R.ExecutionCount, R.TrueFolded, Total) << ", " + << BranchCount("False", R.FalseExecutionCount, R.FalseFolded, Total) + << "]\n"; } } diff --git a/llvm/tools/llvm-cvtres/llvm-cvtres.cpp b/llvm/tools/llvm-cvtres/llvm-cvtres.cpp index 0c10769a9488..8ef8d6e239cf 100644 --- a/llvm/tools/llvm-cvtres/llvm-cvtres.cpp +++ b/llvm/tools/llvm-cvtres/llvm-cvtres.cpp @@ -42,12 +42,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -58,7 +59,9 @@ static constexpr opt::OptTable::Info InfoTable[] = { class CvtResOptTable : public opt::GenericOptTable { public: - CvtResOptTable() : opt::GenericOptTable(InfoTable, true) {} + CvtResOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable, + true) {} }; } diff --git a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp index 41b379e8fd39..1467093e78c0 100644 --- a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp +++ b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp @@ -31,12 +31,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr llvm::StringLiteral NAME##_init[] = VALUE; \ - static constexpr llvm::ArrayRef<llvm::StringLiteral> NAME( \ - NAME##_init, std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -47,7 +48,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class CxxfiltOptTable : public opt::GenericOptTable { public: - CxxfiltOptTable() : opt::GenericOptTable(InfoTable) { + CxxfiltOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) { setGroupedShortOptions(true); } }; diff --git a/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp b/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp index 77862737bccd..934833bf6fe4 100644 --- a/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp +++ b/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp @@ -37,12 +37,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -53,7 +54,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class DebuginfodFindOptTable : public opt::GenericOptTable { public: - DebuginfodFindOptTable() : GenericOptTable(InfoTable) {} + DebuginfodFindOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; } // end anonymous namespace diff --git a/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp b/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp index 44d656148a4e..2859a36c80b0 100644 --- a/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp +++ b/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp @@ -36,12 +36,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -52,7 +53,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class DebuginfodOptTable : public opt::GenericOptTable { public: - DebuginfodOptTable() : GenericOptTable(InfoTable) {} + DebuginfodOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; } // end anonymous namespace diff --git a/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp b/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp index 7b777b1845f8..0180abb834f9 100644 --- a/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp +++ b/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp @@ -38,12 +38,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Options.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Options.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -54,7 +55,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class DwarfutilOptTable : public opt::GenericOptTable { public: - DwarfutilOptTable() : opt::GenericOptTable(InfoTable) {} + DwarfutilOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; } // namespace diff --git a/llvm/tools/llvm-dwp/llvm-dwp.cpp b/llvm/tools/llvm-dwp/llvm-dwp.cpp index 60a89cb13c57..e34fcadfde5f 100644 --- a/llvm/tools/llvm-dwp/llvm-dwp.cpp +++ b/llvm/tools/llvm-dwp/llvm-dwp.cpp @@ -47,12 +47,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -63,7 +64,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class DwpOptTable : public opt::GenericOptTable { public: - DwpOptTable() : GenericOptTable(InfoTable) {} + DwpOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; } // end anonymous namespace diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp index 9116b5ced027..a7771b99e97b 100644 --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp @@ -422,8 +422,9 @@ private: "Expected getcpu call to succeed."); assert(static_cast<int>(CurrentCPU) == CPUToUse && "Expected current CPU to equal the CPU requested by the user"); -#endif // defined(__x86_64__) && defined(SYS_getcpu) +#else exit(ChildProcessExitCodeE::SetCPUAffinityFailed); +#endif // defined(__x86_64__) && defined(SYS_getcpu) } Error createSubProcessAndRunBenchmark( diff --git a/llvm/tools/llvm-exegesis/lib/CMakeLists.txt b/llvm/tools/llvm-exegesis/lib/CMakeLists.txt index 414b49e5e021..d95c37ff5426 100644 --- a/llvm/tools/llvm-exegesis/lib/CMakeLists.txt +++ b/llvm/tools/llvm-exegesis/lib/CMakeLists.txt @@ -12,6 +12,9 @@ endif() if (LLVM_TARGETS_TO_BUILD MATCHES "Mips") list(APPEND LLVM_EXEGESIS_TARGETS "Mips") endif() +if(LLVM_TARGETS_TO_BUILD MATCHES "RISCV") + list(APPEND LLVM_EXEGESIS_TARGETS "RISCV") +endif() set(LLVM_EXEGESIS_TARGETS ${LLVM_EXEGESIS_TARGETS} PARENT_SCOPE) diff --git a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp index 9c926d1fc611..c9225e51213e 100644 --- a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp +++ b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp @@ -95,11 +95,12 @@ Instruction::Instruction(const MCInstrDesc *Description, StringRef Name, const BitVector *ImplDefRegs, const BitVector *ImplUseRegs, const BitVector *AllDefRegs, - const BitVector *AllUseRegs) + const BitVector *AllUseRegs, + const BitVector *NonMemoryRegs) : Description(*Description), Name(Name), Operands(std::move(Operands)), Variables(std::move(Variables)), ImplDefRegs(*ImplDefRegs), ImplUseRegs(*ImplUseRegs), AllDefRegs(*AllDefRegs), - AllUseRegs(*AllUseRegs) {} + AllUseRegs(*AllUseRegs), NonMemoryRegs(*NonMemoryRegs) {} std::unique_ptr<Instruction> Instruction::create(const MCInstrInfo &InstrInfo, @@ -166,6 +167,8 @@ Instruction::create(const MCInstrInfo &InstrInfo, BitVector ImplUseRegs = RATC.emptyRegisters(); BitVector AllDefRegs = RATC.emptyRegisters(); BitVector AllUseRegs = RATC.emptyRegisters(); + BitVector NonMemoryRegs = RATC.emptyRegisters(); + for (const auto &Op : Operands) { if (Op.isReg()) { const auto &AliasingBits = Op.getRegisterAliasing().aliasedBits(); @@ -177,6 +180,8 @@ Instruction::create(const MCInstrInfo &InstrInfo, ImplDefRegs |= AliasingBits; if (Op.isUse() && Op.isImplicit()) ImplUseRegs |= AliasingBits; + if (Op.isUse() && !Op.isMemory()) + NonMemoryRegs |= AliasingBits; } } // Can't use make_unique because constructor is private. @@ -185,7 +190,8 @@ Instruction::create(const MCInstrInfo &InstrInfo, std::move(Variables), BVC.getUnique(std::move(ImplDefRegs)), BVC.getUnique(std::move(ImplUseRegs)), BVC.getUnique(std::move(AllDefRegs)), - BVC.getUnique(std::move(AllUseRegs)))); + BVC.getUnique(std::move(AllUseRegs)), + BVC.getUnique(std::move(NonMemoryRegs)))); } const Operand &Instruction::getPrimaryOperand(const Variable &Var) const { @@ -240,6 +246,12 @@ bool Instruction::hasAliasingRegisters( ForbiddenRegisters); } +bool Instruction::hasAliasingNotMemoryRegisters( + const BitVector &ForbiddenRegisters) const { + return anyCommonExcludingForbidden(AllDefRegs, NonMemoryRegs, + ForbiddenRegisters); +} + bool Instruction::hasOneUseOrOneDef() const { return AllDefRegs.count() || AllUseRegs.count(); } diff --git a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h index f8ebc07d01f3..d7712e21c32c 100644 --- a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h +++ b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h @@ -133,6 +133,12 @@ struct Instruction { // aliasing Use and Def registers. bool hasAliasingRegisters(const BitVector &ForbiddenRegisters) const; + // Whether this instruction is self aliasing through some registers. + // Repeating this instruction may execute sequentially by picking aliasing + // Def and Not Memory Use registers. It may also execute in parallel by + // picking non aliasing Def and Not Memory Use registers. + bool hasAliasingNotMemoryRegisters(const BitVector &ForbiddenRegisters) const; + // Whether this instruction's registers alias with OtherInstr's registers. bool hasAliasingRegistersThrough(const Instruction &OtherInstr, const BitVector &ForbiddenRegisters) const; @@ -160,12 +166,15 @@ struct Instruction { const BitVector &ImplUseRegs; // The set of aliased implicit use registers. const BitVector &AllDefRegs; // The set of all aliased def registers. const BitVector &AllUseRegs; // The set of all aliased use registers. + // The set of all aliased not memory use registers. + const BitVector &NonMemoryRegs; + private: Instruction(const MCInstrDesc *Description, StringRef Name, SmallVector<Operand, 8> Operands, SmallVector<Variable, 4> Variables, const BitVector *ImplDefRegs, const BitVector *ImplUseRegs, const BitVector *AllDefRegs, - const BitVector *AllUseRegs); + const BitVector *AllUseRegs, const BitVector *NonMemoryRegs); }; // Instructions are expensive to instantiate. This class provides a cache of diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt b/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt new file mode 100644 index 000000000000..489ac6d6e34b --- /dev/null +++ b/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt @@ -0,0 +1,22 @@ +include_directories( + ${LLVM_MAIN_SRC_DIR}/lib/Target/RISCV + ${LLVM_BINARY_DIR}/lib/Target/RISCV +) + +set(LLVM_LINK_COMPONENTS + CodeGen + RISCV + Exegesis + Core + Support + ) + +add_llvm_library(LLVMExegesisRISCV + DISABLE_LLVM_LINK_LLVM_DYLIB + STATIC + Target.cpp + + DEPENDS + intrinsics_gen + RISCVCommonTableGen + ) diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp new file mode 100644 index 000000000000..41d361532908 --- /dev/null +++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp @@ -0,0 +1,272 @@ +//===-- Target.cpp ----------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "../Target.h" + +#include "MCTargetDesc/RISCVBaseInfo.h" +#include "MCTargetDesc/RISCVMCTargetDesc.h" +#include "MCTargetDesc/RISCVMatInt.h" +#include "RISCVInstrInfo.h" + +// include computeAvailableFeatures and computeRequiredFeatures. +#define GET_AVAILABLE_OPCODE_CHECKER +#include "RISCVGenInstrInfo.inc" + +#include "llvm/CodeGen/MachineInstrBuilder.h" + +#include <vector> + +namespace llvm { +namespace exegesis { + +namespace { + +// Stores constant value to a general-purpose (integer) register. +static std::vector<MCInst> loadIntReg(const MCSubtargetInfo &STI, unsigned Reg, + const APInt &Value) { + SmallVector<MCInst, 8> MCInstSeq; + std::vector<MCInst> MatIntInstrs; + MCRegister DestReg = Reg; + + RISCVMatInt::generateMCInstSeq(Value.getSExtValue(), STI, DestReg, MCInstSeq); + MatIntInstrs.resize(MCInstSeq.size()); + std::copy(MCInstSeq.begin(), MCInstSeq.end(), MatIntInstrs.begin()); + + return MatIntInstrs; +} + +const unsigned ScratchIntReg = RISCV::X30; // t5 + +// Stores constant bits to a floating-point register. +static std::vector<MCInst> loadFPRegBits(const MCSubtargetInfo &STI, + unsigned Reg, const APInt &Bits, + unsigned FmvOpcode) { + std::vector<MCInst> Instrs = loadIntReg(STI, ScratchIntReg, Bits); + Instrs.push_back(MCInstBuilder(FmvOpcode).addReg(Reg).addReg(ScratchIntReg)); + return Instrs; +} + +// main idea is: +// we support APInt only if (represented as double) it has zero fractional +// part: 1.0, 2.0, 3.0, etc... then we can do the trick: write int to tmp reg t5 +// and then do FCVT this is only reliable thing in 32-bit mode, otherwise we +// need to use __floatsidf +static std::vector<MCInst> loadFP64RegBits32(const MCSubtargetInfo &STI, + unsigned Reg, const APInt &Bits) { + double D = Bits.bitsToDouble(); + double IPart; + double FPart = std::modf(D, &IPart); + + if (std::abs(FPart) > std::numeric_limits<double>::epsilon()) { + errs() << "loadFP64RegBits32 is not implemented for doubles like " << D + << ", please remove fractional part\n"; + return {}; + } + + std::vector<MCInst> Instrs = loadIntReg(STI, ScratchIntReg, Bits); + Instrs.push_back( + MCInstBuilder(RISCV::FCVT_D_W).addReg(Reg).addReg(ScratchIntReg)); + return Instrs; +} + +static MCInst nop() { + // ADDI X0, X0, 0 + return MCInstBuilder(RISCV::ADDI) + .addReg(RISCV::X0) + .addReg(RISCV::X0) + .addImm(0); +} + +static bool isVectorRegList(unsigned Reg) { + return RISCV::VRM2RegClass.contains(Reg) || + RISCV::VRM4RegClass.contains(Reg) || + RISCV::VRM8RegClass.contains(Reg) || + RISCV::VRN2M1RegClass.contains(Reg) || + RISCV::VRN2M2RegClass.contains(Reg) || + RISCV::VRN2M4RegClass.contains(Reg) || + RISCV::VRN3M1RegClass.contains(Reg) || + RISCV::VRN3M2RegClass.contains(Reg) || + RISCV::VRN4M1RegClass.contains(Reg) || + RISCV::VRN4M2RegClass.contains(Reg) || + RISCV::VRN5M1RegClass.contains(Reg) || + RISCV::VRN6M1RegClass.contains(Reg) || + RISCV::VRN7M1RegClass.contains(Reg) || + RISCV::VRN8M1RegClass.contains(Reg); +} + +class ExegesisRISCVTarget : public ExegesisTarget { +public: + ExegesisRISCVTarget(); + + bool matchesArch(Triple::ArchType Arch) const override; + + std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg, + const APInt &Value) const override; + + unsigned getDefaultLoopCounterRegister(const Triple &) const override; + + void decrementLoopCounterAndJump(MachineBasicBlock &MBB, + MachineBasicBlock &TargetMBB, + const MCInstrInfo &MII, + unsigned LoopRegister) const override; + + unsigned getScratchMemoryRegister(const Triple &TT) const override; + + void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg, + unsigned Offset) const override; + + ArrayRef<unsigned> getUnavailableRegisters() const override; + + Error randomizeTargetMCOperand(const Instruction &Instr, const Variable &Var, + MCOperand &AssignedValue, + const BitVector &ForbiddenRegs) const override; + + std::vector<InstructionTemplate> + generateInstructionVariants(const Instruction &Instr, + unsigned MaxConfigsPerOpcode) const override; +}; + +ExegesisRISCVTarget::ExegesisRISCVTarget() + : ExegesisTarget(ArrayRef<CpuAndPfmCounters>{}, + RISCV_MC::isOpcodeAvailable) {} + +bool ExegesisRISCVTarget::matchesArch(Triple::ArchType Arch) const { + return Arch == Triple::riscv32 || Arch == Triple::riscv64; +} + +std::vector<MCInst> ExegesisRISCVTarget::setRegTo(const MCSubtargetInfo &STI, + unsigned Reg, + const APInt &Value) const { + if (RISCV::GPRRegClass.contains(Reg)) + return loadIntReg(STI, Reg, Value); + if (RISCV::FPR16RegClass.contains(Reg)) + return loadFPRegBits(STI, Reg, Value, RISCV::FMV_H_X); + if (RISCV::FPR32RegClass.contains(Reg)) + return loadFPRegBits(STI, Reg, Value, RISCV::FMV_W_X); + if (RISCV::FPR64RegClass.contains(Reg)) { + if (STI.hasFeature(RISCV::Feature64Bit)) + return loadFPRegBits(STI, Reg, Value, RISCV::FMV_D_X); + return loadFP64RegBits32(STI, Reg, Value); + } + if (Reg == RISCV::FRM || Reg == RISCV::VL || Reg == RISCV::VLENB || + Reg == RISCV::VTYPE || RISCV::GPRPairRegClass.contains(Reg) || + RISCV::VRRegClass.contains(Reg) || isVectorRegList(Reg)) { + // Don't initialize: + // - FRM + // - VL, VLENB, VTYPE + // - vector registers (and vector register lists) + // - Zfinx registers + // Generate 'NOP' so that exegesis treats such registers as initialized + // (it tries to initialize them with '0' anyway). + return {nop()}; + } + errs() << "setRegTo is not implemented for Reg " << Reg + << ", results will be unreliable\n"; + return {}; +} + +const unsigned DefaultLoopCounterReg = RISCV::X31; // t6 +const unsigned ScratchMemoryReg = RISCV::X10; // a0 + +unsigned +ExegesisRISCVTarget::getDefaultLoopCounterRegister(const Triple &) const { + return DefaultLoopCounterReg; +} + +void ExegesisRISCVTarget::decrementLoopCounterAndJump( + MachineBasicBlock &MBB, MachineBasicBlock &TargetMBB, + const MCInstrInfo &MII, unsigned LoopRegister) const { + BuildMI(&MBB, DebugLoc(), MII.get(RISCV::ADDI)) + .addDef(LoopRegister) + .addUse(LoopRegister) + .addImm(-1); + BuildMI(&MBB, DebugLoc(), MII.get(RISCV::BNE)) + .addUse(LoopRegister) + .addUse(RISCV::X0) + .addMBB(&TargetMBB); +} + +unsigned ExegesisRISCVTarget::getScratchMemoryRegister(const Triple &TT) const { + return ScratchMemoryReg; // a0 +} + +void ExegesisRISCVTarget::fillMemoryOperands(InstructionTemplate &IT, + unsigned Reg, + unsigned Offset) const { + // TODO: for now we ignore Offset because have no way + // to detect it in instruction. + auto &I = IT.getInstr(); + + auto MemOpIt = + find_if(I.Operands, [](const Operand &Op) { return Op.isMemory(); }); + assert(MemOpIt != I.Operands.end() && + "Instruction must have memory operands"); + + const Operand &MemOp = *MemOpIt; + + assert(MemOp.isReg() && "Memory operand expected to be register"); + + IT.getValueFor(MemOp) = MCOperand::createReg(Reg); +} + +const unsigned UnavailableRegisters[4] = {RISCV::X0, DefaultLoopCounterReg, + ScratchIntReg, ScratchMemoryReg}; + +ArrayRef<unsigned> ExegesisRISCVTarget::getUnavailableRegisters() const { + return UnavailableRegisters; +} + +Error ExegesisRISCVTarget::randomizeTargetMCOperand( + const Instruction &Instr, const Variable &Var, MCOperand &AssignedValue, + const BitVector &ForbiddenRegs) const { + uint8_t OperandType = + Instr.getPrimaryOperand(Var).getExplicitOperandInfo().OperandType; + + switch (OperandType) { + case RISCVOp::OPERAND_FRMARG: + AssignedValue = MCOperand::createImm(RISCVFPRndMode::DYN); + break; + case RISCVOp::OPERAND_SIMM10_LSB0000_NONZERO: + AssignedValue = MCOperand::createImm(0b1 << 4); + break; + case RISCVOp::OPERAND_SIMM6_NONZERO: + case RISCVOp::OPERAND_UIMMLOG2XLEN_NONZERO: + AssignedValue = MCOperand::createImm(1); + break; + default: + if (OperandType >= RISCVOp::OPERAND_FIRST_RISCV_IMM && + OperandType <= RISCVOp::OPERAND_LAST_RISCV_IMM) + AssignedValue = MCOperand::createImm(0); + } + return Error::success(); +} + +std::vector<InstructionTemplate> +ExegesisRISCVTarget::generateInstructionVariants( + const Instruction &Instr, unsigned int MaxConfigsPerOpcode) const { + InstructionTemplate IT{&Instr}; + for (const Operand &Op : Instr.Operands) + if (Op.isMemory()) { + IT.getValueFor(Op) = MCOperand::createReg(ScratchMemoryReg); + } + return {IT}; +} + +} // anonymous namespace + +static ExegesisTarget *getTheRISCVExegesisTarget() { + static ExegesisRISCVTarget Target; + return &Target; +} + +void InitializeRISCVExegesisTarget() { + ExegesisTarget::registerTarget(getTheRISCVExegesisTarget()); +} + +} // namespace exegesis +} // namespace llvm diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp index 7100b51bbb72..25cdf1ce66d4 100644 --- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp +++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp @@ -53,13 +53,6 @@ computeAliasingInstructions(const LLVMState &State, const Instruction *Instr, if (OtherOpcode == Instr->Description.getOpcode()) continue; const Instruction &OtherInstr = State.getIC().getInstr(OtherOpcode); - const MCInstrDesc &OtherInstrDesc = OtherInstr.Description; - // Ignore instructions that we cannot run. - if (OtherInstrDesc.isPseudo() || OtherInstrDesc.usesCustomInsertionHook() || - OtherInstrDesc.isBranch() || OtherInstrDesc.isIndirectBranch() || - OtherInstrDesc.isCall() || OtherInstrDesc.isReturn()) { - continue; - } if (OtherInstr.hasMemoryOperands()) continue; if (!ET.allowAsBackToBack(OtherInstr)) @@ -81,12 +74,10 @@ static ExecutionMode getExecutionModes(const Instruction &Instr, EM |= ExecutionMode::ALWAYS_SERIAL_TIED_REGS_ALIAS; if (Instr.hasMemoryOperands()) EM |= ExecutionMode::SERIAL_VIA_MEMORY_INSTR; - else { - if (Instr.hasAliasingRegisters(ForbiddenRegisters)) - EM |= ExecutionMode::SERIAL_VIA_EXPLICIT_REGS; - if (Instr.hasOneUseOrOneDef()) - EM |= ExecutionMode::SERIAL_VIA_NON_MEMORY_INSTR; - } + if (Instr.hasAliasingNotMemoryRegisters(ForbiddenRegisters)) + EM |= ExecutionMode::SERIAL_VIA_EXPLICIT_REGS; + if (Instr.hasOneUseOrOneDef()) + EM |= ExecutionMode::SERIAL_VIA_NON_MEMORY_INSTR; return EM; } diff --git a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp index 7dcff60a8fd1..48357d443f71 100644 --- a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp +++ b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp @@ -73,6 +73,9 @@ Error SnippetGenerator::generateConfigurations( for (CodeTemplate &CT : Templates) { // TODO: Generate as many BenchmarkCode as needed. { + CT.ScratchSpacePointerInReg = + State.getExegesisTarget().getScratchMemoryRegister( + State.getTargetMachine().getTargetTriple()); BenchmarkCode BC; BC.Info = CT.Info; BC.Key.Instructions.reserve(CT.Instructions.size()); @@ -108,6 +111,12 @@ std::vector<RegisterValue> SnippetGenerator::computeRegisterInitialValues( // Loop invariant: DefinedRegs[i] is true iif it has been set at least once // before the current instruction. BitVector DefinedRegs = State.getRATC().emptyRegisters(); + // If target always expects a scratch memory register as live input, + // mark it as defined. + const ExegesisTarget &Target = State.getExegesisTarget(); + unsigned ScratchMemoryReg = Target.getScratchMemoryRegister( + State.getTargetMachine().getTargetTriple()); + DefinedRegs.set(ScratchMemoryReg); std::vector<RegisterValue> RIV; for (const InstructionTemplate &IT : Instructions) { // Returns the register that this Operand sets or uses, or 0 if this is not @@ -200,7 +209,8 @@ static void setRegisterOperandValue(const RegisterOperandAssignment &ROV, if (ROV.Op->isExplicit()) { auto &AssignedValue = IB.getValueFor(*ROV.Op); if (AssignedValue.isValid()) { - assert(AssignedValue.isReg() && AssignedValue.getReg() == ROV.Reg); + // TODO don't re-assign register operands which are already "locked" + // by Target in corresponding InstructionTemplate return; } AssignedValue = MCOperand::createReg(ROV.Reg); diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp index 546ec770a8d2..fa37e05956be 100644 --- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp +++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp @@ -274,6 +274,10 @@ static cl::opt<int> BenchmarkProcessCPU( cl::desc("The CPU number that the benchmarking process should executon on"), cl::cat(BenchmarkOptions), cl::init(-1)); +static cl::opt<std::string> MAttr( + "mattr", cl::desc("comma-separated list of target architecture features"), + cl::value_desc("+feature1,-feature2,..."), cl::cat(Options), cl::init("")); + static ExitOnError ExitOnErr("llvm-exegesis error: "); // Helper function that logs the error(s) and exits. @@ -296,6 +300,18 @@ T ExitOnFileError(const Twine &FileName, Expected<T> &&E) { return std::move(*E); } +static const char *getIgnoredOpcodeReasonOrNull(const LLVMState &State, + unsigned Opcode) { + const MCInstrDesc &InstrDesc = State.getIC().getInstr(Opcode).Description; + if (InstrDesc.isPseudo() || InstrDesc.usesCustomInsertionHook()) + return "Unsupported opcode: isPseudo/usesCustomInserter"; + if (InstrDesc.isBranch() || InstrDesc.isIndirectBranch()) + return "Unsupported opcode: isBranch/isIndirectBranch"; + if (InstrDesc.isCall() || InstrDesc.isReturn()) + return "Unsupported opcode: isCall/isReturn"; + return nullptr; +} + // Checks that only one of OpcodeNames, OpcodeIndex or SnippetsFile is provided, // and returns the opcode indices or {} if snippets should be read from // `SnippetsFile`. @@ -334,6 +350,7 @@ static std::vector<unsigned> getOpcodesOrDie(const LLVMState &State) { return I->getSecond(); return 0u; }; + SmallVector<StringRef, 2> Pieces; StringRef(OpcodeNames.getValue()) .split(Pieces, ",", /* MaxSplit */ -1, /* KeepEmpty */ false); @@ -352,17 +369,11 @@ static std::vector<unsigned> getOpcodesOrDie(const LLVMState &State) { static Expected<std::vector<BenchmarkCode>> generateSnippets(const LLVMState &State, unsigned Opcode, const BitVector &ForbiddenRegs) { - const Instruction &Instr = State.getIC().getInstr(Opcode); - const MCInstrDesc &InstrDesc = Instr.Description; // Ignore instructions that we cannot run. - if (InstrDesc.isPseudo() || InstrDesc.usesCustomInsertionHook()) - return make_error<Failure>( - "Unsupported opcode: isPseudo/usesCustomInserter"); - if (InstrDesc.isBranch() || InstrDesc.isIndirectBranch()) - return make_error<Failure>("Unsupported opcode: isBranch/isIndirectBranch"); - if (InstrDesc.isCall() || InstrDesc.isReturn()) - return make_error<Failure>("Unsupported opcode: isCall/isReturn"); + if (const char *Reason = getIgnoredOpcodeReasonOrNull(State, Opcode)) + return make_error<Failure>(Reason); + const Instruction &Instr = State.getIC().getInstr(Opcode); const std::vector<InstructionTemplate> InstructionVariants = State.getExegesisTarget().generateInstructionVariants( Instr, MaxConfigsPerOpcode); @@ -485,8 +496,8 @@ void benchmarkMain() { LLVMInitialize##TargetName##AsmParser(); #include "llvm/Config/TargetExegesis.def" - const LLVMState State = - ExitOnErr(LLVMState::Create(TripleName, MCPU, "", UseDummyPerfCounters)); + const LLVMState State = ExitOnErr( + LLVMState::Create(TripleName, MCPU, MAttr, UseDummyPerfCounters)); // Preliminary check to ensure features needed for requested // benchmark mode are present on target CPU and/or OS. diff --git a/llvm/tools/llvm-gsymutil/Opts.td b/llvm/tools/llvm-gsymutil/Opts.td index 00f903c5211f..d61b418d2d84 100644 --- a/llvm/tools/llvm-gsymutil/Opts.td +++ b/llvm/tools/llvm-gsymutil/Opts.td @@ -18,6 +18,7 @@ defm convert : "Convert the specified file to the GSYM format.\nSupported files include ELF and mach-o files that will have their debug info (DWARF) and symbol table converted">; def merged_functions : FF<"merged-functions", "Encode merged function information for functions in debug info that have matching address ranges.\nWithout this option one function per unique address range will be emitted.">; +def dwarf_callsites : FF<"dwarf-callsites", "Load call site info from DWARF, if available">; defm callsites_yaml_file : Eq<"callsites-yaml-file", "Load call site info from YAML file. Useful for testing.">, Flags<[HelpHidden]>; defm arch : diff --git a/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp b/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp index 4d441465c47f..aed4ae7c615f 100644 --- a/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp +++ b/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp @@ -64,12 +64,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - constexpr llvm::StringLiteral NAME##_init[] = VALUE; \ - constexpr llvm::ArrayRef<llvm::StringLiteral> NAME( \ - NAME##_init, std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE const opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -79,7 +80,8 @@ const opt::OptTable::Info InfoTable[] = { class GSYMUtilOptTable : public llvm::opt::GenericOptTable { public: - GSYMUtilOptTable() : GenericOptTable(InfoTable) { + GSYMUtilOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) { setGroupedShortOptions(true); } }; @@ -97,6 +99,7 @@ static bool Quiet; static std::vector<uint64_t> LookupAddresses; static bool LookupAddressesFromStdin; static bool StoreMergedFunctionInfo = false; +static bool LoadDwarfCallSites = false; static std::string CallSiteYamlPath; static void parseArgs(int argc, char **argv) { @@ -189,6 +192,8 @@ static void parseArgs(int argc, char **argv) { std::exit(1); } } + + LoadDwarfCallSites = Args.hasArg(OPT_dwarf_callsites); } /// @} @@ -363,7 +368,7 @@ static llvm::Error handleObjectFile(ObjectFile &Obj, const std::string &OutFile, // Make a DWARF transformer object and populate the ranges of the code // so we don't end up adding invalid functions to GSYM data. - DwarfTransformer DT(*DICtx, Gsym); + DwarfTransformer DT(*DICtx, Gsym, LoadDwarfCallSites); if (!TextRanges.empty()) Gsym.SetValidTextRanges(TextRanges); diff --git a/llvm/tools/llvm-ifs/llvm-ifs.cpp b/llvm/tools/llvm-ifs/llvm-ifs.cpp index b76ea8dec0c9..e12016c51e90 100644 --- a/llvm/tools/llvm-ifs/llvm-ifs.cpp +++ b/llvm/tools/llvm-ifs/llvm-ifs.cpp @@ -59,12 +59,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -74,7 +75,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class IFSOptTable : public opt::GenericOptTable { public: - IFSOptTable() : opt::GenericOptTable(InfoTable) { + IFSOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) { setGroupedShortOptions(true); } }; diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink-coff.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink-coff.cpp index 5271fdb55659..6db78926101f 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink-coff.cpp +++ b/llvm/tools/llvm-jitlink/llvm-jitlink-coff.cpp @@ -66,6 +66,8 @@ static Expected<Symbol &> getCOFFStubTarget(LinkGraph &G, Block &B) { namespace llvm { Error registerCOFFGraphInfo(Session &S, LinkGraph &G) { + std::lock_guard<std::mutex> Lock(S.M); + auto FileName = sys::path::filename(G.getName()); if (S.FileInfos.count(FileName)) { return make_error<StringError>("When -check is passed, file names must be " diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp index a8c804a459e3..6aa89413b723 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp +++ b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp @@ -101,6 +101,8 @@ static Error registerSymbol(LinkGraph &G, Symbol &Sym, Session::FileInfo &FI, namespace llvm { Error registerELFGraphInfo(Session &S, LinkGraph &G) { + std::lock_guard<std::mutex> Lock(S.M); + auto FileName = sys::path::filename(G.getName()); if (S.FileInfos.count(FileName)) { return make_error<StringError>("When -check is passed, file names must be " diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp index 2c60c802293a..2fc56c9fcc72 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp +++ b/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp @@ -69,6 +69,8 @@ static Expected<Symbol &> getMachOStubTarget(LinkGraph &G, Block &B) { namespace llvm { Error registerMachOGraphInfo(Session &S, LinkGraph &G) { + std::lock_guard<std::mutex> Lock(S.M); + auto FileName = sys::path::filename(G.getName()); if (S.FileInfos.count(FileName)) { return make_error<StringError>("When -check is passed, file names must be " diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp index ccc152dc753b..646d4cef01a5 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp +++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp @@ -30,6 +30,7 @@ #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" #include "llvm/ExecutionEngine/Orc/JITLinkRedirectableSymbolManager.h" +#include "llvm/ExecutionEngine/Orc/JITLinkReentryTrampolines.h" #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" #include "llvm/ExecutionEngine/Orc/LoadLinkableFile.h" #include "llvm/ExecutionEngine/Orc/MachO.h" @@ -90,6 +91,10 @@ static cl::list<std::string> InputFiles(cl::Positional, cl::OneOrMore, cl::desc("input files"), cl::cat(JITLinkCategory)); +static cl::opt<size_t> MaterializationThreads( + "num-threads", cl::desc("Number of materialization threads to use"), + cl::init(std::numeric_limits<size_t>::max()), cl::cat(JITLinkCategory)); + static cl::list<std::string> LibrarySearchPaths("L", cl::desc("Add dir to the list of library search paths"), @@ -365,7 +370,7 @@ static raw_ostream & operator<<(raw_ostream &OS, const Session::SymbolInfoMap &SIM) { OS << "Symbols:\n"; for (auto &SKV : SIM) - OS << " \"" << SKV.first() << "\" " << SKV.second << "\n"; + OS << " \"" << SKV.first << "\" " << SKV.second << "\n"; return OS; } @@ -399,6 +404,7 @@ bool lazyLinkingRequested() { } static Error applyHarnessPromotions(Session &S, LinkGraph &G) { + std::lock_guard<std::mutex> Lock(S.M); // If this graph is part of the test harness there's nothing to do. if (S.HarnessFiles.empty() || S.HarnessFiles.count(G.getName())) @@ -416,8 +422,8 @@ static Error applyHarnessPromotions(Session &S, LinkGraph &G) { continue; if (Sym->getLinkage() == Linkage::Weak) { - if (!S.CanonicalWeakDefs.count(Sym->getName()) || - S.CanonicalWeakDefs[Sym->getName()] != G.getName()) { + if (!S.CanonicalWeakDefs.count(*Sym->getName()) || + S.CanonicalWeakDefs[*Sym->getName()] != G.getName()) { LLVM_DEBUG({ dbgs() << " Externalizing weak symbol " << Sym->getName() << "\n"; }); @@ -426,18 +432,18 @@ static Error applyHarnessPromotions(Session &S, LinkGraph &G) { LLVM_DEBUG({ dbgs() << " Making weak symbol " << Sym->getName() << " strong\n"; }); - if (S.HarnessExternals.count(Sym->getName())) + if (S.HarnessExternals.count(*Sym->getName())) Sym->setScope(Scope::Default); else Sym->setScope(Scope::Hidden); Sym->setLinkage(Linkage::Strong); } - } else if (S.HarnessExternals.count(Sym->getName())) { + } else if (S.HarnessExternals.count(*Sym->getName())) { LLVM_DEBUG(dbgs() << " Promoting " << Sym->getName() << "\n"); Sym->setScope(Scope::Default); Sym->setLive(true); continue; - } else if (S.HarnessDefinitions.count(Sym->getName())) { + } else if (S.HarnessDefinitions.count(*Sym->getName())) { LLVM_DEBUG(dbgs() << " Externalizing " << Sym->getName() << "\n"); DefinitionsToRemove.push_back(Sym); } @@ -449,7 +455,11 @@ static Error applyHarnessPromotions(Session &S, LinkGraph &G) { return Error::success(); } -static void dumpSectionContents(raw_ostream &OS, LinkGraph &G) { +static void dumpSectionContents(raw_ostream &OS, Session &S, LinkGraph &G) { + std::lock_guard<std::mutex> Lock(S.M); + + outs() << "Relocated section contents for " << G.getName() << ":\n"; + constexpr orc::ExecutorAddrDiff DumpWidth = 16; static_assert(isPowerOf2_64(DumpWidth), "DumpWidth must be a power of two"); @@ -739,8 +749,7 @@ getTestObjectFileInterface(Session &S, MemoryBufferRef O) { !(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) continue; - auto InternedName = S.ES.intern(*Name); - I->SymbolFlags[InternedName] = std::move(*SymFlags); + I->SymbolFlags[S.ES.intern(*Name)] = std::move(*SymFlags); } return I; @@ -842,7 +851,7 @@ static Expected<std::unique_ptr<ExecutorProcessControl>> launchExecutor() { S.CreateMemoryManager = createSharedMemoryManager; return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>( - std::make_unique<DynamicThreadPoolTaskDispatcher>(std::nullopt), + std::make_unique<DynamicThreadPoolTaskDispatcher>(MaterializationThreads), std::move(S), FromExecutor[ReadEnd], ToExecutor[WriteEnd]); #endif } @@ -949,41 +958,18 @@ public: } }; -static void handleLazyCallFailure() { - dbgs() << "ERROR: failure to materialize lazy call-through target.\n"; - exit(1); -} - -static void *reenter(void *Ctx, void *TrampolineAddr) { - std::promise<void *> LandingAddressP; - auto LandingAddressF = LandingAddressP.get_future(); - - auto *EPCIU = static_cast<EPCIndirectionUtils *>(Ctx); - EPCIU->getLazyCallThroughManager().resolveTrampolineLandingAddress( - ExecutorAddr::fromPtr(TrampolineAddr), [&](ExecutorAddr LandingAddress) { - LandingAddressP.set_value(LandingAddress.toPtr<void *>()); - }); - return LandingAddressF.get(); -} - Expected<std::unique_ptr<Session::LazyLinkingSupport>> -createLazyLinkingSupport(ObjectLinkingLayer &OLL) { - auto EPCIU = EPCIndirectionUtils::Create(OLL.getExecutionSession()); - if (!EPCIU) - return EPCIU.takeError(); - if (auto Err = (*EPCIU) - ->writeResolverBlock(ExecutorAddr::fromPtr(&reenter), - ExecutorAddr::fromPtr(EPCIU->get())) - .takeError()) - return Err; - (*EPCIU)->createLazyCallThroughManager( - OLL.getExecutionSession(), ExecutorAddr::fromPtr(handleLazyCallFailure)); +createLazyLinkingSupport(ObjectLinkingLayer &OLL, JITDylib &PlatformJD) { auto RSMgr = JITLinkRedirectableSymbolManager::Create(OLL); if (!RSMgr) return RSMgr.takeError(); - return std::make_unique<Session::LazyLinkingSupport>(std::move(*EPCIU), - std::move(*RSMgr), OLL); + auto LRMgr = createJITLinkLazyReexportsManager(OLL, **RSMgr, PlatformJD); + if (!LRMgr) + return LRMgr.takeError(); + + return std::make_unique<Session::LazyLinkingSupport>(std::move(*RSMgr), + std::move(*LRMgr), OLL); } Expected<std::unique_ptr<Session>> Session::Create(Triple TT, @@ -1007,10 +993,21 @@ Expected<std::unique_ptr<Session>> Session::Create(Triple TT, auto PageSize = sys::Process::getPageSize(); if (!PageSize) return PageSize.takeError(); + std::unique_ptr<TaskDispatcher> Dispatcher; + if (MaterializationThreads == 0) + Dispatcher = std::make_unique<InPlaceTaskDispatcher>(); + else { +#if LLVM_ENABLE_THREADS + Dispatcher = std::make_unique<DynamicThreadPoolTaskDispatcher>( + MaterializationThreads); +#else + llvm_unreachable("MaterializationThreads should be 0"); +#endif + } + EPC = std::make_unique<SelfExecutorProcessControl>( - std::make_shared<SymbolStringPool>(), - std::make_unique<InPlaceTaskDispatcher>(), std::move(TT), *PageSize, - createInProcessMemoryManager()); + std::make_shared<SymbolStringPool>(), std::move(Dispatcher), + std::move(TT), *PageSize, createInProcessMemoryManager()); } Error Err = Error::success(); @@ -1020,7 +1017,8 @@ Expected<std::unique_ptr<Session>> Session::Create(Triple TT, S->Features = std::move(Features); if (lazyLinkingRequested()) { - if (auto LazyLinking = createLazyLinkingSupport(S->ObjLayer)) + if (auto LazyLinking = + createLazyLinkingSupport(S->ObjLayer, *S->PlatformJD)) S->LazyLinking = std::move(*LazyLinking); else return LazyLinking.takeError(); @@ -1243,6 +1241,7 @@ void Session::modifyPassConfig(LinkGraph &G, PassConfiguration &PassConfig) { if (ShowGraphsRegex) PassConfig.PostFixupPasses.push_back([this](LinkGraph &G) -> Error { + std::lock_guard<std::mutex> Lock(M); // Print graph if ShowLinkGraphs is specified-but-empty, or if // it contains the given graph. if (ShowGraphsRegex->match(G.getName())) { @@ -1252,18 +1251,29 @@ void Session::modifyPassConfig(LinkGraph &G, PassConfiguration &PassConfig) { return Error::success(); }); + PassConfig.PrePrunePasses.push_back([this](LinkGraph &G) { + std::lock_guard<std::mutex> Lock(M); + ++ActiveLinks; + return Error::success(); + }); PassConfig.PrePrunePasses.push_back( [this](LinkGraph &G) { return applyHarnessPromotions(*this, G); }); if (ShowRelocatedSectionContents) - PassConfig.PostFixupPasses.push_back([](LinkGraph &G) -> Error { - outs() << "Relocated section contents for " << G.getName() << ":\n"; - dumpSectionContents(outs(), G); + PassConfig.PostFixupPasses.push_back([this](LinkGraph &G) -> Error { + dumpSectionContents(outs(), *this, G); return Error::success(); }); if (AddSelfRelocations) PassConfig.PostPrunePasses.push_back(addSelfRelocations); + + PassConfig.PostFixupPasses.push_back([this](LinkGraph &G) { + std::lock_guard<std::mutex> Lock(M); + if (--ActiveLinks == 0) + ActiveLinksCV.notify_all(); + return Error::success(); + }); } Expected<JITDylib *> Session::getOrLoadDynamicLibrary(StringRef LibPath) { @@ -1306,9 +1316,9 @@ Error Session::FileInfo::registerGOTEntry( auto TS = GetSymbolTarget(G, Sym.getBlock()); if (!TS) return TS.takeError(); - GOTEntryInfos[TS->getName()] = {Sym.getSymbolContent(), - Sym.getAddress().getValue(), - Sym.getTargetFlags()}; + GOTEntryInfos[*TS->getName()] = {Sym.getSymbolContent(), + Sym.getAddress().getValue(), + Sym.getTargetFlags()}; return Error::success(); } @@ -1322,7 +1332,7 @@ Error Session::FileInfo::registerStubEntry( if (!TS) return TS.takeError(); - SmallVectorImpl<MemoryRegionInfo> &Entry = StubInfos[TS->getName()]; + SmallVectorImpl<MemoryRegionInfo> &Entry = StubInfos[*TS->getName()]; Entry.insert(Entry.begin(), {Sym.getSymbolContent(), Sym.getAddress().getValue(), Sym.getTargetFlags()}); @@ -1340,7 +1350,7 @@ Error Session::FileInfo::registerMultiStubEntry( if (!Target) return Target.takeError(); - SmallVectorImpl<MemoryRegionInfo> &Entry = StubInfos[Target->getName()]; + SmallVectorImpl<MemoryRegionInfo> &Entry = StubInfos[*Target->getName()]; Entry.emplace_back(Sym.getSymbolContent(), Sym.getAddress().getValue(), Sym.getTargetFlags()); @@ -1485,15 +1495,16 @@ Session::findGOTEntryInfo(StringRef FileName, StringRef TargetName) { return GOTInfoItr->second; } -bool Session::isSymbolRegistered(StringRef SymbolName) { +bool Session::isSymbolRegistered(const orc::SymbolStringPtr &SymbolName) { return SymbolInfos.count(SymbolName); } Expected<Session::MemoryRegionInfo &> -Session::findSymbolInfo(StringRef SymbolName, Twine ErrorMsgStem) { +Session::findSymbolInfo(const orc::SymbolStringPtr &SymbolName, + Twine ErrorMsgStem) { auto SymInfoItr = SymbolInfos.find(SymbolName); if (SymInfoItr == SymbolInfos.end()) - return make_error<StringError>(ErrorMsgStem + ": symbol " + SymbolName + + return make_error<StringError>(ErrorMsgStem + ": symbol " + *SymbolName + " not found", inconvertibleErrorCode()); return SymInfoItr->second; @@ -1622,6 +1633,40 @@ static Error sanitizeArguments(const Triple &TT, const char *ArgV0) { } } +#if LLVM_ENABLE_THREADS + if (MaterializationThreads == std::numeric_limits<size_t>::max()) { + if (auto HC = std::thread::hardware_concurrency()) + MaterializationThreads = HC; + else { + errs() << "Warning: std::thread::hardware_concurrency() returned 0, " + "defaulting to -num-threads=1.\n"; + MaterializationThreads = 1; + } + } +#else + if (MaterializationThreads.getNumOccurrences() && + MaterializationThreads != 0) { + errs() << "Warning: -num-threads was set, but LLVM was built with threads " + "disabled. Resetting to -num-threads=0\n"; + } + MaterializationThreads = 0; +#endif + + if (!!OutOfProcessExecutor.getNumOccurrences() || + !!OutOfProcessExecutorConnect.getNumOccurrences()) { + if (NoExec) + return make_error<StringError>("-noexec cannot be used with " + + OutOfProcessExecutor.ArgStr + " or " + + OutOfProcessExecutorConnect.ArgStr, + inconvertibleErrorCode()); + + if (MaterializationThreads == 0) + return make_error<StringError>("-threads=0 cannot be used with " + + OutOfProcessExecutor.ArgStr + " or " + + OutOfProcessExecutorConnect.ArgStr, + inconvertibleErrorCode()); + } + // Only one of -oop-executor and -oop-executor-connect can be used. if (!!OutOfProcessExecutor.getNumOccurrences() && !!OutOfProcessExecutorConnect.getNumOccurrences()) @@ -1641,10 +1686,17 @@ static Error sanitizeArguments(const Triple &TT, const char *ArgV0) { OutOfProcessExecutor = OOPExecutorPath.str().str(); } - if (lazyLinkingRequested() && !TestHarnesses.empty()) - return make_error<StringError>( - "Lazy linking cannot be used with -harness mode", - inconvertibleErrorCode()); + // If lazy linking is requested then check compatibility with other options. + if (lazyLinkingRequested()) { + if (OrcRuntime.empty()) + return make_error<StringError>("Lazy linking requries the ORC runtime", + inconvertibleErrorCode()); + + if (!TestHarnesses.empty()) + return make_error<StringError>( + "Lazy linking cannot be used with -harness mode", + inconvertibleErrorCode()); + } return Error::success(); } @@ -1719,12 +1771,13 @@ static Error addAbsoluteSymbols(Session &S, AbsDefStmt + "\"", inconvertibleErrorCode()); ExecutorSymbolDef AbsDef(ExecutorAddr(Addr), JITSymbolFlags::Exported); - if (auto Err = JD.define(absoluteSymbols({{S.ES.intern(Name), AbsDef}}))) + auto InternedName = S.ES.intern(Name); + if (auto Err = JD.define(absoluteSymbols({{InternedName, AbsDef}}))) return Err; // Register the absolute symbol with the session symbol infos. - S.SymbolInfos[Name] = {ArrayRef<char>(), Addr, - AbsDef.getFlags().getTargetFlags()}; + S.SymbolInfos[std::move(InternedName)] = + {ArrayRef<char>(), Addr, AbsDef.getFlags().getTargetFlags()}; } return Error::success(); @@ -2327,14 +2380,18 @@ static Error runChecks(Session &S, Triple TT, SubtargetFeatures Features) { if (CheckFiles.empty()) return Error::success(); + S.waitForFilesLinkedFromEntryPointFile(); + LLVM_DEBUG(dbgs() << "Running checks...\n"); auto IsSymbolValid = [&S](StringRef Symbol) { - return S.isSymbolRegistered(Symbol); + auto InternedSymbol = S.ES.getSymbolStringPool()->intern(Symbol); + return S.isSymbolRegistered(InternedSymbol); }; auto GetSymbolInfo = [&S](StringRef Symbol) { - return S.findSymbolInfo(Symbol, "Can not get symbol info"); + auto InternedSymbol = S.ES.getSymbolStringPool()->intern(Symbol); + return S.findSymbolInfo(InternedSymbol, "Can not get symbol info"); }; auto GetSectionInfo = [&S](StringRef FileName, StringRef SectionName) { diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.h b/llvm/tools/llvm-jitlink/llvm-jitlink.h index 40fac2fe6888..be3710971729 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink.h +++ b/llvm/tools/llvm-jitlink/llvm-jitlink.h @@ -15,9 +15,9 @@ #include "llvm/ADT/StringSet.h" #include "llvm/ExecutionEngine/Orc/Core.h" -#include "llvm/ExecutionEngine/Orc/EPCIndirectionUtils.h" #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" #include "llvm/ExecutionEngine/Orc/LazyObjectLinkingLayer.h" +#include "llvm/ExecutionEngine/Orc/LazyReexports.h" #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" #include "llvm/ExecutionEngine/Orc/RedirectionManager.h" #include "llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h" @@ -33,20 +33,14 @@ namespace llvm { struct Session { struct LazyLinkingSupport { - LazyLinkingSupport(std::unique_ptr<orc::EPCIndirectionUtils> EPCIU, - std::unique_ptr<orc::RedirectableSymbolManager> RSMgr, + LazyLinkingSupport(std::unique_ptr<orc::RedirectableSymbolManager> RSMgr, + std::unique_ptr<orc::LazyReexportsManager> LRMgr, orc::ObjectLinkingLayer &ObjLinkingLayer) - : EPCIU(std::move(EPCIU)), RSMgr(std::move(RSMgr)), - LazyObjLinkingLayer(ObjLinkingLayer, - this->EPCIU->getLazyCallThroughManager(), - *this->RSMgr) {} - ~LazyLinkingSupport() { - if (auto Err = EPCIU->cleanup()) - LazyObjLinkingLayer.getExecutionSession().reportError(std::move(Err)); - } - - std::unique_ptr<orc::EPCIndirectionUtils> EPCIU; + : RSMgr(std::move(RSMgr)), LRMgr(std::move(LRMgr)), + LazyObjLinkingLayer(ObjLinkingLayer, *this->LRMgr) {} + std::unique_ptr<orc::RedirectableSymbolManager> RSMgr; + std::unique_ptr<orc::LazyReexportsManager> LRMgr; orc::LazyObjectLinkingLayer LazyObjLinkingLayer; }; @@ -67,6 +61,16 @@ struct Session { void modifyPassConfig(jitlink::LinkGraph &G, jitlink::PassConfiguration &PassConfig); + /// For -check: wait for all files that are referenced (transitively) from + /// the entry point *file* to be linked. (ORC's usual dependence tracking is + /// to fine-grained here: a lookup of the main symbol will return as soon as + /// all reachable symbols have been linked, but testcases may want to + /// inspect side-effects in unreachable symbols).. + void waitForFilesLinkedFromEntryPointFile() { + std::unique_lock<std::mutex> Lock(M); + return ActiveLinksCV.wait(Lock, [this]() { return ActiveLinks == 0; }); + } + using MemoryRegionInfo = RuntimeDyldChecker::MemoryRegionInfo; struct FileInfo { @@ -78,7 +82,6 @@ struct Session { using LinkGraph = jitlink::LinkGraph; using GetSymbolTargetFunction = unique_function<Expected<Symbol &>(LinkGraph &G, jitlink::Block &)>; - Error registerGOTEntry(LinkGraph &G, Symbol &Sym, GetSymbolTargetFunction GetSymbolTarget); Error registerStubEntry(LinkGraph &G, Symbol &Sym, @@ -88,7 +91,7 @@ struct Session { }; using DynLibJDMap = std::map<std::string, orc::JITDylib *, std::less<>>; - using SymbolInfoMap = StringMap<MemoryRegionInfo>; + using SymbolInfoMap = DenseMap<orc::SymbolStringPtr, MemoryRegionInfo>; using FileInfoMap = StringMap<FileInfo>; Expected<orc::JITDylib *> getOrLoadDynamicLibrary(StringRef LibPath); @@ -111,12 +114,15 @@ struct Session { Expected<MemoryRegionInfo &> findGOTEntryInfo(StringRef FileName, StringRef TargetName); - bool isSymbolRegistered(StringRef Name); - Expected<MemoryRegionInfo &> findSymbolInfo(StringRef SymbolName, + bool isSymbolRegistered(const orc::SymbolStringPtr &Name); + Expected<MemoryRegionInfo &> findSymbolInfo(const orc::SymbolStringPtr &Name, Twine ErrorMsgStem); DynLibJDMap DynLibJDs; + std::mutex M; + std::condition_variable ActiveLinksCV; + size_t ActiveLinks = 0; SymbolInfoMap SymbolInfos; FileInfoMap FileInfos; diff --git a/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp b/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp index 3d3f3f0af4b7..94247118dc4e 100644 --- a/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp +++ b/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp @@ -48,12 +48,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -63,7 +64,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class LibtoolDarwinOptTable : public opt::GenericOptTable { public: - LibtoolDarwinOptTable() : GenericOptTable(InfoTable) {} + LibtoolDarwinOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; } // end anonymous namespace diff --git a/llvm/tools/llvm-lipo/llvm-lipo.cpp b/llvm/tools/llvm-lipo/llvm-lipo.cpp index 711a9185e155..3c0197e8b7ba 100644 --- a/llvm/tools/llvm-lipo/llvm-lipo.cpp +++ b/llvm/tools/llvm-lipo/llvm-lipo.cpp @@ -72,12 +72,13 @@ enum LipoID { }; namespace lipo { -#define PREFIX(NAME, VALUE) \ - static constexpr llvm::StringLiteral NAME##_init[] = VALUE; \ - static constexpr llvm::ArrayRef<llvm::StringLiteral> NAME( \ - NAME##_init, std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "LipoOpts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "LipoOpts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info LipoInfoTable[] = { @@ -89,7 +90,9 @@ static constexpr opt::OptTable::Info LipoInfoTable[] = { class LipoOptTable : public opt::GenericOptTable { public: - LipoOptTable() : opt::GenericOptTable(lipo::LipoInfoTable) {} + LipoOptTable() + : opt::GenericOptTable(lipo::OptionStrTable, lipo::OptionPrefixesTable, + lipo::LipoInfoTable) {} }; enum class LipoAction { diff --git a/llvm/tools/llvm-mc/Disassembler.cpp b/llvm/tools/llvm-mc/Disassembler.cpp index a588058437ec..16897054fbea 100644 --- a/llvm/tools/llvm-mc/Disassembler.cpp +++ b/llvm/tools/llvm-mc/Disassembler.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "Disassembler.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDisassembler/MCDisassembler.h" @@ -94,10 +95,8 @@ static bool SkipToToken(StringRef &Str) { } } - -static bool ByteArrayFromString(ByteArrayTy &ByteArray, - StringRef &Str, - SourceMgr &SM) { +static bool byteArrayFromString(ByteArrayTy &ByteArray, StringRef &Str, + SourceMgr &SM, bool HexBytes) { while (SkipToToken(Str)) { // Handled by higher level if (Str[0] == '[' || Str[0] == ']') @@ -109,7 +108,24 @@ static bool ByteArrayFromString(ByteArrayTy &ByteArray, // Convert to a byte and add to the byte vector. unsigned ByteVal; - if (Value.getAsInteger(0, ByteVal) || ByteVal > 255) { + if (HexBytes) { + if (Next < 2) { + SM.PrintMessage(SMLoc::getFromPointer(Value.data()), + SourceMgr::DK_Error, "expected two hex digits"); + Str = Str.substr(Next); + return true; + } + Next = 2; + unsigned C0 = hexDigitValue(Value[0]); + unsigned C1 = hexDigitValue(Value[1]); + if (C0 == -1u || C1 == -1u) { + SM.PrintMessage(SMLoc::getFromPointer(Value.data()), + SourceMgr::DK_Error, "invalid input token"); + Str = Str.substr(Next); + return true; + } + ByteVal = C0 * 16 + C1; + } else if (Value.getAsInteger(0, ByteVal) || ByteVal > 255) { // If we have an error, print it and skip to the end of line. SM.PrintMessage(SMLoc::getFromPointer(Value.data()), SourceMgr::DK_Error, "invalid input token"); @@ -130,9 +146,8 @@ static bool ByteArrayFromString(ByteArrayTy &ByteArray, int Disassembler::disassemble(const Target &T, const std::string &Triple, MCSubtargetInfo &STI, MCStreamer &Streamer, MemoryBuffer &Buffer, SourceMgr &SM, - MCContext &Ctx, - const MCTargetOptions &MCOptions) { - + MCContext &Ctx, const MCTargetOptions &MCOptions, + bool HexBytes) { std::unique_ptr<const MCRegisterInfo> MRI(T.createMCRegInfo(Triple)); if (!MRI) { errs() << "error: no register info for target " << Triple << "\n"; @@ -153,9 +168,6 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple, return -1; } - // Set up initial section manually here - Streamer.initSections(false, STI); - bool ErrorOccurred = false; // Convert the input to a vector for disassembly. @@ -188,7 +200,7 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple, } // It's a real token, get the bytes and emit them - ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM); + ErrorOccurred |= byteArrayFromString(ByteArray, Str, SM, HexBytes); if (!ByteArray.first.empty()) ErrorOccurred |= diff --git a/llvm/tools/llvm-mc/Disassembler.h b/llvm/tools/llvm-mc/Disassembler.h index d0226abadc63..5efffca1e992 100644 --- a/llvm/tools/llvm-mc/Disassembler.h +++ b/llvm/tools/llvm-mc/Disassembler.h @@ -32,7 +32,7 @@ public: static int disassemble(const Target &T, const std::string &Triple, MCSubtargetInfo &STI, MCStreamer &Streamer, MemoryBuffer &Buffer, SourceMgr &SM, MCContext &Ctx, - const MCTargetOptions &MCOptions); + const MCTargetOptions &MCOptions, bool HexBytes); }; } // namespace llvm diff --git a/llvm/tools/llvm-mc/llvm-mc.cpp b/llvm/tools/llvm-mc/llvm-mc.cpp index 898d79b9233b..70f92d09aded 100644 --- a/llvm/tools/llvm-mc/llvm-mc.cpp +++ b/llvm/tools/llvm-mc/llvm-mc.cpp @@ -94,6 +94,12 @@ static cl::opt<bool> cl::desc("Prefer hex format for immediate values"), cl::cat(MCCategory)); +static cl::opt<bool> + HexBytes("hex", + cl::desc("Take raw hexadecimal bytes as input for disassembly. " + "Whitespace is ignored"), + cl::cat(MCCategory)); + static cl::list<std::string> DefineSymbol("defsym", cl::desc("Defines a symbol to be an integer constant"), @@ -563,7 +569,7 @@ int main(int argc, char **argv) { : MAB->createObjectWriter(*OS), std::unique_ptr<MCCodeEmitter>(CE), *STI)); if (NoExecStack) - Str->initSections(true, *STI); + Str->switchSection(Ctx.getAsmInfo()->getNonexecutableStackSection(Ctx)); Str->emitVersionForTarget(TheTriple, VersionTuple(), nullptr, VersionTuple()); } @@ -592,7 +598,7 @@ int main(int argc, char **argv) { } if (disassemble) Res = Disassembler::disassemble(*TheTarget, TripleName, *STI, *Str, *Buffer, - SrcMgr, Ctx, MCOptions); + SrcMgr, Ctx, MCOptions, HexBytes); // Keep output if no errors. if (Res == 0) { diff --git a/llvm/tools/llvm-ml/llvm-ml.cpp b/llvm/tools/llvm-ml/llvm-ml.cpp index db69109e2d1f..1aa41096002e 100644 --- a/llvm/tools/llvm-ml/llvm-ml.cpp +++ b/llvm/tools/llvm-ml/llvm-ml.cpp @@ -58,12 +58,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -73,7 +74,9 @@ static constexpr opt::OptTable::Info InfoTable[] = { class MLOptTable : public opt::GenericOptTable { public: - MLOptTable() : opt::GenericOptTable(InfoTable, /*IgnoreCase=*/false) {} + MLOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable, + /*IgnoreCase=*/false) {} }; } // namespace diff --git a/llvm/tools/llvm-mt/llvm-mt.cpp b/llvm/tools/llvm-mt/llvm-mt.cpp index 8b793b877642..3bd1bc786f86 100644 --- a/llvm/tools/llvm-mt/llvm-mt.cpp +++ b/llvm/tools/llvm-mt/llvm-mt.cpp @@ -40,12 +40,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -56,7 +57,9 @@ static constexpr opt::OptTable::Info InfoTable[] = { class CvtResOptTable : public opt::GenericOptTable { public: - CvtResOptTable() : opt::GenericOptTable(InfoTable, true) {} + CvtResOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable, + true) {} }; } // namespace diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp index d3e8d4c5ed98..e7c3e36dd38d 100644 --- a/llvm/tools/llvm-nm/llvm-nm.cpp +++ b/llvm/tools/llvm-nm/llvm-nm.cpp @@ -65,12 +65,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -80,7 +81,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class NmOptTable : public opt::GenericOptTable { public: - NmOptTable() : opt::GenericOptTable(InfoTable) { + NmOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) { setGroupedShortOptions(true); } }; diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp index 104d802b1e1e..0925fc55317f 100644 --- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp +++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp @@ -39,12 +39,13 @@ enum ObjcopyID { }; namespace objcopy_opt { -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "ObjcopyOpts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "ObjcopyOpts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info ObjcopyInfoTable[] = { #define OPTION(...) \ @@ -56,7 +57,10 @@ static constexpr opt::OptTable::Info ObjcopyInfoTable[] = { class ObjcopyOptTable : public opt::GenericOptTable { public: - ObjcopyOptTable() : opt::GenericOptTable(objcopy_opt::ObjcopyInfoTable) { + ObjcopyOptTable() + : opt::GenericOptTable(objcopy_opt::OptionStrTable, + objcopy_opt::OptionPrefixesTable, + objcopy_opt::ObjcopyInfoTable) { setGroupedShortOptions(true); setDashDashParsing(true); } @@ -71,13 +75,13 @@ enum InstallNameToolID { }; namespace install_name_tool { +#define OPTTABLE_STR_TABLE_CODE +#include "InstallNameToolOpts.inc" +#undef OPTTABLE_STR_TABLE_CODE -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_PREFIXES_TABLE_CODE #include "InstallNameToolOpts.inc" -#undef PREFIX +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InstallNameToolInfoTable[] = { #define OPTION(...) \ @@ -90,7 +94,9 @@ static constexpr opt::OptTable::Info InstallNameToolInfoTable[] = { class InstallNameToolOptTable : public opt::GenericOptTable { public: InstallNameToolOptTable() - : GenericOptTable(install_name_tool::InstallNameToolInfoTable) {} + : GenericOptTable(install_name_tool::OptionStrTable, + install_name_tool::OptionPrefixesTable, + install_name_tool::InstallNameToolInfoTable) {} }; enum BitcodeStripID { @@ -102,13 +108,13 @@ enum BitcodeStripID { }; namespace bitcode_strip { +#define OPTTABLE_STR_TABLE_CODE +#include "BitcodeStripOpts.inc" +#undef OPTTABLE_STR_TABLE_CODE -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_PREFIXES_TABLE_CODE #include "BitcodeStripOpts.inc" -#undef PREFIX +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info BitcodeStripInfoTable[] = { #define OPTION(...) \ @@ -121,7 +127,9 @@ static constexpr opt::OptTable::Info BitcodeStripInfoTable[] = { class BitcodeStripOptTable : public opt::GenericOptTable { public: BitcodeStripOptTable() - : opt::GenericOptTable(bitcode_strip::BitcodeStripInfoTable) {} + : opt::GenericOptTable(bitcode_strip::OptionStrTable, + bitcode_strip::OptionPrefixesTable, + bitcode_strip::BitcodeStripInfoTable) {} }; enum StripID { @@ -132,12 +140,13 @@ enum StripID { }; namespace strip { -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE +#include "StripOpts.inc" +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE #include "StripOpts.inc" -#undef PREFIX +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info StripInfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(STRIP_, __VA_ARGS__), @@ -148,7 +157,9 @@ static constexpr opt::OptTable::Info StripInfoTable[] = { class StripOptTable : public opt::GenericOptTable { public: - StripOptTable() : GenericOptTable(strip::StripInfoTable) { + StripOptTable() + : GenericOptTable(strip::OptionStrTable, strip::OptionPrefixesTable, + strip::StripInfoTable) { setGroupedShortOptions(true); } }; diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp index 5ac13495662f..d78cf485587e 100644 --- a/llvm/tools/llvm-objdump/ELFDump.cpp +++ b/llvm/tools/llvm-objdump/ELFDump.cpp @@ -17,7 +17,6 @@ #include "llvm/Demangle/Demangle.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/Format.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; diff --git a/llvm/tools/llvm-objdump/SourcePrinter.cpp b/llvm/tools/llvm-objdump/SourcePrinter.cpp index 600bd6aa4d51..061e4c0bd87c 100644 --- a/llvm/tools/llvm-objdump/SourcePrinter.cpp +++ b/llvm/tools/llvm-objdump/SourcePrinter.cpp @@ -15,10 +15,7 @@ #include "SourcePrinter.h" #include "llvm-objdump.h" #include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/StringSet.h" #include "llvm/DebugInfo/DWARF/DWARFExpression.h" -#include "llvm/DebugInfo/Symbolize/SymbolizableModule.h" -#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/FormatVariadic.h" #define DEBUG_TYPE "objdump" diff --git a/llvm/tools/llvm-objdump/XCOFFDump.cpp b/llvm/tools/llvm-objdump/XCOFFDump.cpp index 2e8a8c82b890..92f9ee4fb9f9 100644 --- a/llvm/tools/llvm-objdump/XCOFFDump.cpp +++ b/llvm/tools/llvm-objdump/XCOFFDump.cpp @@ -18,7 +18,6 @@ #include "llvm/Demangle/Demangle.h" #include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index 246d5cfa0581..93fed8ee8e6f 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -27,12 +27,10 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetOperations.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringSet.h" #include "llvm/ADT/Twine.h" #include "llvm/BinaryFormat/Wasm.h" #include "llvm/DebugInfo/BTF/BTFParser.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" -#include "llvm/DebugInfo/Symbolize/SymbolizableModule.h" #include "llvm/DebugInfo/Symbolize/Symbolize.h" #include "llvm/Debuginfod/BuildIDFetcher.h" #include "llvm/Debuginfod/Debuginfod.h" @@ -40,7 +38,6 @@ #include "llvm/Demangle/Demangle.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDisassembler/MCDisassembler.h" #include "llvm/MC/MCDisassembler/MCRelocationInfo.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstPrinter.h" @@ -50,7 +47,6 @@ #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCTargetOptions.h" #include "llvm/MC/TargetRegistry.h" -#include "llvm/Object/Archive.h" #include "llvm/Object/BuildID.h" #include "llvm/Object/COFF.h" #include "llvm/Object/COFFImportFile.h" @@ -59,7 +55,6 @@ #include "llvm/Object/FaultMapParser.h" #include "llvm/Object/MachO.h" #include "llvm/Object/MachOUniversal.h" -#include "llvm/Object/ObjectFile.h" #include "llvm/Object/OffloadBinary.h" #include "llvm/Object/Wasm.h" #include "llvm/Option/Arg.h" @@ -99,10 +94,11 @@ namespace { class CommonOptTable : public opt::GenericOptTable { public: - CommonOptTable(ArrayRef<Info> OptionInfos, const char *Usage, + CommonOptTable(const char *StrTable, ArrayRef<unsigned> PrefixesTable, + ArrayRef<Info> OptionInfos, const char *Usage, const char *Description) - : opt::GenericOptTable(OptionInfos), Usage(Usage), - Description(Description) { + : opt::GenericOptTable(StrTable, PrefixesTable, OptionInfos), + Usage(Usage), Description(Description) { setGroupedShortOptions(true); } @@ -121,12 +117,13 @@ private: // ObjdumpOptID is in ObjdumpOptID.h namespace objdump_opt { -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "ObjdumpOpts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "ObjdumpOpts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info ObjdumpInfoTable[] = { #define OPTION(...) \ @@ -139,9 +136,10 @@ static constexpr opt::OptTable::Info ObjdumpInfoTable[] = { class ObjdumpOptTable : public CommonOptTable { public: ObjdumpOptTable() - : CommonOptTable(objdump_opt::ObjdumpInfoTable, - " [options] <input object files>", - "llvm object file dumper") {} + : CommonOptTable( + objdump_opt::OptionStrTable, objdump_opt::OptionPrefixesTable, + objdump_opt::ObjdumpInfoTable, " [options] <input object files>", + "llvm object file dumper") {} }; enum OtoolOptID { @@ -152,12 +150,13 @@ enum OtoolOptID { }; namespace otool { -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE +#include "OtoolOpts.inc" +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE #include "OtoolOpts.inc" -#undef PREFIX +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info OtoolInfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(OTOOL_, __VA_ARGS__), @@ -169,7 +168,8 @@ static constexpr opt::OptTable::Info OtoolInfoTable[] = { class OtoolOptTable : public CommonOptTable { public: OtoolOptTable() - : CommonOptTable(otool::OtoolInfoTable, " [option...] [file...]", + : CommonOptTable(otool::OptionStrTable, otool::OptionPrefixesTable, + otool::OtoolInfoTable, " [option...] [file...]", "Mach-O object file displaying tool") {} }; diff --git a/llvm/tools/llvm-objdump/llvm-objdump.h b/llvm/tools/llvm-objdump/llvm-objdump.h index debaedd33429..7253cc3f4d91 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.h +++ b/llvm/tools/llvm-objdump/llvm-objdump.h @@ -15,8 +15,6 @@ #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ObjectFile.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/DataTypes.h" #include "llvm/Support/FormattedStream.h" #include <functional> #include <memory> diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp index 1d9d7bcf7654..ffc481f07185 100644 --- a/llvm/tools/llvm-profdata/llvm-profdata.cpp +++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp @@ -21,6 +21,7 @@ #include "llvm/ProfileData/InstrProfWriter.h" #include "llvm/ProfileData/MemProf.h" #include "llvm/ProfileData/MemProfReader.h" +#include "llvm/ProfileData/MemProfYAML.h" #include "llvm/ProfileData/ProfileCommon.h" #include "llvm/ProfileData/SampleProfReader.h" #include "llvm/ProfileData/SampleProfWriter.h" @@ -723,6 +724,43 @@ loadInput(const WeightedFile &Input, SymbolRemapper *Remapper, return; } + using ::llvm::memprof::YAMLMemProfReader; + if (YAMLMemProfReader::hasFormat(Input.Filename)) { + auto ReaderOrErr = YAMLMemProfReader::create(Input.Filename); + if (!ReaderOrErr) + exitWithError(ReaderOrErr.takeError(), Input.Filename); + std::unique_ptr<YAMLMemProfReader> Reader = std::move(ReaderOrErr.get()); + // Check if the profile types can be merged, e.g. clang frontend profiles + // should not be merged with memprof profiles. + if (Error E = WC->Writer.mergeProfileKind(Reader->getProfileKind())) { + consumeError(std::move(E)); + WC->Errors.emplace_back( + make_error<StringError>( + "Cannot merge MemProf profile with incompatible profile.", + std::error_code()), + Filename); + return; + } + + auto MemProfError = [&](Error E) { + auto [ErrorCode, Msg] = InstrProfError::take(std::move(E)); + WC->Errors.emplace_back(make_error<InstrProfError>(ErrorCode, Msg), + Filename); + }; + + auto MemProfData = Reader->takeMemProfData(); + + // Check for the empty input in case the YAML file is invalid. + if (MemProfData.Records.empty()) { + WC->Errors.emplace_back( + make_error<StringError>("The profile is empty.", std::error_code()), + Filename); + } + + WC->Writer.addMemProfData(std::move(MemProfData), MemProfError); + return; + } + auto FS = vfs::getRealFileSystem(); // TODO: This only saves the first non-fatal error from InstrProfReader, and // then added to WriterContext::Errors. However, this is not extensible, if @@ -3242,18 +3280,38 @@ static int showSampleProfile(ShowFormat SFormat, raw_fd_ostream &OS) { static int showMemProfProfile(ShowFormat SFormat, raw_fd_ostream &OS) { if (SFormat == ShowFormat::Json) exitWithError("JSON output is not supported for MemProf"); - auto ReaderOr = llvm::memprof::RawMemProfReader::create( - Filename, ProfiledBinary, /*KeepNames=*/true); - if (Error E = ReaderOr.takeError()) - // Since the error can be related to the profile or the binary we do not - // pass whence. Instead additional context is provided where necessary in - // the error message. - exitWithError(std::move(E), /*Whence*/ ""); - - std::unique_ptr<llvm::memprof::RawMemProfReader> Reader( - ReaderOr.get().release()); - - Reader->printYAML(OS); + + // Show the raw profile in YAML. + if (memprof::RawMemProfReader::hasFormat(Filename)) { + auto ReaderOr = llvm::memprof::RawMemProfReader::create( + Filename, ProfiledBinary, /*KeepNames=*/true); + if (Error E = ReaderOr.takeError()) { + // Since the error can be related to the profile or the binary we do not + // pass whence. Instead additional context is provided where necessary in + // the error message. + exitWithError(std::move(E), /*Whence*/ ""); + } + + std::unique_ptr<llvm::memprof::RawMemProfReader> Reader( + ReaderOr.get().release()); + + Reader->printYAML(OS); + return 0; + } + + // Show the indexed MemProf profile in YAML. + auto FS = vfs::getRealFileSystem(); + auto ReaderOrErr = IndexedInstrProfReader::create(Filename, *FS); + if (Error E = ReaderOrErr.takeError()) + exitWithError(std::move(E), Filename); + + auto Reader = std::move(ReaderOrErr.get()); + memprof::AllMemProfData Data = Reader->getAllMemProfData(); + // Construct yaml::Output with the maximum column width of 80 so that each + // Frame fits in one line. + yaml::Output Yout(OS, nullptr, 80); + Yout << Data; + return 0; } diff --git a/llvm/tools/llvm-rc/llvm-rc.cpp b/llvm/tools/llvm-rc/llvm-rc.cpp index 4bc9d9009557..a77188c462af 100644 --- a/llvm/tools/llvm-rc/llvm-rc.cpp +++ b/llvm/tools/llvm-rc/llvm-rc.cpp @@ -57,12 +57,13 @@ enum ID { }; namespace rc_opt { -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -73,7 +74,10 @@ static constexpr opt::OptTable::Info InfoTable[] = { class RcOptTable : public opt::GenericOptTable { public: - RcOptTable() : GenericOptTable(rc_opt::InfoTable, /* IgnoreCase = */ true) {} + RcOptTable() + : GenericOptTable(rc_opt::OptionStrTable, rc_opt::OptionPrefixesTable, + rc_opt::InfoTable, + /* IgnoreCase = */ true) {} }; enum Windres_ID { @@ -84,12 +88,13 @@ enum Windres_ID { }; namespace windres_opt { -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE +#include "WindresOpts.inc" +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE #include "WindresOpts.inc" -#undef PREFIX +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) \ @@ -102,7 +107,10 @@ static constexpr opt::OptTable::Info InfoTable[] = { class WindresOptTable : public opt::GenericOptTable { public: WindresOptTable() - : GenericOptTable(windres_opt::InfoTable, /* IgnoreCase = */ false) {} + : GenericOptTable(windres_opt::OptionStrTable, + windres_opt::OptionPrefixesTable, + windres_opt::InfoTable, + /* IgnoreCase = */ false) {} }; static ExitOnError ExitOnErr; diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index bb8ec41d8745..bfca65aad52b 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -6057,6 +6057,7 @@ const NoteType CoreNoteTypes[] = { {ELF::NT_ARM_ZA, "NT_ARM_ZA (AArch64 SME ZA registers)"}, {ELF::NT_ARM_ZT, "NT_ARM_ZT (AArch64 SME ZT registers)"}, {ELF::NT_ARM_FPMR, "NT_ARM_FPMR (AArch64 Floating Point Mode Register)"}, + {ELF::NT_ARM_GCS, "NT_ARM_GCS (AArch64 Guarded Control Stack state)"}, {ELF::NT_FILE, "NT_FILE (mapped files)"}, {ELF::NT_PRXFPREG, "NT_PRXFPREG (user_xfpregs structure)"}, diff --git a/llvm/tools/llvm-readobj/XCOFFDumper.cpp b/llvm/tools/llvm-readobj/XCOFFDumper.cpp index 46b510cfb06a..6a099c08e1ac 100644 --- a/llvm/tools/llvm-readobj/XCOFFDumper.cpp +++ b/llvm/tools/llvm-readobj/XCOFFDumper.cpp @@ -723,7 +723,12 @@ const EnumEntry<XCOFF::CFileLangId> CFileLangIdClass[] = { const EnumEntry<XCOFF::CFileCpuId> CFileCpuIdClass[] = { #define ECase(X) \ { #X, XCOFF::X } - ECase(TCPU_PPC64), ECase(TCPU_COM), ECase(TCPU_970) + ECase(TCPU_INVALID), ECase(TCPU_PPC), ECase(TCPU_PPC64), ECase(TCPU_COM), + ECase(TCPU_PWR), ECase(TCPU_ANY), ECase(TCPU_601), ECase(TCPU_603), + ECase(TCPU_604), ECase(TCPU_620), ECase(TCPU_A35), ECase(TCPU_970), + ECase(TCPU_PWR5), ECase(TCPU_PWR6), ECase(TCPU_PWR5X), ECase(TCPU_PWR6E), + ECase(TCPU_PWR7), ECase(TCPU_PWR8), ECase(TCPU_PWR9), ECase(TCPU_PWR10), + ECase(TCPU_PWRX) #undef ECase }; diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp index 3e76cda2dd43..2f77e5d35055 100644 --- a/llvm/tools/llvm-readobj/llvm-readobj.cpp +++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -59,12 +59,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -74,7 +75,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class ReadobjOptTable : public opt::GenericOptTable { public: - ReadobjOptTable() : opt::GenericOptTable(InfoTable) { + ReadobjOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) { setGroupedShortOptions(true); } }; diff --git a/llvm/tools/llvm-readtapi/llvm-readtapi.cpp b/llvm/tools/llvm-readtapi/llvm-readtapi.cpp index 04282d3e4877..b5574ea41e33 100644 --- a/llvm/tools/llvm-readtapi/llvm-readtapi.cpp +++ b/llvm/tools/llvm-readtapi/llvm-readtapi.cpp @@ -45,12 +45,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "TapiOpts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "TapiOpts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -60,7 +61,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class TAPIOptTable : public opt::GenericOptTable { public: - TAPIOptTable() : opt::GenericOptTable(InfoTable) { + TAPIOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) { setGroupedShortOptions(true); } }; diff --git a/llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.cpp b/llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.cpp index 5f0697f5aaad..40bc6b180fb8 100644 --- a/llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.cpp +++ b/llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.cpp @@ -65,7 +65,7 @@ static bool shouldNotRemoveInstruction(const TargetInstrInfo &TII, static void extractInstrFromFunction(Oracle &O, MachineFunction &MF) { MachineDominatorTree MDT; - MDT.calculate(MF); + MDT.recalculate(MF); auto MRI = &MF.getRegInfo(); SetVector<MachineInstr *> ToDelete; diff --git a/llvm/tools/llvm-size/llvm-size.cpp b/llvm/tools/llvm-size/llvm-size.cpp index 4a1b0e879036..0d7bf2483267 100644 --- a/llvm/tools/llvm-size/llvm-size.cpp +++ b/llvm/tools/llvm-size/llvm-size.cpp @@ -45,12 +45,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -60,7 +61,10 @@ static constexpr opt::OptTable::Info InfoTable[] = { class SizeOptTable : public opt::GenericOptTable { public: - SizeOptTable() : GenericOptTable(InfoTable) { setGroupedShortOptions(true); } + SizeOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) { + setGroupedShortOptions(true); + } }; enum OutputFormatTy { berkeley, sysv, darwin }; diff --git a/llvm/tools/llvm-split/llvm-split.cpp b/llvm/tools/llvm-split/llvm-split.cpp index c456403e6bc6..1b1f97f44e27 100644 --- a/llvm/tools/llvm-split/llvm-split.cpp +++ b/llvm/tools/llvm-split/llvm-split.cpp @@ -67,7 +67,7 @@ static cl::opt<std::string> cl::value_desc("triple"), cl::cat(SplitCategory)); static cl::opt<std::string> - MCPU("mcpu", cl::desc("Target CPU, ignored if -mtriple is not used"), + MCPU("mcpu", cl::desc("Target CPU, ignored if --mtriple is not used"), cl::value_desc("cpu"), cl::cat(SplitCategory)); int main(int argc, char **argv) { @@ -125,11 +125,11 @@ int main(int argc, char **argv) { if (TM) { if (PreserveLocals) { - errs() << "warning: -preserve-locals has no effect when using " + errs() << "warning: --preserve-locals has no effect when using " "TargetMachine::splitModule\n"; } if (RoundRobin) - errs() << "warning: -round-robin has no effect when using " + errs() << "warning: --round-robin has no effect when using " "TargetMachine::splitModule\n"; if (TM->splitModule(*M, NumOutputs, HandleModulePart)) diff --git a/llvm/tools/llvm-strings/llvm-strings.cpp b/llvm/tools/llvm-strings/llvm-strings.cpp index d4305096b60a..9979b93de842 100644 --- a/llvm/tools/llvm-strings/llvm-strings.cpp +++ b/llvm/tools/llvm-strings/llvm-strings.cpp @@ -38,12 +38,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -54,7 +55,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class StringsOptTable : public opt::GenericOptTable { public: - StringsOptTable() : GenericOptTable(InfoTable) { + StringsOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) { setGroupedShortOptions(true); setDashDashParsing(true); } diff --git a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp index 3e41a85d6469..3ba7f59d5b84 100644 --- a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp +++ b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -56,12 +56,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -72,7 +73,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class SymbolizerOptTable : public opt::GenericOptTable { public: - SymbolizerOptTable() : GenericOptTable(InfoTable) { + SymbolizerOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) { setGroupedShortOptions(true); } }; diff --git a/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp b/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp index a091e37ff402..ca0b42472219 100644 --- a/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp +++ b/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp @@ -33,12 +33,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -49,7 +50,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class TLICheckerOptTable : public opt::GenericOptTable { public: - TLICheckerOptTable() : GenericOptTable(InfoTable) {} + TLICheckerOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; } // end anonymous namespace diff --git a/llvm/tools/sancov/sancov.cpp b/llvm/tools/sancov/sancov.cpp index 39feff62391f..727b94b8477c 100644 --- a/llvm/tools/sancov/sancov.cpp +++ b/llvm/tools/sancov/sancov.cpp @@ -67,12 +67,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -82,7 +83,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class SancovOptTable : public opt::GenericOptTable { public: - SancovOptTable() : GenericOptTable(InfoTable) {} + SancovOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; } // namespace |
