diff options
Diffstat (limited to 'llvm/tools')
37 files changed, 643 insertions, 242 deletions
diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp index 83473704398d..f6a35708dc07 100644 --- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp +++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp @@ -147,7 +147,7 @@ DwarfLinkerForBinary::loadObject(const DebugMapObject &Obj, if (!ObjectEntry) { auto Err = ObjectEntry.takeError(); reportWarning(Twine(Obj.getObjectFilename()) + ": " + - toString(std::move(Err)), + toStringWithoutConsuming(Err), Obj.getObjectFilename()); return errorToErrorCode(std::move(Err)); } @@ -156,7 +156,7 @@ DwarfLinkerForBinary::loadObject(const DebugMapObject &Obj, if (!Object) { auto Err = Object.takeError(); reportWarning(Twine(Obj.getObjectFilename()) + ": " + - toString(std::move(Err)), + toStringWithoutConsuming(Err), Obj.getObjectFilename()); return errorToErrorCode(std::move(Err)); } diff --git a/llvm/tools/dsymutil/MachOUtils.cpp b/llvm/tools/dsymutil/MachOUtils.cpp index 8e144d640ed0..e2ec8cae2285 100644 --- a/llvm/tools/dsymutil/MachOUtils.cpp +++ b/llvm/tools/dsymutil/MachOUtils.cpp @@ -381,7 +381,6 @@ bool generateDsymCompanion( auto &Writer = static_cast<MachObjectWriter &>(MCAsm.getWriter()); // Layout but don't emit. - ObjectStreamer.flushPendingLabels(); MCAsmLayout Layout(MCAsm); MCAsm.layout(Layout); @@ -630,9 +629,6 @@ bool generateDsymCompanion( // Emit the Dwarf sections contents. for (const MCSection &Sec : MCAsm) { - if (Sec.begin() == Sec.end()) - continue; - uint64_t Pos = OutFile.tell(); OutFile.write_zeros(alignTo(Pos, Sec.getAlign()) - Pos); MCAsm.writeSectionData(OutFile, &Sec, Layout); diff --git a/llvm/tools/gold/gold-plugin.cpp b/llvm/tools/gold/gold-plugin.cpp index 265ebcbff587..0b175a3852e4 100644 --- a/llvm/tools/gold/gold-plugin.cpp +++ b/llvm/tools/gold/gold-plugin.cpp @@ -307,7 +307,8 @@ namespace options { } else if (opt.consume_front("opt-remarks-hotness-threshold=")) { auto ResultOrErr = remarks::parseHotnessThresholdOption(opt); if (!ResultOrErr) - message(LDPL_FATAL, "Invalid remarks hotness threshold: %s", opt); + message(LDPL_FATAL, "Invalid remarks hotness threshold: %s", + opt.data()); else RemarksHotnessThreshold = *ResultOrErr; } else if (opt.consume_front("opt-remarks-format=")) { @@ -319,7 +320,7 @@ namespace options { } else if (opt.consume_front("time-trace-granularity=")) { unsigned Granularity; if (opt.getAsInteger(10, Granularity)) - message(LDPL_FATAL, "Invalid time trace granularity: %s", opt); + message(LDPL_FATAL, "Invalid time trace granularity: %s", opt.data()); else time_trace_granularity = Granularity; } else { diff --git a/llvm/tools/llvm-as/llvm-as.cpp b/llvm/tools/llvm-as/llvm-as.cpp index e48e3f4d22c1..082565a9ef3d 100644 --- a/llvm/tools/llvm-as/llvm-as.cpp +++ b/llvm/tools/llvm-as/llvm-as.cpp @@ -67,6 +67,7 @@ static cl::opt<std::string> ClDataLayout("data-layout", cl::desc("data layout string to use"), cl::value_desc("layout-string"), cl::init(""), cl::cat(AsCat)); +extern cl::opt<bool> UseNewDbgInfoFormat; extern bool WriteNewDbgInfoFormatToBitcode; static void WriteOutputFile(const Module *M, const ModuleSummaryIndex *Index) { @@ -142,11 +143,10 @@ int main(int argc, char **argv) { } // Convert to new debug format if requested. - assert(!M->IsNewDbgInfoFormat && "Unexpectedly in new debug mode"); - if (UseNewDbgInfoFormat && WriteNewDbgInfoFormatToBitcode) { - M->convertToNewDbgValues(); + M->setIsNewDbgInfoFormat(UseNewDbgInfoFormat && + WriteNewDbgInfoFormatToBitcode); + if (M->IsNewDbgInfoFormat) M->removeDebugIntrinsicDeclarations(); - } std::unique_ptr<ModuleSummaryIndex> Index = std::move(ModuleAndIndex.Index); diff --git a/llvm/tools/llvm-c-test/debuginfo.c b/llvm/tools/llvm-c-test/debuginfo.c index 35c65f885af3..49c90f5b87b8 100644 --- a/llvm/tools/llvm-c-test/debuginfo.c +++ b/llvm/tools/llvm-c-test/debuginfo.c @@ -29,10 +29,13 @@ declare_objc_class(LLVMDIBuilderRef DIB, LLVMMetadataRef File) { return Decl; } -int llvm_test_dibuilder(bool NewDebugInfoFormat) { +int llvm_test_dibuilder(void) { const char *Filename = "debuginfo.c"; LLVMModuleRef M = LLVMModuleCreateWithName(Filename); - LLVMSetIsNewDbgInfoFormat(M, NewDebugInfoFormat); + + LLVMSetIsNewDbgInfoFormat(M, true); + assert(LLVMIsNewDbgInfoFormat(M)); + LLVMDIBuilderRef DIB = LLVMCreateDIBuilder(M); LLVMMetadataRef File = LLVMDIBuilderCreateFile(DIB, Filename, @@ -137,38 +140,24 @@ int llvm_test_dibuilder(bool NewDebugInfoFormat) { LLVMDIBuilderCreateParameterVariable(DIB, FunctionMetadata, "a", 1, 1, File, 42, Int64Ty, true, 0); - if (LLVMIsNewDbgInfoFormat(M)) - LLVMDIBuilderInsertDeclareAtEnd( - DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar1, - FooParamExpression, FooParamLocation, FooEntryBlock); - else - LLVMDIBuilderInsertDeclareIntrinsicAtEnd( - DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar1, - FooParamExpression, FooParamLocation, FooEntryBlock); + LLVMDIBuilderInsertDeclareRecordAtEnd( + DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar1, + FooParamExpression, FooParamLocation, FooEntryBlock); + LLVMMetadataRef FooParamVar2 = LLVMDIBuilderCreateParameterVariable(DIB, FunctionMetadata, "b", 1, 2, File, 42, Int64Ty, true, 0); - if (LLVMIsNewDbgInfoFormat(M)) - LLVMDIBuilderInsertDeclareAtEnd( - DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar2, - FooParamExpression, FooParamLocation, FooEntryBlock); - else - LLVMDIBuilderInsertDeclareIntrinsicAtEnd( - DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar2, - FooParamExpression, FooParamLocation, FooEntryBlock); - - LLVMMetadataRef FooParamVar3 = - LLVMDIBuilderCreateParameterVariable(DIB, FunctionMetadata, "c", 1, 3, File, - 42, VectorTy, true, 0); - if (LLVMIsNewDbgInfoFormat(M)) - LLVMDIBuilderInsertDeclareAtEnd( - DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar3, - FooParamExpression, FooParamLocation, FooEntryBlock); - else - LLVMDIBuilderInsertDeclareIntrinsicAtEnd( - DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar3, - FooParamExpression, FooParamLocation, FooEntryBlock); + LLVMDIBuilderInsertDeclareRecordAtEnd( + DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar2, + FooParamExpression, FooParamLocation, FooEntryBlock); + + LLVMMetadataRef FooParamVar3 = LLVMDIBuilderCreateParameterVariable( + DIB, FunctionMetadata, "c", 1, 3, File, 42, VectorTy, true, 0); + + LLVMDIBuilderInsertDeclareRecordAtEnd( + DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar3, + FooParamExpression, FooParamLocation, FooEntryBlock); LLVMSetSubprogram(FooFunction, FunctionMetadata); @@ -185,12 +174,9 @@ int llvm_test_dibuilder(bool NewDebugInfoFormat) { LLVMValueRef FooVal1 = LLVMConstInt(LLVMInt64Type(), 0, false); LLVMMetadataRef FooVarValueExpr = LLVMDIBuilderCreateConstantValueExpression(DIB, 0); - if (LLVMIsNewDbgInfoFormat(M)) - LLVMDIBuilderInsertDbgValueRecordAtEnd( - DIB, FooVal1, FooVar1, FooVarValueExpr, FooVarsLocation, FooVarBlock); - else - LLVMDIBuilderInsertDbgValueIntrinsicAtEnd( - DIB, FooVal1, FooVar1, FooVarValueExpr, FooVarsLocation, FooVarBlock); + + LLVMDIBuilderInsertDbgValueRecordAtEnd(DIB, FooVal1, FooVar1, FooVarValueExpr, + FooVarsLocation, FooVarBlock); LLVMMetadataRef MacroFile = LLVMDIBuilderCreateTempMacroFile(DIB, NULL, 0, File); @@ -228,7 +214,24 @@ int llvm_test_dibuilder(bool NewDebugInfoFormat) { LLVMPositionBuilderAtEnd(Builder, FooVarBlock); LLVMTypeRef I64 = LLVMInt64TypeInContext(Ctx); LLVMValueRef Zero = LLVMConstInt(I64, 0, false); - LLVMBuildRet(Builder, Zero); + LLVMValueRef Ret = LLVMBuildRet(Builder, Zero); + + // Insert a `phi` before the `ret`. In the new debug info mode we need to + // be careful to insert before debug records too, else the debug records + // will come before the `phi` (and be absorbed onto it) which is an invalid + // state. + LLVMValueRef InsertPos = LLVMGetFirstInstruction(FooVarBlock); + LLVMPositionBuilderBeforeInstrAndDbgRecords(Builder, InsertPos); + LLVMValueRef Phi1 = LLVMBuildPhi(Builder, I64, "p1"); + LLVMAddIncoming(Phi1, &Zero, &FooEntryBlock, 1); + // Do the same again using the other position-setting function. + LLVMPositionBuilderBeforeDbgRecords(Builder, FooVarBlock, InsertPos); + LLVMValueRef Phi2 = LLVMBuildPhi(Builder, I64, "p2"); + LLVMAddIncoming(Phi2, &Zero, &FooEntryBlock, 1); + // Insert a non-phi before the `ret` but not before the debug records to + // test that works as expected. + LLVMPositionBuilder(Builder, FooVarBlock, Ret); + LLVMBuildAdd(Builder, Phi1, Phi2, "a"); char *MStr = LLVMPrintModuleToString(M); puts(MStr); diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp index 518716168c42..6fa36421810f 100644 --- a/llvm/tools/llvm-c-test/echo.cpp +++ b/llvm/tools/llvm-c-test/echo.cpp @@ -157,8 +157,26 @@ struct TypeCloner { return LLVMX86MMXTypeInContext(Ctx); case LLVMTokenTypeKind: return LLVMTokenTypeInContext(Ctx); - case LLVMTargetExtTypeKind: - assert(false && "Implement me"); + case LLVMTargetExtTypeKind: { + const char *Name = LLVMGetTargetExtTypeName(Src); + unsigned NumTypeParams = LLVMGetTargetExtTypeNumTypeParams(Src); + unsigned NumIntParams = LLVMGetTargetExtTypeNumIntParams(Src); + + SmallVector<LLVMTypeRef, 4> TypeParams((size_t)NumTypeParams); + SmallVector<unsigned, 4> IntParams((size_t)NumIntParams); + + for (unsigned i = 0; i < TypeParams.size(); i++) + TypeParams[i] = Clone(LLVMGetTargetExtTypeTypeParam(Src, i)); + + for (unsigned i = 0; i < IntParams.size(); i++) + IntParams[i] = LLVMGetTargetExtTypeIntParam(Src, i); + + LLVMTypeRef TargetExtTy = LLVMTargetExtTypeInContext( + Ctx, Name, TypeParams.data(), TypeParams.size(), IntParams.data(), + IntParams.size()); + + return TargetExtTy; + } } fprintf(stderr, "%d is not a supported typekind\n", Kind); diff --git a/llvm/tools/llvm-c-test/llvm-c-test.h b/llvm/tools/llvm-c-test/llvm-c-test.h index c50d3cce8674..00566660257e 100644 --- a/llvm/tools/llvm-c-test/llvm-c-test.h +++ b/llvm/tools/llvm-c-test/llvm-c-test.h @@ -36,7 +36,7 @@ int llvm_calc(void); int llvm_disassemble(void); // debuginfo.c -int llvm_test_dibuilder(bool NewDebugInfoFormat); +int llvm_test_dibuilder(void); int llvm_get_di_tag(void); int llvm_di_type_get_name(void); diff --git a/llvm/tools/llvm-c-test/main.c b/llvm/tools/llvm-c-test/main.c index 9db6e05d6350..8be9ea06fc68 100644 --- a/llvm/tools/llvm-c-test/main.c +++ b/llvm/tools/llvm-c-test/main.c @@ -110,11 +110,8 @@ int main(int argc, char **argv) { } else if (argc == 2 && !strcmp(argv[1], "--test-diagnostic-handler")) { return llvm_test_diagnostic_handler(); } else if (argc == 2 && - !strcmp(argv[1], "--test-dibuilder-old-debuginfo-format")) { - return llvm_test_dibuilder(false); - } else if (argc == 2 && - !strcmp(argv[1], "--test-dibuilder-new-debuginfo-format")) { - return llvm_test_dibuilder(true); + !strcmp(argv[1], "--test-dibuilder-debuginfo-format")) { + return llvm_test_dibuilder(); } else { print_usage(); } diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp index 1e5bfbe5c3aa..75028ac0bb50 100644 --- a/llvm/tools/llvm-cov/CodeCoverage.cpp +++ b/llvm/tools/llvm-cov/CodeCoverage.cpp @@ -515,7 +515,7 @@ void CodeCoverageTool::remapPathNames(const CoverageMapping &Coverage) { if (!PathRemappings) return; - // Convert remapping paths to native paths with trailing seperators. + // Convert remapping paths to native paths with trailing separators. auto nativeWithTrailing = [](StringRef Path) -> std::string { if (Path.empty()) return ""; diff --git a/llvm/tools/llvm-cov/CoverageReport.cpp b/llvm/tools/llvm-cov/CoverageReport.cpp index 49a35f2a943e..00aea4039bfd 100644 --- a/llvm/tools/llvm-cov/CoverageReport.cpp +++ b/llvm/tools/llvm-cov/CoverageReport.cpp @@ -102,8 +102,25 @@ void adjustColumnWidths(ArrayRef<StringRef> Files, /// Prints a horizontal divider long enough to cover the given column /// widths. -void renderDivider(ArrayRef<size_t> ColumnWidths, raw_ostream &OS) { - size_t Length = std::accumulate(ColumnWidths.begin(), ColumnWidths.end(), 0); +void renderDivider(raw_ostream &OS, const CoverageViewOptions &Options, bool isFileReport) { + size_t Length; + if (isFileReport) { + Length = std::accumulate(std::begin(FileReportColumns), std::end(FileReportColumns), 0); + if (!Options.ShowRegionSummary) + Length -= (FileReportColumns[1] + FileReportColumns[2] + FileReportColumns[3]); + if (!Options.ShowInstantiationSummary) + Length -= (FileReportColumns[7] + FileReportColumns[8] + FileReportColumns[9]); + if (!Options.ShowBranchSummary) + Length -= (FileReportColumns[13] + FileReportColumns[14] + FileReportColumns[15]); + if (!Options.ShowMCDCSummary) + Length -= (FileReportColumns[16] + FileReportColumns[17] + FileReportColumns[18]); + } else { + Length = std::accumulate(std::begin(FunctionReportColumns), std::end(FunctionReportColumns), 0); + if (!Options.ShowBranchSummary) + Length -= (FunctionReportColumns[7] + FunctionReportColumns[8] + FunctionReportColumns[9]); + if (!Options.ShowMCDCSummary) + Length -= (FunctionReportColumns[10] + FunctionReportColumns[11] + FunctionReportColumns[12]); + } for (size_t I = 0; I < Length; ++I) OS << '-'; } @@ -405,7 +422,7 @@ void CoverageReport::renderFunctionReports(ArrayRef<std::string> Files, << column("Miss", FunctionReportColumns[11], Column::RightAlignment) << column("Cover", FunctionReportColumns[12], Column::RightAlignment); OS << "\n"; - renderDivider(FunctionReportColumns, OS); + renderDivider(OS, Options, false); OS << "\n"; FunctionCoverageSummary Totals("TOTAL"); for (const auto &F : Functions) { @@ -418,7 +435,7 @@ void CoverageReport::renderFunctionReports(ArrayRef<std::string> Files, render(Function, DC, OS); } if (Totals.ExecutionCount) { - renderDivider(FunctionReportColumns, OS); + renderDivider(OS, Options, false); OS << "\n"; render(Totals, DC, OS); } @@ -544,7 +561,7 @@ void CoverageReport::renderFileReports( Column::RightAlignment) << column("Cover", FileReportColumns[18], Column::RightAlignment); OS << "\n"; - renderDivider(FileReportColumns, OS); + renderDivider(OS, Options, true); OS << "\n"; std::vector<const FileCoverageSummary *> EmptyFiles; @@ -563,7 +580,7 @@ void CoverageReport::renderFileReports( render(*FCS, OS); } - renderDivider(FileReportColumns, OS); + renderDivider(OS, Options, true); OS << "\n"; render(Totals, OS); } diff --git a/llvm/tools/llvm-cov/SourceCoverageView.cpp b/llvm/tools/llvm-cov/SourceCoverageView.cpp index 45bddd728446..ce55e3abf23b 100644 --- a/llvm/tools/llvm-cov/SourceCoverageView.cpp +++ b/llvm/tools/llvm-cov/SourceCoverageView.cpp @@ -203,8 +203,7 @@ void SourceCoverageView::print(raw_ostream &OS, bool WholeFile, if (ShowSourceName) renderSourceName(OS, WholeFile); - renderTableHeader(OS, (ViewDepth > 0) ? 0 : getFirstUncoveredLineNo(), - ViewDepth); + renderTableHeader(OS, ViewDepth); // We need the expansions, instantiations, and branches sorted so we can go // through them while we iterate lines. diff --git a/llvm/tools/llvm-cov/SourceCoverageView.h b/llvm/tools/llvm-cov/SourceCoverageView.h index a874f7c6820d..d255f8c200b2 100644 --- a/llvm/tools/llvm-cov/SourceCoverageView.h +++ b/llvm/tools/llvm-cov/SourceCoverageView.h @@ -262,8 +262,7 @@ protected: virtual void renderTitle(raw_ostream &OS, StringRef CellText) = 0; /// Render the table header for a given source file. - virtual void renderTableHeader(raw_ostream &OS, unsigned FirstUncoveredLineNo, - unsigned IndentLevel) = 0; + virtual void renderTableHeader(raw_ostream &OS, unsigned IndentLevel) = 0; /// @} diff --git a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp index d4b2ea3594fc..6f4d327679d6 100644 --- a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp +++ b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp @@ -88,6 +88,113 @@ const char *BeginHeader = "<meta name='viewport' content='width=device-width,initial-scale=1'>" "<meta charset='UTF-8'>"; +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"}); + } + + } + + 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 { + 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 + return last; + } else { + return undefined; + } + } + } + + 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) { + next_uncovered("td.uncovered-line", reverse) +} + +function next_region(reverse) { + next_uncovered("span.red.region", 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); + } + if (event.code == "KeyB") { + next_branch(reverse); + } + if (event.code == "KeyR") { + next_region(reverse); + } + +}); +)javascript"; + const char *CSSForCoverage = R"(.red { background-color: #f004; @@ -95,6 +202,9 @@ const char *CSSForCoverage = .cyan { background-color: cyan; } +html { + scroll-behavior: smooth; +} body { font-family: -apple-system, sans-serif; } @@ -171,6 +281,18 @@ table { text-align: right; color: #d00; } +.uncovered-line.selected { + color: #f00; + font-weight: bold; +} +.region.red.selected { + background-color: #f008; + font-weight: bold; +} +.branch.red.selected { + background-color: #f008; + font-weight: bold; +} .tooltip { position: relative; display: inline; @@ -231,12 +353,19 @@ tr:hover { tr:last-child { border-bottom: none; } -tr:has(> td >a:target) { - background-color: #50f6; +tr:has(> td >a:target), tr:has(> td.uncovered-line.selected) { + background-color: #8884; } a { color: inherit; } +.control { + position: fixed; + top: 0em; + right: 0em; + padding: 1em; + background: #FFF8; +} @media (prefers-color-scheme: dark) { body { background-color: #222; @@ -254,6 +383,12 @@ a { .tooltip { background-color: #068; } + .control { + background: #2228; + } + tr:has(> td >a:target), tr:has(> td.uncovered-line.selected) { + background-color: #8884; + } } )"; @@ -298,8 +433,18 @@ std::string getPathToStyle(StringRef ViewPath) { return PathToStyle + "style.css"; } +std::string getPathToJavaScript(StringRef ViewPath) { + std::string PathToJavaScript; + std::string PathSep = std::string(sys::path::get_separator()); + unsigned NumSeps = ViewPath.count(PathSep); + for (unsigned I = 0, E = NumSeps; I < E; ++I) + PathToJavaScript += ".." + PathSep; + return PathToJavaScript + "control.js"; +} + void emitPrelude(raw_ostream &OS, const CoverageViewOptions &Opts, - const std::string &PathToStyle = "") { + const std::string &PathToStyle = "", + const std::string &PathToJavaScript = "") { OS << "<!doctype html>" "<html>" << BeginHeader; @@ -311,6 +456,12 @@ void emitPrelude(raw_ostream &OS, const CoverageViewOptions &Opts, OS << "<link rel='stylesheet' type='text/css' href='" << escape(PathToStyle, Opts) << "'>"; + // Link to a JavaScript if one is available + if (PathToJavaScript.empty()) + OS << "<script>" << JSForCoverage << "</script>"; + else + OS << "<script src='" << escape(PathToJavaScript, Opts) << "'></script>"; + OS << EndHeader << "<body>"; } @@ -390,7 +541,8 @@ CoveragePrinterHTML::createViewFile(StringRef Path, bool InToplevel) { emitPrelude(*OS.get(), Opts); } else { std::string ViewPath = getOutputPath(Path, "html", InToplevel); - emitPrelude(*OS.get(), Opts, getPathToStyle(ViewPath)); + emitPrelude(*OS.get(), Opts, getPathToStyle(ViewPath), + getPathToJavaScript(ViewPath)); } return std::move(OS); @@ -442,6 +594,17 @@ Error CoveragePrinterHTML::emitStyleSheet() { return Error::success(); } +Error CoveragePrinterHTML::emitJavaScript() { + auto JSOrErr = createOutputStream("control", "js", /*InToplevel=*/true); + if (Error E = JSOrErr.takeError()) + return E; + + OwnedStream JS = std::move(JSOrErr.get()); + JS->operator<<(JSForCoverage); + + return Error::success(); +} + void CoveragePrinterHTML::emitReportHeader(raw_ostream &OSRef, const std::string &Title) { // Emit some basic information about the coverage report. @@ -487,6 +650,10 @@ Error CoveragePrinterHTML::createIndexFile( if (Error E = emitStyleSheet()) return E; + // Emit the JavaScript UI implementation + if (Error E = emitJavaScript()) + return E; + // Emit a file index along with some coverage statistics. auto OSOrErr = createOutputStream("index", "html", /*InToplevel=*/true); if (Error E = OSOrErr.takeError()) @@ -495,7 +662,7 @@ Error CoveragePrinterHTML::createIndexFile( raw_ostream &OSRef = *OS.get(); assert(Opts.hasOutputDirectory() && "No output directory for index file"); - emitPrelude(OSRef, Opts, getPathToStyle("")); + emitPrelude(OSRef, Opts, getPathToStyle(""), getPathToJavaScript("")); emitReportHeader(OSRef, "Coverage Report"); @@ -561,7 +728,8 @@ struct CoveragePrinterHTMLDirectory::Reporter : public DirectoryCoverageReport { auto IndexHtmlPath = Printer.getOutputPath((LCPath + "index").str(), "html", /*InToplevel=*/false); - emitPrelude(OSRef, Options, getPathToStyle(IndexHtmlPath)); + emitPrelude(OSRef, Options, getPathToStyle(IndexHtmlPath), + getPathToJavaScript(IndexHtmlPath)); auto NavLink = buildTitleLinks(LCPath); Printer.emitReportHeader(OSRef, "Coverage Report (" + NavLink + ")"); @@ -699,6 +867,10 @@ Error CoveragePrinterHTMLDirectory::createIndexFile( if (Error E = emitStyleSheet()) return E; + // Emit the JavaScript UI implementation + if (Error E = emitJavaScript()) + return E; + // Emit index files in every subdirectory. Reporter Report(*this, Coverage, Filters); auto TotalsOrErr = Report.prepareDirectoryReports(SourceFiles); @@ -800,7 +972,10 @@ void SourceCoverageViewHTML::renderLine(raw_ostream &OS, LineRef L, auto Highlight = [&](const std::string &Snippet, unsigned LC, unsigned RC) { if (getOptions().Debug) HighlightedRanges.emplace_back(LC, RC); - return tag("span", Snippet, std::string(*Color)); + if (Snippet.empty()) + return tag("span", Snippet, std::string(*Color)); + else + return tag("span", Snippet, "region " + std::string(*Color)); }; auto CheckIfUncovered = [&](const CoverageSegment *S) { @@ -883,7 +1058,9 @@ void SourceCoverageViewHTML::renderLineCoverageColumn( if (Line.isMapped()) Count = tag("pre", formatCount(Line.getExecutionCount())); std::string CoverageClass = - (Line.getExecutionCount() > 0) ? "covered-line" : "uncovered-line"; + (Line.getExecutionCount() > 0) + ? "covered-line" + : (Line.isMapped() ? "uncovered-line" : "skipped-line"); OS << tag("td", Count, CoverageClass); } @@ -957,7 +1134,7 @@ void SourceCoverageViewHTML::renderBranchView(raw_ostream &OS, BranchView &BRV, } // Display TrueCount or TruePercent. - std::string TrueColor = R.ExecutionCount ? "None" : "red"; + std::string TrueColor = R.ExecutionCount ? "None" : "red branch"; std::string TrueCovClass = (R.ExecutionCount > 0) ? "covered-line" : "uncovered-line"; @@ -969,7 +1146,7 @@ void SourceCoverageViewHTML::renderBranchView(raw_ostream &OS, BranchView &BRV, OS << format("%0.2f", TruePercent) << "%, "; // Display FalseCount or FalsePercent. - std::string FalseColor = R.FalseExecutionCount ? "None" : "red"; + std::string FalseColor = R.FalseExecutionCount ? "None" : "red branch"; std::string FalseCovClass = (R.FalseExecutionCount > 0) ? "covered-line" : "uncovered-line"; @@ -1053,24 +1230,21 @@ void SourceCoverageViewHTML::renderTitle(raw_ostream &OS, StringRef Title) { if (getOptions().hasCreatedTime()) OS << tag(CreatedTimeTag, escape(getOptions().CreatedTimeStr, getOptions())); + + OS << tag("span", + a("javascript:next_line()", "next uncovered line (L)") + ", " + + a("javascript:next_region()", "next uncovered region (R)") + + ", " + + a("javascript:next_branch()", "next uncovered branch (B)"), + "control"); } void SourceCoverageViewHTML::renderTableHeader(raw_ostream &OS, - unsigned FirstUncoveredLineNo, unsigned ViewDepth) { - std::string SourceLabel; - if (FirstUncoveredLineNo == 0) { - SourceLabel = tag("td", tag("pre", "Source")); - } else { - std::string LinkTarget = "#L" + utostr(uint64_t(FirstUncoveredLineNo)); - SourceLabel = - tag("td", tag("pre", "Source (" + - a(LinkTarget, "jump to first uncovered line") + - ")")); - } + std::string Links; renderLinePrefix(OS, ViewDepth); - OS << tag("td", tag("pre", "Line")) << tag("td", tag("pre", "Count")) - << SourceLabel; + OS << tag("td", tag("pre", "Line")) << tag("td", tag("pre", "Count")); + OS << tag("td", tag("pre", "Source" + Links)); renderLineSuffix(OS, ViewDepth); } diff --git a/llvm/tools/llvm-cov/SourceCoverageViewHTML.h b/llvm/tools/llvm-cov/SourceCoverageViewHTML.h index 32313a3963c4..9b7391d0043e 100644 --- a/llvm/tools/llvm-cov/SourceCoverageViewHTML.h +++ b/llvm/tools/llvm-cov/SourceCoverageViewHTML.h @@ -38,6 +38,7 @@ public: protected: Error emitStyleSheet(); + Error emitJavaScript(); void emitReportHeader(raw_ostream &OSRef, const std::string &Title); private: @@ -105,8 +106,7 @@ class SourceCoverageViewHTML : public SourceCoverageView { void renderTitle(raw_ostream &OS, StringRef Title) override; - void renderTableHeader(raw_ostream &OS, unsigned FirstUncoveredLineNo, - unsigned IndentLevel) override; + void renderTableHeader(raw_ostream &OS, unsigned IndentLevel) override; public: SourceCoverageViewHTML(StringRef SourceName, const MemoryBuffer &File, diff --git a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp index 580da45ecfc0..cab60c2d9034 100644 --- a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp +++ b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp @@ -414,5 +414,4 @@ void SourceCoverageViewText::renderTitle(raw_ostream &OS, StringRef Title) { << getOptions().CreatedTimeStr << "\n"; } -void SourceCoverageViewText::renderTableHeader(raw_ostream &, unsigned, - unsigned) {} +void SourceCoverageViewText::renderTableHeader(raw_ostream &, unsigned) {} diff --git a/llvm/tools/llvm-cov/SourceCoverageViewText.h b/llvm/tools/llvm-cov/SourceCoverageViewText.h index 7cb47fcbf42b..25a161b09620 100644 --- a/llvm/tools/llvm-cov/SourceCoverageViewText.h +++ b/llvm/tools/llvm-cov/SourceCoverageViewText.h @@ -93,8 +93,7 @@ class SourceCoverageViewText : public SourceCoverageView { void renderTitle(raw_ostream &OS, StringRef Title) override; - void renderTableHeader(raw_ostream &OS, unsigned FirstUncoveredLineNo, - unsigned IndentLevel) override; + void renderTableHeader(raw_ostream &OS, unsigned IndentLevel) override; public: SourceCoverageViewText(StringRef SourceName, const MemoryBuffer &File, diff --git a/llvm/tools/llvm-dis/llvm-dis.cpp b/llvm/tools/llvm-dis/llvm-dis.cpp index fbbb5506e43e..d28af85bc739 100644 --- a/llvm/tools/llvm-dis/llvm-dis.cpp +++ b/llvm/tools/llvm-dis/llvm-dis.cpp @@ -258,7 +258,7 @@ int main(int argc, char **argv) { // All that llvm-dis does is write the assembly to a file. if (!DontPrint) { if (M) { - ScopedDbgInfoFormatSetter FormatSetter(*M, WriteNewDbgInfoFormat); + M->setIsNewDbgInfoFormat(WriteNewDbgInfoFormat); if (WriteNewDbgInfoFormat) M->removeDebugIntrinsicDeclarations(); M->print(Out->os(), Annotator.get(), PreserveAssemblyUseListOrder); diff --git a/llvm/tools/llvm-dwarfdump/Statistics.cpp b/llvm/tools/llvm-dwarfdump/Statistics.cpp index 1846f9265c75..8d6dd17ceae9 100644 --- a/llvm/tools/llvm-dwarfdump/Statistics.cpp +++ b/llvm/tools/llvm-dwarfdump/Statistics.cpp @@ -8,6 +8,7 @@ #include "llvm-dwarfdump.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringSet.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" @@ -188,6 +189,16 @@ struct LocationStats { /// Total number of local variables processed. SaturatingUINT64 NumVar = 0; }; + +/// Holds accumulated debug line statistics across all CUs. +struct LineStats { + SaturatingUINT64 NumBytes = 0; + SaturatingUINT64 NumLineZeroBytes = 0; + SaturatingUINT64 NumEntries = 0; + SaturatingUINT64 NumIsStmtEntries = 0; + SaturatingUINT64 NumUniqueEntries = 0; + SaturatingUINT64 NumUniqueNonZeroEntries = 0; +}; } // namespace /// Collect debug location statistics for one DIE. @@ -848,6 +859,7 @@ bool dwarfdump::collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx, StringRef FormatName = Obj.getFileFormatName(); GlobalStats GlobalStats; LocationStats LocStats; + LineStats LnStats; StringMap<PerFunctionStats> Statistics; // This variable holds variable information for functions with // abstract_origin globally, across all CUs. @@ -856,6 +868,14 @@ bool dwarfdump::collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx, // abstract_origin. FunctionDIECUTyMap AbstractOriginFnCUs; CrossCUReferencingDIELocationTy CrossCUReferencesToBeResolved; + // Tuple representing a single source code position in the line table. Fields + // are respectively: Line, Col, File, where 'File' is an index into the Files + // vector below. + using LineTuple = std::tuple<uint32_t, uint16_t, uint16_t>; + SmallVector<std::string> Files; + DenseSet<LineTuple> UniqueLines; + DenseSet<LineTuple> UniqueNonZeroLines; + for (const auto &CU : static_cast<DWARFContext *>(&DICtx)->compile_units()) { if (DWARFDie CUDie = CU->getNonSkeletonUnitDIE(false)) { // This variable holds variable information for functions with @@ -882,8 +902,58 @@ bool dwarfdump::collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx, CrossCUReferencesToBeResolved.push_back( DIELocation(CUDie.getDwarfUnit(), CrossCUReferencingDIEOffset)); } + const auto *LineTable = DICtx.getLineTableForUnit(CU.get()); + std::optional<uint64_t> LastFileIdxOpt; + if (LineTable) + LastFileIdxOpt = LineTable->getLastValidFileIndex(); + if (LastFileIdxOpt) { + // Each CU has its own file index; in order to track unique line entries + // across CUs, we therefore need to map each CU file index to a global + // file index, which we store here. + DenseMap<uint64_t, uint16_t> CUFileMapping; + for (uint64_t FileIdx = 0; FileIdx <= *LastFileIdxOpt; ++FileIdx) { + std::string File; + if (LineTable->getFileNameByIndex( + FileIdx, CU->getCompilationDir(), + DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, + File)) { + auto ExistingFile = llvm::find(Files, File); + if (ExistingFile != Files.end()) { + CUFileMapping[FileIdx] = std::distance(Files.begin(), ExistingFile); + } else { + CUFileMapping[FileIdx] = Files.size(); + Files.push_back(File); + } + } + } + for (const auto &Seq : LineTable->Sequences) { + LnStats.NumBytes += Seq.HighPC - Seq.LowPC; + // Ignore the `end_sequence` entry, since it's not interesting for us. + LnStats.NumEntries += Seq.LastRowIndex - Seq.FirstRowIndex - 1; + for (size_t RowIdx = Seq.FirstRowIndex; RowIdx < Seq.LastRowIndex - 1; + ++RowIdx) { + auto Entry = LineTable->Rows[RowIdx]; + if (Entry.IsStmt) + LnStats.NumIsStmtEntries += 1; + assert(CUFileMapping.contains(Entry.File) && + "Should have been collected earlier!"); + uint16_t MappedFile = CUFileMapping[Entry.File]; + UniqueLines.insert({Entry.Line, Entry.Column, MappedFile}); + if (Entry.Line != 0) { + UniqueNonZeroLines.insert({Entry.Line, Entry.Column, MappedFile}); + } else { + auto EntryStartAddress = Entry.Address.Address; + auto EntryEndAddress = LineTable->Rows[RowIdx + 1].Address.Address; + LnStats.NumLineZeroBytes += EntryEndAddress - EntryStartAddress; + } + } + } + } } + LnStats.NumUniqueEntries = UniqueLines.size(); + LnStats.NumUniqueNonZeroEntries = UniqueNonZeroLines.size(); + /// Resolve CrossCU references. collectZeroLocCovForVarsWithCrossCUReferencingAbstractOrigin( LocStats, AbstractOriginFnCUs, GlobalAbstractOriginFnInfo, @@ -1043,6 +1113,16 @@ bool dwarfdump::collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx, printLocationStats(J, "#local vars", LocStats.LocalVarLocStats); printLocationStats(J, "#local vars - entry values", LocStats.LocalVarNonEntryValLocStats); + + // Print line statistics for the object file. + printDatum(J, "#bytes with line information", LnStats.NumBytes.Value); + printDatum(J, "#bytes with line-0 locations", LnStats.NumLineZeroBytes.Value); + printDatum(J, "#line entries", LnStats.NumEntries.Value); + printDatum(J, "#line entries (is_stmt)", LnStats.NumIsStmtEntries.Value); + printDatum(J, "#line entries (unique)", LnStats.NumUniqueEntries.Value); + printDatum(J, "#line entries (unique non-0)", + LnStats.NumUniqueNonZeroEntries.Value); + J.objectEnd(); OS << '\n'; LLVM_DEBUG( diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp index 2bfc9705368e..d00cf5207571 100644 --- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -502,7 +502,7 @@ static void filterByAccelName( getDies(DICtx, DICtx.getDebugNames(), Name, Dies); } llvm::sort(Dies); - Dies.erase(std::unique(Dies.begin(), Dies.end()), Dies.end()); + Dies.erase(llvm::unique(Dies), Dies.end()); DIDumpOptions DumpOpts = getDumpOpts(DICtx); DumpOpts.GetNameForDWARFReg = GetNameForDWARFReg; @@ -646,7 +646,7 @@ static bool collectObjectSources(ObjectFile &Obj, DWARFContext &DICtx, // Dedup and order the sources. llvm::sort(Sources); - Sources.erase(std::unique(Sources.begin(), Sources.end()), Sources.end()); + Sources.erase(llvm::unique(Sources), Sources.end()); for (StringRef Name : Sources) OS << Name << "\n"; diff --git a/llvm/tools/llvm-dwp/llvm-dwp.cpp b/llvm/tools/llvm-dwp/llvm-dwp.cpp index 81556b3ad4bc..4c4f2a9fdf78 100644 --- a/llvm/tools/llvm-dwp/llvm-dwp.cpp +++ b/llvm/tools/llvm-dwp/llvm-dwp.cpp @@ -91,7 +91,7 @@ getDWOFilenames(StringRef ExecFilename) { std::string DWOCompDir = dwarf::toString(Die.find(dwarf::DW_AT_comp_dir), ""); if (!DWOCompDir.empty()) { - SmallString<16> DWOPath(std::move(DWOName)); + SmallString<16> DWOPath(DWOName); sys::fs::make_absolute(DWOCompDir, DWOPath); if (!sys::fs::exists(DWOPath) && sys::fs::exists(DWOName)) DWOPaths.push_back(std::move(DWOName)); diff --git a/llvm/tools/llvm-exegesis/CMakeLists.txt b/llvm/tools/llvm-exegesis/CMakeLists.txt index ec418a7d51ec..49cb7e176c6d 100644 --- a/llvm/tools/llvm-exegesis/CMakeLists.txt +++ b/llvm/tools/llvm-exegesis/CMakeLists.txt @@ -1,9 +1,7 @@ +# Has side effect of defining LLVM_EXEGESIS_TARGETS +add_subdirectory(lib) + set(LLVM_LINK_COMPONENTS - AllTargetsAsmParsers - AllTargetsCodeGens - AllTargetsDescs - AllTargetsDisassemblers - AllTargetsInfos CodeGenTypes MC MCParser @@ -11,6 +9,15 @@ set(LLVM_LINK_COMPONENTS TargetParser ) +foreach(t ${LLVM_EXEGESIS_TARGETS}) + string(STRIP ${t} t) + list(APPEND LLVM_LINK_COMPONENTS "${t}AsmParser") + list(APPEND LLVM_LINK_COMPONENTS "${t}CodeGen") + list(APPEND LLVM_LINK_COMPONENTS "${t}Desc") + list(APPEND LLVM_LINK_COMPONENTS "${t}Disassembler") + list(APPEND LLVM_LINK_COMPONENTS "${t}Info") +endforeach() + add_llvm_tool(llvm-exegesis DISABLE_LLVM_LINK_LLVM_DYLIB llvm-exegesis.cpp @@ -19,9 +26,6 @@ add_llvm_tool(llvm-exegesis intrinsics_gen ) -# Has side effect of defining LLVM_EXEGESIS_TARGETS -add_subdirectory(lib) - # Link all enabled exegesis targets set(libs) foreach(t ${LLVM_EXEGESIS_TARGETS}) diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp index 06e1c7f3c1bb..e6a43cfc6db5 100644 --- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp +++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp @@ -470,9 +470,11 @@ void benchmarkMain() { #endif } - InitializeAllAsmPrinters(); - InitializeAllAsmParsers(); InitializeAllExegesisTargets(); +#define LLVM_EXEGESIS(TargetName) \ + LLVMInitialize##TargetName##AsmPrinter(); \ + LLVMInitialize##TargetName##AsmParser(); +#include "llvm/Config/TargetExegesis.def" const LLVMState State = ExitOnErr(LLVMState::Create(TripleName, MCPU, "", UseDummyPerfCounters)); @@ -621,9 +623,11 @@ static void analysisMain() { "and --analysis-inconsistencies-output-file must be specified"); } - InitializeAllAsmPrinters(); - InitializeAllDisassemblers(); InitializeAllExegesisTargets(); +#define LLVM_EXEGESIS(TargetName) \ + LLVMInitialize##TargetName##AsmPrinter(); \ + LLVMInitialize##TargetName##Disassembler(); +#include "llvm/Config/TargetExegesis.def" auto MemoryBuffer = ExitOnFileError( BenchmarkFile, @@ -690,9 +694,11 @@ int main(int Argc, char **Argv) { InitLLVM X(Argc, Argv); // Initialize targets so we can print them when flag --version is specified. - InitializeAllTargetInfos(); - InitializeAllTargets(); - InitializeAllTargetMCs(); +#define LLVM_EXEGESIS(TargetName) \ + LLVMInitialize##TargetName##Target(); \ + LLVMInitialize##TargetName##TargetInfo(); \ + LLVMInitialize##TargetName##TargetMC(); +#include "llvm/Config/TargetExegesis.def" // Register the Target and CPU printer for --version. cl::AddExtraVersionPrinter(sys::printDefaultTargetAndDetectedCPU); diff --git a/llvm/tools/llvm-link/llvm-link.cpp b/llvm/tools/llvm-link/llvm-link.cpp index 7794f2d81ed0..24ee02be7e9e 100644 --- a/llvm/tools/llvm-link/llvm-link.cpp +++ b/llvm/tools/llvm-link/llvm-link.cpp @@ -377,9 +377,13 @@ static bool importFunctions(const char *argv0, Module &DestModule) { if (Verbose) errs() << "Importing " << FunctionName << " from " << FileName << "\n"; + // `-import` specifies the `<filename,function-name>` pairs to import as + // definition, so make the import type definition directly. + // FIXME: A follow-up patch should add test coverage for import declaration + // in `llvm-link` CLI (e.g., by introducing a new command line option). auto &Entry = ImportList[FileNameStringCache.insert(FileName).first->getKey()]; - Entry.insert(F->getGUID()); + Entry[F->getGUID()] = GlobalValueSummary::Definition; } auto CachedModuleLoader = [&](StringRef Identifier) { return ModuleLoaderCache.takeModule(std::string(Identifier)); @@ -489,12 +493,6 @@ int main(int argc, char **argv) { if (LoadBitcodeIntoNewDbgInfoFormat == cl::boolOrDefault::BOU_UNSET) LoadBitcodeIntoNewDbgInfoFormat = cl::boolOrDefault::BOU_TRUE; - // RemoveDIs debug-info transition: tests may request that we /try/ to use the - // new debug-info format. - if (TryUseNewDbgInfoFormat) { - // Turn the new debug-info format on. - UseNewDbgInfoFormat = true; - } // Since llvm-link collects multiple IR modules together, for simplicity's // sake we disable the "PreserveInputDbgFormat" flag to enforce a single // debug info format. @@ -556,7 +554,7 @@ int main(int argc, char **argv) { SetFormat(WriteNewDbgInfoFormat); Composite->print(Out.os(), nullptr, PreserveAssemblyUseListOrder); } else if (Force || !CheckBitcodeOutputToConsole(Out.os())) { - SetFormat(WriteNewDbgInfoFormatToBitcode); + SetFormat(UseNewDbgInfoFormat && WriteNewDbgInfoFormatToBitcode); WriteBitcodeToFile(*Composite, Out.os(), PreserveBitcodeUseListOrder); } diff --git a/llvm/tools/llvm-mc/llvm-mc.cpp b/llvm/tools/llvm-mc/llvm-mc.cpp index 506e4f22ef8f..de999a48d575 100644 --- a/llvm/tools/llvm-mc/llvm-mc.cpp +++ b/llvm/tools/llvm-mc/llvm-mc.cpp @@ -183,10 +183,6 @@ static cl::opt<std::string> MainFileName( cl::desc("Specifies the name we should consider the input file"), cl::cat(MCCategory)); -static cl::opt<bool> SaveTempLabels("save-temp-labels", - cl::desc("Don't discard temporary labels"), - cl::cat(MCCategory)); - static cl::opt<bool> LexMasmIntegers( "masm-integers", cl::desc("Enable binary and hex masm integers (0b110 and 0ABCh)"), @@ -428,9 +424,6 @@ int main(int argc, char **argv) { TheTarget->createMCObjectFileInfo(Ctx, PIC, LargeCodeModel)); Ctx.setObjectFileInfo(MOFI.get()); - if (SaveTempLabels) - Ctx.setAllowTemporaryLabels(false); - Ctx.setGenDwarfForAssembly(GenDwarfForAssembly); // Default to 4 for dwarf version. unsigned DwarfVersion = MCOptions.DwarfVersion ? MCOptions.DwarfVersion : 4; diff --git a/llvm/tools/llvm-mca/CodeRegion.h b/llvm/tools/llvm-mca/CodeRegion.h index 5a2e8baa1f3e..ef8804f1b494 100644 --- a/llvm/tools/llvm-mca/CodeRegion.h +++ b/llvm/tools/llvm-mca/CodeRegion.h @@ -104,11 +104,9 @@ public: dropInstructions(const llvm::SmallPtrSetImpl<const llvm::MCInst *> &Insts) { if (Insts.empty()) return Instructions; - Instructions.erase(std::remove_if(Instructions.begin(), Instructions.end(), - [&Insts](const llvm::MCInst &Inst) { - return Insts.contains(&Inst); - }), - Instructions.end()); + llvm::erase_if(Instructions, [&Insts](const llvm::MCInst &Inst) { + return Insts.contains(&Inst); + }); return Instructions; } diff --git a/llvm/tools/llvm-ml/llvm-ml.cpp b/llvm/tools/llvm-ml/llvm-ml.cpp index f1f39af059aa..24643bd4296b 100644 --- a/llvm/tools/llvm-ml/llvm-ml.cpp +++ b/llvm/tools/llvm-ml/llvm-ml.cpp @@ -263,6 +263,7 @@ int llvm_ml_main(int Argc, char **Argv, const llvm::ToolContext &) { MCTargetOptions MCOptions; MCOptions.AssemblyLanguage = "masm"; MCOptions.MCFatalWarnings = InputArgs.hasArg(OPT_fatal_warnings); + MCOptions.MCSaveTempLabels = InputArgs.hasArg(OPT_save_temp_labels); Triple TheTriple = GetTriple(ProgName, InputArgs); std::string Error; @@ -330,9 +331,6 @@ int llvm_ml_main(int Argc, char **Argv, const llvm::ToolContext &) { Ctx, /*PIC=*/false, /*LargeCodeModel=*/true)); Ctx.setObjectFileInfo(MOFI.get()); - if (InputArgs.hasArg(OPT_save_temp_labels)) - Ctx.setAllowTemporaryLabels(false); - // Set compilation information. SmallString<128> CWD; if (!sys::fs::current_path(CWD)) diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp index e3b81451fcac..d3e8d4c5ed98 100644 --- a/llvm/tools/llvm-nm/llvm-nm.cpp +++ b/llvm/tools/llvm-nm/llvm-nm.cpp @@ -2395,8 +2395,7 @@ exportSymbolNamesFromFiles(const std::vector<std::string> &InputFilenames) { llvm::erase_if(SymbolList, [](const NMSymbol &s) { return !s.shouldPrint(); }); sortSymbolList(SymbolList); - SymbolList.erase(std::unique(SymbolList.begin(), SymbolList.end()), - SymbolList.end()); + SymbolList.erase(llvm::unique(SymbolList), SymbolList.end()); printExportSymbolList(SymbolList); } diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index 675364a1c1bc..6249be4f332b 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -1570,8 +1570,7 @@ static void addSymbolizer( LabelAddrs.insert(LabelAddrs.end(), LabelAddrsRef.begin(), LabelAddrsRef.end()); llvm::sort(LabelAddrs); - LabelAddrs.resize(std::unique(LabelAddrs.begin(), LabelAddrs.end()) - - LabelAddrs.begin()); + LabelAddrs.resize(llvm::unique(LabelAddrs) - LabelAddrs.begin()); // Add the labels. for (unsigned LabelNum = 0; LabelNum != LabelAddrs.size(); ++LabelNum) { auto Name = std::make_unique<std::string>(); @@ -3152,7 +3151,7 @@ void Dumper::printPrivateHeaders() { } static void printFileHeaders(const ObjectFile *O) { - if (!O->isELF() && !O->isCOFF()) + if (!O->isELF() && !O->isCOFF() && !O->isXCOFF()) reportError(O->getFileName(), "Invalid/Unsupported object file format"); Triple::ArchType AT = O->getArch(); diff --git a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp index 1cecbfc463fe..b2362ecb7570 100644 --- a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp +++ b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp @@ -1494,13 +1494,13 @@ Error DumpOutputStyle::dumpModuleSymsForPdb() { if (auto EC = Visitor.visitSymbolStreamFiltered(ModS.getSymbolArray(), Filter)) { P.formatLine("Error while processing symbol records. {0}", - toString(std::move(EC))); + toStringWithoutConsuming(EC)); return EC; } } else if (auto EC = Visitor.visitSymbolStream(ModS.getSymbolArray(), SS.Offset)) { P.formatLine("Error while processing symbol records. {0}", - toString(std::move(EC))); + toStringWithoutConsuming(EC)); return EC; } return Error::success(); diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp index fae6d1e989ab..2ce0668601bc 100644 --- a/llvm/tools/llvm-profdata/llvm-profdata.cpp +++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp @@ -291,6 +291,11 @@ cl::opt<bool> DropProfileSymbolList( cl::desc("Drop the profile symbol list when merging AutoFDO profiles " "(only meaningful for -sample)")); +cl::opt<bool> KeepVTableSymbols( + "keep-vtable-symbols", cl::init(false), cl::Hidden, + cl::sub(MergeSubcommand), + cl::desc("If true, keep the vtable symbols in indexed profiles")); + // Temporary support for writing the previous version of the format, to enable // some forward compatibility. // TODO: Consider enabling this with future version changes as well, to ease @@ -767,11 +772,12 @@ static void loadInput(const WeightedFile &Input, SymbolRemapper *Remapper, }); } - const InstrProfSymtab &symtab = Reader->getSymtab(); - const auto &VTableNames = symtab.getVTableNames(); + if (KeepVTableSymbols) { + const InstrProfSymtab &symtab = Reader->getSymtab(); + const auto &VTableNames = symtab.getVTableNames(); - for (const auto &kv : VTableNames) { - WC->Writer.addVTableName(kv.getKey()); + for (const auto &kv : VTableNames) + WC->Writer.addVTableName(kv.getKey()); } if (Reader->hasTemporalProfile()) { @@ -2695,30 +2701,30 @@ static void traverseAllValueSites(const InstrProfRecord &Func, uint32_t VK, uint32_t NS = Func.getNumValueSites(VK); Stats.TotalNumValueSites += NS; for (size_t I = 0; I < NS; ++I) { - uint32_t NV = Func.getNumValueDataForSite(VK, I); - std::unique_ptr<InstrProfValueData[]> VD = Func.getValueForSite(VK, I); + auto VD = Func.getValueArrayForSite(VK, I); + uint32_t NV = VD.size(); + if (NV == 0) + continue; Stats.TotalNumValues += NV; - if (NV) { - Stats.TotalNumValueSitesWithValueProfile++; - if (NV > Stats.ValueSitesHistogram.size()) - Stats.ValueSitesHistogram.resize(NV, 0); - Stats.ValueSitesHistogram[NV - 1]++; - } + Stats.TotalNumValueSitesWithValueProfile++; + if (NV > Stats.ValueSitesHistogram.size()) + Stats.ValueSitesHistogram.resize(NV, 0); + Stats.ValueSitesHistogram[NV - 1]++; uint64_t SiteSum = 0; - for (uint32_t V = 0; V < NV; V++) - SiteSum += VD[V].Count; + for (const auto &V : VD) + SiteSum += V.Count; if (SiteSum == 0) SiteSum = 1; - for (uint32_t V = 0; V < NV; V++) { + for (const auto &V : VD) { OS << "\t[ " << format("%2u", I) << ", "; if (Symtab == nullptr) - OS << format("%4" PRIu64, VD[V].Value); + OS << format("%4" PRIu64, V.Value); else - OS << Symtab->getFuncOrVarName(VD[V].Value); - OS << ", " << format("%10" PRId64, VD[V].Count) << " ] (" - << format("%.2f%%", (VD[V].Count * 100.0 / SiteSum)) << ")\n"; + OS << Symtab->getFuncOrVarName(V.Value); + OS << ", " << format("%10" PRId64, V.Count) << " ] (" + << format("%.2f%%", (V.Count * 100.0 / SiteSum)) << ")\n"; } } } diff --git a/llvm/tools/llvm-profgen/PerfReader.cpp b/llvm/tools/llvm-profgen/PerfReader.cpp index e63c6d61b3bf..111c546f5329 100644 --- a/llvm/tools/llvm-profgen/PerfReader.cpp +++ b/llvm/tools/llvm-profgen/PerfReader.cpp @@ -321,7 +321,7 @@ bool VirtualUnwinder::unwind(const PerfSample *Sample, uint64_t Repeat) { std::unique_ptr<PerfReaderBase> PerfReaderBase::create(ProfiledBinary *Binary, PerfInputFile &PerfInput, - std::optional<uint32_t> PIDFilter) { + std::optional<int32_t> PIDFilter) { std::unique_ptr<PerfReaderBase> PerfReader; if (PerfInput.Format == PerfFormat::UnsymbolizedProfile) { @@ -331,9 +331,10 @@ PerfReaderBase::create(ProfiledBinary *Binary, PerfInputFile &PerfInput, } // For perf data input, we need to convert them into perf script first. + // If this is a kernel perf file, there is no need for retrieving PIDs. if (PerfInput.Format == PerfFormat::PerfData) - PerfInput = - PerfScriptReader::convertPerfDataToTrace(Binary, PerfInput, PIDFilter); + PerfInput = PerfScriptReader::convertPerfDataToTrace( + Binary, Binary->isKernel(), PerfInput, PIDFilter); assert((PerfInput.Format == PerfFormat::PerfScript) && "Should be a perfscript!"); @@ -353,9 +354,9 @@ PerfReaderBase::create(ProfiledBinary *Binary, PerfInputFile &PerfInput, } PerfInputFile -PerfScriptReader::convertPerfDataToTrace(ProfiledBinary *Binary, +PerfScriptReader::convertPerfDataToTrace(ProfiledBinary *Binary, bool SkipPID, PerfInputFile &File, - std::optional<uint32_t> PIDFilter) { + std::optional<int32_t> PIDFilter) { StringRef PerfData = File.InputFile; // Run perf script to retrieve PIDs matching binary we're interested in. auto PerfExecutable = sys::Process::FindInEnvPath("PATH", "perf"); @@ -363,49 +364,59 @@ PerfScriptReader::convertPerfDataToTrace(ProfiledBinary *Binary, exitWithError("Perf not found."); } std::string PerfPath = *PerfExecutable; - SmallString<128> PerfTraceFile; sys::fs::createUniquePath("perf-script-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%.tmp", PerfTraceFile, /*MakeAbsolute=*/true); std::string ErrorFile = std::string(PerfTraceFile) + ".err"; - StringRef ScriptMMapArgs[] = {PerfPath, "script", "--show-mmap-events", - "-F", "comm,pid", "-i", - PerfData}; std::optional<StringRef> Redirects[] = {std::nullopt, // Stdin StringRef(PerfTraceFile), // Stdout StringRef(ErrorFile)}; // Stderr - sys::ExecuteAndWait(PerfPath, ScriptMMapArgs, std::nullopt, Redirects); - PerfScriptReader::TempFileCleanups.emplace_back(PerfTraceFile); PerfScriptReader::TempFileCleanups.emplace_back(ErrorFile); - // Collect the PIDs - TraceStream TraceIt(PerfTraceFile); std::string PIDs; - std::unordered_set<uint32_t> PIDSet; - while (!TraceIt.isAtEoF()) { - MMapEvent MMap; - if (isMMap2Event(TraceIt.getCurrentLine()) && - extractMMap2EventForBinary(Binary, TraceIt.getCurrentLine(), MMap)) { - auto It = PIDSet.emplace(MMap.PID); - if (It.second && (!PIDFilter || MMap.PID == *PIDFilter)) { - if (!PIDs.empty()) { - PIDs.append(","); + if (!SkipPID) { + StringRef ScriptMMapArgs[] = {PerfPath, "script", "--show-mmap-events", + "-F", "comm,pid", "-i", + PerfData}; + sys::ExecuteAndWait(PerfPath, ScriptMMapArgs, std::nullopt, Redirects); + + // Collect the PIDs + TraceStream TraceIt(PerfTraceFile); + std::unordered_set<int32_t> PIDSet; + while (!TraceIt.isAtEoF()) { + MMapEvent MMap; + if (isMMapEvent(TraceIt.getCurrentLine()) && + extractMMapEventForBinary(Binary, TraceIt.getCurrentLine(), MMap)) { + auto It = PIDSet.emplace(MMap.PID); + if (It.second && (!PIDFilter || MMap.PID == *PIDFilter)) { + if (!PIDs.empty()) { + PIDs.append(","); + } + PIDs.append(utostr(MMap.PID)); } - PIDs.append(utostr(MMap.PID)); } + TraceIt.advance(); } - TraceIt.advance(); - } - if (PIDs.empty()) { - exitWithError("No relevant mmap event is found in perf data."); + if (PIDs.empty()) { + exitWithError("No relevant mmap event is found in perf data."); + } } // Run perf script again to retrieve events for PIDs collected above - StringRef ScriptSampleArgs[] = {PerfPath, "script", "--show-mmap-events", - "-F", "ip,brstack", "--pid", - PIDs, "-i", PerfData}; + SmallVector<StringRef, 8> ScriptSampleArgs; + ScriptSampleArgs.push_back(PerfPath); + ScriptSampleArgs.push_back("script"); + ScriptSampleArgs.push_back("--show-mmap-events"); + ScriptSampleArgs.push_back("-F"); + ScriptSampleArgs.push_back("ip,brstack"); + ScriptSampleArgs.push_back("-i"); + ScriptSampleArgs.push_back(PerfData); + if (!PIDs.empty()) { + ScriptSampleArgs.push_back("--pid"); + ScriptSampleArgs.push_back(PIDs); + } sys::ExecuteAndWait(PerfPath, ScriptSampleArgs, std::nullopt, Redirects); return {std::string(PerfTraceFile), PerfFormat::PerfScript, @@ -428,7 +439,10 @@ static StringRef filename(StringRef Path, bool UseBackSlash) { void PerfScriptReader::updateBinaryAddress(const MMapEvent &Event) { // Drop the event which doesn't belong to user-provided binary StringRef BinaryName = filename(Event.BinaryPath, Binary->isCOFF()); - if (Binary->getName() != BinaryName) + bool IsKernel = Binary->isKernel(); + if (!IsKernel && Binary->getName() != BinaryName) + return; + if (IsKernel && !Binary->isKernelImageName(BinaryName)) return; // Drop the event if process does not match pid filter @@ -441,7 +455,7 @@ void PerfScriptReader::updateBinaryAddress(const MMapEvent &Event) { return; } - if (Event.Offset == Binary->getTextSegmentOffset()) { + if (IsKernel || Event.Offset == Binary->getTextSegmentOffset()) { // A binary image could be unloaded and then reloaded at different // place, so update binary load address. // Only update for the first executable segment and assume all other @@ -550,7 +564,7 @@ bool PerfScriptReader::extractLBRStack(TraceStream &TraceIt, // The raw format of LBR stack is like: // 0x4005c8/0x4005dc/P/-/-/0 0x40062f/0x4005b0/P/-/-/0 ... // ... 0x4005c8/0x4005dc/P/-/-/0 - // It's in FIFO order and seperated by whitespace. + // It's in FIFO order and separated by whitespace. SmallVector<StringRef, 32> Records; TraceIt.getCurrentLine().rtrim().split(Records, " ", -1, false); auto WarnInvalidLBR = [](TraceStream &TraceIt) { @@ -950,16 +964,23 @@ void PerfScriptReader::parseSample(TraceStream &TraceIt) { parseSample(TraceIt, Count); } -bool PerfScriptReader::extractMMap2EventForBinary(ProfiledBinary *Binary, - StringRef Line, - MMapEvent &MMap) { - // Parse a line like: +bool PerfScriptReader::extractMMapEventForBinary(ProfiledBinary *Binary, + StringRef Line, + MMapEvent &MMap) { + // Parse a MMap2 line like: // PERF_RECORD_MMAP2 2113428/2113428: [0x7fd4efb57000(0x204000) @ 0 // 08:04 19532229 3585508847]: r-xp /usr/lib64/libdl-2.17.so - constexpr static const char *const Pattern = - "PERF_RECORD_MMAP2 ([0-9]+)/[0-9]+: " + constexpr static const char *const MMap2Pattern = + "PERF_RECORD_MMAP2 (-?[0-9]+)/[0-9]+: " "\\[(0x[a-f0-9]+)\\((0x[a-f0-9]+)\\) @ " "(0x[a-f0-9]+|0) .*\\]: [-a-z]+ (.*)"; + // Parse a MMap line like + // PERF_RECORD_MMAP -1/0: [0xffffffff81e00000(0x3e8fa000) @ \ + // 0xffffffff81e00000]: x [kernel.kallsyms]_text + constexpr static const char *const MMapPattern = + "PERF_RECORD_MMAP (-?[0-9]+)/[0-9]+: " + "\\[(0x[a-f0-9]+)\\((0x[a-f0-9]+)\\) @ " + "(0x[a-f0-9]+|0)\\]: [-a-z]+ (.*)"; // Field 0 - whole line // Field 1 - PID // Field 2 - base address @@ -975,14 +996,25 @@ bool PerfScriptReader::extractMMap2EventForBinary(ProfiledBinary *Binary, BINARY_PATH = 5 }; - Regex RegMmap2(Pattern); + bool R = false; SmallVector<StringRef, 6> Fields; - bool R = RegMmap2.match(Line, &Fields); + if (Line.contains("PERF_RECORD_MMAP2 ")) { + Regex RegMmap2(MMap2Pattern); + R = RegMmap2.match(Line, &Fields); + } else if (Line.contains("PERF_RECORD_MMAP ")) { + Regex RegMmap(MMapPattern); + R = RegMmap.match(Line, &Fields); + } else + llvm_unreachable("unexpected MMAP event entry"); + if (!R) { std::string WarningMsg = "Cannot parse mmap event: " + Line.str() + " \n"; WithColor::warning() << WarningMsg; + return false; } - Fields[PID].getAsInteger(10, MMap.PID); + long long MMapPID = 0; + getAsSignedInteger(Fields[PID], 10, MMapPID); + MMap.PID = MMapPID; Fields[MMAPPED_ADDRESS].getAsInteger(0, MMap.Address); Fields[MMAPPED_SIZE].getAsInteger(0, MMap.Size); Fields[PAGE_OFFSET].getAsInteger(0, MMap.Offset); @@ -993,19 +1025,22 @@ bool PerfScriptReader::extractMMap2EventForBinary(ProfiledBinary *Binary, } StringRef BinaryName = filename(MMap.BinaryPath, Binary->isCOFF()); + if (Binary->isKernel()) { + return Binary->isKernelImageName(BinaryName); + } return Binary->getName() == BinaryName; } -void PerfScriptReader::parseMMap2Event(TraceStream &TraceIt) { +void PerfScriptReader::parseMMapEvent(TraceStream &TraceIt) { MMapEvent MMap; - if (extractMMap2EventForBinary(Binary, TraceIt.getCurrentLine(), MMap)) + if (extractMMapEventForBinary(Binary, TraceIt.getCurrentLine(), MMap)) updateBinaryAddress(MMap); TraceIt.advance(); } void PerfScriptReader::parseEventOrSample(TraceStream &TraceIt) { - if (isMMap2Event(TraceIt.getCurrentLine())) - parseMMap2Event(TraceIt); + if (isMMapEvent(TraceIt.getCurrentLine())) + parseMMapEvent(TraceIt); else parseSample(TraceIt); } @@ -1032,7 +1067,7 @@ bool PerfScriptReader::isLBRSample(StringRef Line) { return false; } -bool PerfScriptReader::isMMap2Event(StringRef Line) { +bool PerfScriptReader::isMMapEvent(StringRef Line) { // Short cut to avoid string find is possible. if (Line.empty() || Line.size() < 50) return false; @@ -1040,9 +1075,9 @@ bool PerfScriptReader::isMMap2Event(StringRef Line) { if (std::isdigit(Line[0])) return false; - // PERF_RECORD_MMAP2 does not appear at the beginning of the line - // for ` perf script --show-mmap-events -i ...` - return Line.contains("PERF_RECORD_MMAP2"); + // PERF_RECORD_MMAP2 or PERF_RECORD_MMAP does not appear at the beginning of + // the line for ` perf script --show-mmap-events -i ...` + return Line.contains("PERF_RECORD_MMAP"); } // The raw hybird sample is like @@ -1208,6 +1243,10 @@ void PerfScriptReader::warnInvalidRange() { void PerfScriptReader::parsePerfTraces() { // Parse perf traces and do aggregation. parseAndAggregateTrace(); + if (Binary->isKernel() && !Binary->getIsLoadedByMMap()) { + exitWithError( + "Kernel is requested, but no kernel is found in mmap events."); + } emitWarningSummary(NumLeafExternalFrame, NumTotalSample, "of samples have leaf external frame in call stack."); diff --git a/llvm/tools/llvm-profgen/PerfReader.h b/llvm/tools/llvm-profgen/PerfReader.h index b821cbe13efa..a3bd7a0a6493 100644 --- a/llvm/tools/llvm-profgen/PerfReader.h +++ b/llvm/tools/llvm-profgen/PerfReader.h @@ -570,7 +570,7 @@ public: virtual ~PerfReaderBase() = default; static std::unique_ptr<PerfReaderBase> create(ProfiledBinary *Binary, PerfInputFile &PerfInput, - std::optional<uint32_t> PIDFilter); + std::optional<int32_t> PIDFilter); // Entry of the reader to parse multiple perf traces virtual void parsePerfTraces() = 0; @@ -595,15 +595,15 @@ protected: class PerfScriptReader : public PerfReaderBase { public: PerfScriptReader(ProfiledBinary *B, StringRef PerfTrace, - std::optional<uint32_t> PID) - : PerfReaderBase(B, PerfTrace), PIDFilter(PID){}; + std::optional<int32_t> PID) + : PerfReaderBase(B, PerfTrace), PIDFilter(PID) {}; // Entry of the reader to parse multiple perf traces void parsePerfTraces() override; // Generate perf script from perf data - static PerfInputFile - convertPerfDataToTrace(ProfiledBinary *Binary, PerfInputFile &File, - std::optional<uint32_t> PIDFilter); + static PerfInputFile convertPerfDataToTrace(ProfiledBinary *Binary, + bool SkipPID, PerfInputFile &File, + std::optional<int32_t> PIDFilter); // Extract perf script type by peaking at the input static PerfContent checkPerfScriptType(StringRef FileName); @@ -615,7 +615,7 @@ public: protected: // The parsed MMap event struct MMapEvent { - uint64_t PID = 0; + int64_t PID = 0; uint64_t Address = 0; uint64_t Size = 0; uint64_t Offset = 0; @@ -625,15 +625,15 @@ protected: // Check whether a given line is LBR sample static bool isLBRSample(StringRef Line); // Check whether a given line is MMAP event - static bool isMMap2Event(StringRef Line); - // Parse a single line of a PERF_RECORD_MMAP2 event looking for a + static bool isMMapEvent(StringRef Line); + // Parse a single line of a PERF_RECORD_MMAP event looking for a // mapping between the binary name and its memory layout. - static bool extractMMap2EventForBinary(ProfiledBinary *Binary, StringRef Line, - MMapEvent &MMap); + static bool extractMMapEventForBinary(ProfiledBinary *Binary, StringRef Line, + MMapEvent &MMap); // Update base address based on mmap events void updateBinaryAddress(const MMapEvent &Event); // Parse mmap event and update binary address - void parseMMap2Event(TraceStream &TraceIt); + void parseMMapEvent(TraceStream &TraceIt); // Parse perf events/samples and do aggregation void parseAndAggregateTrace(); // Parse either an MMAP event or a perf sample @@ -669,7 +669,7 @@ protected: // Keep track of all invalid return addresses std::set<uint64_t> InvalidReturnAddresses; // PID for the process of interest - std::optional<uint32_t> PIDFilter; + std::optional<int32_t> PIDFilter; }; /* @@ -681,8 +681,8 @@ protected: class LBRPerfReader : public PerfScriptReader { public: LBRPerfReader(ProfiledBinary *Binary, StringRef PerfTrace, - std::optional<uint32_t> PID) - : PerfScriptReader(Binary, PerfTrace, PID){}; + std::optional<int32_t> PID) + : PerfScriptReader(Binary, PerfTrace, PID) {}; // Parse the LBR only sample. void parseSample(TraceStream &TraceIt, uint64_t Count) override; }; @@ -699,8 +699,8 @@ public: class HybridPerfReader : public PerfScriptReader { public: HybridPerfReader(ProfiledBinary *Binary, StringRef PerfTrace, - std::optional<uint32_t> PID) - : PerfScriptReader(Binary, PerfTrace, PID){}; + std::optional<int32_t> PID) + : PerfScriptReader(Binary, PerfTrace, PID) {}; // Parse the hybrid sample including the call and LBR line void parseSample(TraceStream &TraceIt, uint64_t Count) override; void generateUnsymbolizedProfile() override; diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.cpp b/llvm/tools/llvm-profgen/ProfiledBinary.cpp index 1baf35820f97..a7e506d32ac2 100644 --- a/llvm/tools/llvm-profgen/ProfiledBinary.cpp +++ b/llvm/tools/llvm-profgen/ProfiledBinary.cpp @@ -56,6 +56,10 @@ static cl::list<std::string> DisassembleFunctions( cl::desc("List of functions to print disassembly for. Accept demangled " "names only. Only work with show-disassembly-only")); +static cl::opt<bool> + KernelBinary("kernel", + cl::desc("Generate the profile for Linux kernel binary.")); + extern cl::opt<bool> ShowDetailedWarning; extern cl::opt<bool> InferMissingFrames; @@ -221,6 +225,9 @@ void ProfiledBinary::load() { LLVM_DEBUG(dbgs() << "Loading " << Path << "\n"); + // Mark the binary as a kernel image; + IsKernel = KernelBinary; + // Find the preferred load address for text sections. setPreferredTextSegmentAddresses(Obj); diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.h b/llvm/tools/llvm-profgen/ProfiledBinary.h index 5d2088ad7691..8d96d1598959 100644 --- a/llvm/tools/llvm-profgen/ProfiledBinary.h +++ b/llvm/tools/llvm-profgen/ProfiledBinary.h @@ -291,6 +291,9 @@ class ProfiledBinary { // Whether we need to symbolize all instructions to get function context size. bool TrackFuncContextSize = false; + // Whether this is a kernel image; + bool IsKernel = false; + // Indicate if the base loading address is parsed from the mmap event or uses // the preferred address bool IsLoadedByMMap = false; @@ -428,6 +431,14 @@ public: bool usePseudoProbes() const { return UsePseudoProbes; } bool useFSDiscriminator() const { return UseFSDiscriminator; } + bool isKernel() const { return IsKernel; } + + static bool isKernelImageName(StringRef BinaryName) { + return BinaryName == "[kernel.kallsyms]" || + BinaryName == "[kernel.kallsyms]_stext" || + BinaryName == "[kernel.kallsyms]_text"; + } + // Get the index in CodeAddressVec for the address // As we might get an address which is not the code // here it would round to the next valid code address by diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index c696934a959b..a986ba88fdcf 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -793,7 +793,11 @@ public: void printEmptyGroupMessage() const override; + void printDynamicTable() override; + private: + void printAuxillaryDynamicTableEntryInfo(const Elf_Dyn &Entry); + std::unique_ptr<DictScope> FileScope; }; @@ -2313,6 +2317,12 @@ std::string ELFDumper<ELFT>::getDynamicEntry(uint64_t Type, return OS.str(); }; + const std::map<uint64_t, const char *> TagNames = { + {DT_NEEDED, "Shared library"}, {DT_SONAME, "Library soname"}, + {DT_AUXILIARY, "Auxiliary library"}, {DT_USED, "Not needed object"}, + {DT_FILTER, "Filter library"}, {DT_RPATH, "Library rpath"}, + {DT_RUNPATH, "Library runpath"}, + }; // Handle custom printing of architecture specific tags switch (Obj.getHeader().e_machine) { case EM_AARCH64: @@ -2470,18 +2480,11 @@ std::string ELFDumper<ELFT>::getDynamicEntry(uint64_t Type, case DT_AUXILIARY: case DT_USED: case DT_FILTER: + return (Twine(TagNames.at(Type)) + ": " + getDynamicString(Value)).str(); case DT_RPATH: - case DT_RUNPATH: { - const std::map<uint64_t, const char *> TagNames = { - {DT_NEEDED, "Shared library"}, {DT_SONAME, "Library soname"}, - {DT_AUXILIARY, "Auxiliary library"}, {DT_USED, "Not needed object"}, - {DT_FILTER, "Filter library"}, {DT_RPATH, "Library rpath"}, - {DT_RUNPATH, "Library runpath"}, - }; - + case DT_RUNPATH: return (Twine(TagNames.at(Type)) + ": [" + getDynamicString(Value) + "]") .str(); - } case DT_FLAGS: return FormatFlags(Value, ArrayRef(ElfDynamicDTFlags)); case DT_FLAGS_1: @@ -7365,6 +7368,63 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printDynamicTable() { W.startLine() << "]\n"; } +template <class ELFT> +void JSONELFDumper<ELFT>::printAuxillaryDynamicTableEntryInfo( + const Elf_Dyn &Entry) { + auto FormatFlags = [this, Value = Entry.getVal()](auto Flags) { + ListScope L(this->W, "Flags"); + for (const auto &Flag : Flags) { + if (Flag.Value != 0 && (Value & Flag.Value) == Flag.Value) + this->W.printString(Flag.Name); + } + }; + switch (Entry.getTag()) { + case DT_SONAME: + this->W.printString("Name", this->getDynamicString(Entry.getVal())); + break; + case DT_AUXILIARY: + case DT_FILTER: + case DT_NEEDED: + this->W.printString("Library", this->getDynamicString(Entry.getVal())); + break; + case DT_USED: + this->W.printString("Object", this->getDynamicString(Entry.getVal())); + break; + case DT_RPATH: + case DT_RUNPATH: { + StringRef Value = this->getDynamicString(Entry.getVal()); + ListScope L(this->W, "Path"); + while (!Value.empty()) { + auto [Front, Back] = Value.split(':'); + this->W.printString(Front); + Value = Back; + } + break; + } + case DT_FLAGS: + FormatFlags(ArrayRef(ElfDynamicDTFlags)); + break; + case DT_FLAGS_1: + FormatFlags(ArrayRef(ElfDynamicDTFlags1)); + break; + default: + return; + } +} + +template <class ELFT> void JSONELFDumper<ELFT>::printDynamicTable() { + Elf_Dyn_Range Table = this->dynamic_table(); + ListScope L(this->W, "DynamicSection"); + for (const auto &Entry : Table) { + DictScope D(this->W); + uintX_t Tag = Entry.getTag(); + this->W.printHex("Tag", Tag); + this->W.printString("Type", this->Obj.getDynamicTagAsString(Tag)); + this->W.printHex("Value", Entry.getVal()); + this->printAuxillaryDynamicTableEntryInfo(Entry); + } +} + template <class ELFT> void LLVMELFDumper<ELFT>::printDynamicRelocations() { W.startLine() << "Dynamic Relocations {\n"; W.indent(); diff --git a/llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.cpp b/llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.cpp index b97d75a822f7..5f0697f5aaad 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.runOnMachineFunction(MF); + MDT.calculate(MF); auto MRI = &MF.getRegInfo(); SetVector<MachineInstr *> ToDelete; diff --git a/llvm/tools/opt/optdriver.cpp b/llvm/tools/opt/optdriver.cpp index d322666b207d..a088e7512f5f 100644 --- a/llvm/tools/opt/optdriver.cpp +++ b/llvm/tools/opt/optdriver.cpp @@ -47,6 +47,7 @@ #include "llvm/Support/SourceMgr.h" #include "llvm/Support/SystemUtils.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Support/TimeProfiler.h" #include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/YAMLTraits.h" #include "llvm/Target/TargetMachine.h" |
