From d97fe62f5c723a9af64f1b2e04da7eef02592bc9 Mon Sep 17 00:00:00 2001 From: Tobias Stadler Date: Fri, 19 Sep 2025 15:34:41 +0100 Subject: [PATCH 1/3] [spr] changes to main this commit is based on Created using spr 1.3.7-wip [skip ci] --- clang/lib/CodeGen/BackendUtil.cpp | 5 + clang/lib/CodeGen/CodeGenAction.cpp | 19 +- flang/lib/Frontend/FrontendActions.cpp | 5 +- llvm/docs/Remarks.rst | 129 ++---------- llvm/include/llvm/IR/LLVMRemarkStreamer.h | 70 ++++++- llvm/include/llvm/LTO/LTO.h | 5 +- llvm/include/llvm/LTO/LTOBackend.h | 3 +- .../llvm/LTO/legacy/LTOCodeGenerator.h | 2 +- .../llvm/Remarks/BitstreamRemarkContainer.h | 48 ++--- .../llvm/Remarks/BitstreamRemarkSerializer.h | 115 ++++------- llvm/include/llvm/Remarks/RemarkSerializer.h | 36 ++-- llvm/include/llvm/Remarks/RemarkStreamer.h | 9 + .../llvm/Remarks/YAMLRemarkSerializer.h | 18 +- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 19 +- llvm/lib/IR/LLVMRemarkStreamer.cpp | 63 ++++-- llvm/lib/LTO/LTO.cpp | 8 +- llvm/lib/LTO/LTOBackend.cpp | 6 +- llvm/lib/LTO/LTOCodeGenerator.cpp | 1 + llvm/lib/Remarks/BitstreamRemarkParser.cpp | 184 +++++++++-------- llvm/lib/Remarks/BitstreamRemarkParser.h | 48 +++-- .../lib/Remarks/BitstreamRemarkSerializer.cpp | 149 +++++--------- llvm/lib/Remarks/RemarkLinker.cpp | 2 +- llvm/lib/Remarks/RemarkSerializer.cpp | 16 +- llvm/lib/Remarks/RemarkStreamer.cpp | 24 +-- llvm/lib/Remarks/YAMLRemarkParser.cpp | 6 +- llvm/lib/Remarks/YAMLRemarkSerializer.cpp | 29 +-- .../optimization-remarks-passed-yaml.ll | 5 + .../ARM/remarks-linking-bundle-empty.test | 13 ++ .../dsymutil/ARM/remarks-linking-bundle.test | 81 ++++++++ llvm/test/tools/dsymutil/Inputs/basic1.c | 4 +- .../tmp/remarks/basic1.macho.remarks.arm64.o | Bin 0 -> 2008 bytes .../basic1.macho.remarks.arm64.opt.yaml | 47 +++++ .../basic1.macho.remarks.empty.arm64.o | Bin 0 -> 2000 bytes ...1.macho.remarks.empty.arm64.opt.bitstream} | 0 .../tmp/remarks/basic2.macho.remarks.arm64.o | Bin 0 -> 2816 bytes .../basic2.macho.remarks.arm64.opt.yaml | 194 ++++++++++++++++++ .../basic2.macho.remarks.empty.arm64.o | Bin 0 -> 2800 bytes ...2.macho.remarks.empty.arm64.opt.bitstream} | 0 .../tmp/remarks/basic3.macho.remarks.arm64.o | Bin 0 -> 2528 bytes .../basic3.macho.remarks.arm64.opt.yaml | 181 ++++++++++++++++ .../basic3.macho.remarks.empty.arm64.o | Bin 0 -> 2584 bytes ...3.macho.remarks.empty.arm64.opt.bitstream} | 0 .../tmp/remarks/fat.macho.remarks.x86.o | Bin 0 -> 34800 bytes .../remarks/fat.macho.remarks.x86_64.opt.yaml | 53 +++++ .../fat.macho.remarks.x86_64h.opt.yaml | 53 +++++ .../Inputs/remarks/basic.macho.remarks.arm64 | Bin 0 -> 34216 bytes .../remarks/basic.macho.remarks.empty.arm64 | Bin 0 -> 34416 bytes .../remarks/basic.macho.remarks.empty.x86_64 | Bin 9296 -> 0 bytes .../Inputs/remarks/basic.macho.remarks.x86_64 | Bin 9280 -> 0 bytes .../basic1.macho.remarks.empty.x86_64.o | Bin 2088 -> 0 bytes .../remarks/basic1.macho.remarks.x86_64.o | Bin 2416 -> 0 bytes .../basic1.macho.remarks.x86_64.opt.bitstream | Bin 384 -> 0 bytes .../basic2.macho.remarks.empty.x86_64.o | Bin 2892 -> 0 bytes .../remarks/basic2.macho.remarks.x86_64.o | Bin 3356 -> 0 bytes .../basic2.macho.remarks.x86_64.opt.bitstream | Bin 592 -> 0 bytes .../basic3.macho.remarks.empty.x86_64.o | Bin 2624 -> 0 bytes .../remarks/basic3.macho.remarks.x86_64.o | Bin 3080 -> 0 bytes .../basic3.macho.remarks.x86_64.opt.bitstream | Bin 592 -> 0 bytes .../fat.macho.remarks.i386.opt.bitstream | Bin 372 -> 0 bytes .../Inputs/remarks/fat.macho.remarks.x86 | Bin 24876 -> 16792 bytes .../Inputs/remarks/fat.macho.remarks.x86.c | 6 +- .../Inputs/remarks/fat.macho.remarks.x86.o | Bin 14440 -> 0 bytes .../fat.macho.remarks.x86.opt.bitstream | Bin 372 -> 0 bytes .../fat.macho.remarks.x86_64.opt.bitstream | Bin 344 -> 0 bytes .../fat.macho.remarks.x86_64h.opt.bitstream | Bin 344 -> 0 bytes .../X86/remarks-linking-bundle-empty.test | 13 -- .../dsymutil/X86/remarks-linking-bundle.test | 67 ------ .../X86/remarks-linking-fat-bundle.test | 13 +- .../Inputs/two-remarks.bitstream | Bin 500 -> 512 bytes .../Inputs/two-remarks.v0.bitstream | Bin 0 -> 500 bytes llvm/test/tools/llvm-remarkutil/convert.test | 3 + llvm/tools/dsymutil/DwarfLinkerForBinary.cpp | 1 + llvm/tools/llc/llc.cpp | 4 +- llvm/tools/llvm-remarkutil/RemarkConvert.cpp | 7 +- llvm/tools/opt/optdriver.cpp | 4 +- .../Remarks/BitstreamRemarksFormatTest.cpp | 2 +- .../Remarks/BitstreamRemarksParsingTest.cpp | 14 +- .../BitstreamRemarksSerializerTest.cpp | 172 ++++++++-------- llvm/unittests/Remarks/RemarksLinkingTest.cpp | 48 +++-- .../Remarks/YAMLRemarksSerializerTest.cpp | 46 ++++- mlir/include/mlir/Remark/RemarkStreamer.h | 5 +- mlir/lib/Remark/RemarkStreamer.cpp | 9 +- offload/plugins-nextgen/common/src/JIT.cpp | 7 +- 83 files changed, 1306 insertions(+), 765 deletions(-) create mode 100644 llvm/test/tools/dsymutil/ARM/remarks-linking-bundle-empty.test create mode 100644 llvm/test/tools/dsymutil/ARM/remarks-linking-bundle.test create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic1.macho.remarks.arm64.o create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic1.macho.remarks.arm64.opt.yaml create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic1.macho.remarks.empty.arm64.o rename llvm/test/tools/dsymutil/Inputs/{remarks/basic1.macho.remarks.empty.x86_64.opt.bitstream => private/tmp/remarks/basic1.macho.remarks.empty.arm64.opt.bitstream} (100%) create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.arm64.o create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.arm64.opt.yaml create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.empty.arm64.o rename llvm/test/tools/dsymutil/Inputs/{remarks/basic2.macho.remarks.empty.x86_64.opt.bitstream => private/tmp/remarks/basic2.macho.remarks.empty.arm64.opt.bitstream} (100%) create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic3.macho.remarks.arm64.o create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic3.macho.remarks.arm64.opt.yaml create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic3.macho.remarks.empty.arm64.o rename llvm/test/tools/dsymutil/Inputs/{remarks/basic3.macho.remarks.empty.x86_64.opt.bitstream => private/tmp/remarks/basic3.macho.remarks.empty.arm64.opt.bitstream} (100%) create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/fat.macho.remarks.x86.o create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/fat.macho.remarks.x86_64.opt.yaml create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/fat.macho.remarks.x86_64h.opt.yaml create mode 100755 llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.arm64 create mode 100755 llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.empty.arm64 delete mode 100755 llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.empty.x86_64 delete mode 100755 llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.x86_64 delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.empty.x86_64.o delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.x86_64.o delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.x86_64.opt.bitstream delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/basic2.macho.remarks.empty.x86_64.o delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/basic2.macho.remarks.x86_64.o delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/basic2.macho.remarks.x86_64.opt.bitstream delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.empty.x86_64.o delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.x86_64.o delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.x86_64.opt.bitstream delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.i386.opt.bitstream delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.x86.o delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.x86.opt.bitstream delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.x86_64.opt.bitstream delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.x86_64h.opt.bitstream delete mode 100644 llvm/test/tools/dsymutil/X86/remarks-linking-bundle-empty.test delete mode 100644 llvm/test/tools/dsymutil/X86/remarks-linking-bundle.test create mode 100644 llvm/test/tools/llvm-remarkutil/Inputs/two-remarks.v0.bitstream diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 8c99af2bdff83..1b5f9796dd243 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -29,6 +29,7 @@ #include "llvm/Frontend/Driver/CodeGenOptions.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugInfo.h" +#include "llvm/IR/LLVMRemarkStreamer.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/ModuleSummaryIndex.h" @@ -1382,6 +1383,10 @@ runThinLTOBackend(CompilerInstance &CI, ModuleSummaryIndex *CombinedIndex, Conf.CGFileType = getCodeGenFileType(Action); break; } + + // FIXME: Both ExecuteAction and thinBackend setup optimization remarks for + // the same context. + finalizeLLVMOptimizationRemarks(M->getContext()); if (Error E = thinBackend(Conf, -1, AddStream, *M, *CombinedIndex, ImportList, ModuleToDefinedGVSummaries[M->getModuleIdentifier()], diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index dc54c97eeae8e..8e3234998df2a 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -29,6 +29,7 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Serialization/ASTWriter.h" #include "llvm/ADT/Hashing.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" #include "llvm/Demangle/Demangle.h" @@ -259,19 +260,18 @@ void BackendConsumer::HandleTranslationUnit(ASTContext &C) { Ctx.setDefaultTargetCPU(TargetOpts.CPU); Ctx.setDefaultTargetFeatures(llvm::join(TargetOpts.Features, ",")); - Expected> OptRecordFileOrErr = - setupLLVMOptimizationRemarks( - Ctx, CodeGenOpts.OptRecordFile, CodeGenOpts.OptRecordPasses, - CodeGenOpts.OptRecordFormat, CodeGenOpts.DiagnosticsWithHotness, - CodeGenOpts.DiagnosticsHotnessThreshold); + Expected OptRecordFileOrErr = + setupLLVMOptimizationRemarks( + Ctx, CodeGenOpts.OptRecordFile, CodeGenOpts.OptRecordPasses, + CodeGenOpts.OptRecordFormat, CodeGenOpts.DiagnosticsWithHotness, + CodeGenOpts.DiagnosticsHotnessThreshold); if (Error E = OptRecordFileOrErr.takeError()) { reportOptRecordError(std::move(E), Diags, CodeGenOpts); return; } - std::unique_ptr OptRecordFile = - std::move(*OptRecordFileOrErr); + LLVMRemarkFileHandle OptRecordFile = std::move(*OptRecordFileOrErr); if (OptRecordFile && CodeGenOpts.getProfileUse() != llvm::driver::ProfileInstrKind::ProfileNone) @@ -1173,7 +1173,7 @@ void CodeGenAction::ExecuteAction() { Ctx.setDefaultTargetCPU(TargetOpts.CPU); Ctx.setDefaultTargetFeatures(llvm::join(TargetOpts.Features, ",")); - Expected> OptRecordFileOrErr = + Expected OptRecordFileOrErr = setupLLVMOptimizationRemarks( Ctx, CodeGenOpts.OptRecordFile, CodeGenOpts.OptRecordPasses, CodeGenOpts.OptRecordFormat, CodeGenOpts.DiagnosticsWithHotness, @@ -1183,8 +1183,7 @@ void CodeGenAction::ExecuteAction() { reportOptRecordError(std::move(E), Diagnostics, CodeGenOpts); return; } - std::unique_ptr OptRecordFile = - std::move(*OptRecordFileOrErr); + LLVMRemarkFileHandle OptRecordFile = std::move(*OptRecordFileOrErr); emitBackendOutput(CI, CI.getCodeGenOpts(), CI.getTarget().getDataLayoutString(), TheModule.get(), BA, diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index 23cc1e63e773d..3c60fc6dbbbf7 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -1343,7 +1343,7 @@ void CodeGenAction::executeAction() { std::make_unique(remarkConsumer)); // write optimization-record - llvm::Expected> optRecordFileOrErr = + llvm::Expected optRecordFileOrErr = setupLLVMOptimizationRemarks( llvmModule->getContext(), codeGenOpts.OptRecordFile, codeGenOpts.OptRecordPasses, codeGenOpts.OptRecordFormat, @@ -1355,8 +1355,7 @@ void CodeGenAction::executeAction() { return; } - std::unique_ptr optRecordFile = - std::move(*optRecordFileOrErr); + llvm::LLVMRemarkFileHandle optRecordFile = std::move(*optRecordFileOrErr); if (optRecordFile) { optRecordFile->keep(); diff --git a/llvm/docs/Remarks.rst b/llvm/docs/Remarks.rst index c89940f9ff4d5..67ed94d9740f4 100644 --- a/llvm/docs/Remarks.rst +++ b/llvm/docs/Remarks.rst @@ -152,26 +152,6 @@ Other tools that support remarks: .. option:: -opt-remarks-format= .. option:: -opt-remarks-with-hotness -Serialization modes -=================== - -There are two modes available for serializing remarks: - -``Separate`` - - In this mode, the remarks and the metadata are serialized separately. The - client is responsible for parsing the metadata first, then use the metadata - to correctly parse the remarks. - -``Standalone`` - - In this mode, the remarks and the metadata are serialized to the same - stream. The metadata will always come before the remarks. - - The compiler does not support emitting standalone remarks. This mode is - more suited for post-processing tools like linkers, that can merge the - remarks for one whole project. - .. _yamlremarks: YAML remarks @@ -374,27 +354,11 @@ This block can contain the following records: The remark container -------------------- -Bitstream remarks are designed to be used in two different modes: - -``The separate mode`` - - The separate mode is the mode that is typically used during compilation. It - provides a way to serialize the remark entries to a stream while some - metadata is kept in memory to be emitted in the product of the compilation - (typically, an object file). - -``The standalone mode`` - - The standalone mode is typically stored and used after the distribution of - a program. It contains all the information that allows the parsing of all - the remarks without having any external dependencies. - -In order to support multiple modes, the format introduces the concept of a -bitstream remark container type. +The bitstream remark container supports multiple types: -.. _bitstreamremarksseparateremarksmeta: +.. _bitstreamremarksfileexternal: -``SeparateRemarksMeta: the metadata emitted separately`` +``RemarksFileExternal: a link to an external remarks file`` This container type expects only a :ref:`META_BLOCK ` containing only: @@ -406,84 +370,33 @@ bitstream remark container type. clients to retrieve remarks and their associated metadata directly from intermediate products. -``SeparateRemarksFile: the remark entries emitted separately`` + The container versions of the external separate container should match in order to + have a well-formed file. - This container type expects only a :ref:`META_BLOCK ` containing only: - - * :ref:`RECORD_META_CONTAINER_INFO ` - * :ref:`RECORD_META_REMARK_VERSION ` +.. _bitstreamremarksfile: - This container type expects 0 or more :ref:`REMARK_BLOCK `. +``RemarksFile: a standalone remarks file`` - Typically, this is emitted in a side-file alongside an object file, and is - made to be able to stream to without increasing the memory consumption of - the compiler. This is referenced by the :ref:`RECORD_META_EXTERNAL_FILE - ` entry in the - :ref:`SeparateRemarksMeta ` container. + This container type expects a :ref:`META_BLOCK ` containing only: -When the parser tries to parse a container that contains the metadata for the -separate remarks, it should parse the version and type, then keep the string -table in memory while opening the external file, validating its metadata and -parsing the remark entries. + * :ref:`RECORD_META_CONTAINER_INFO ` + * :ref:`RECORD_META_REMARK_VERSION ` -The container versions from the separate container should match in order to -have a well-formed file. + Then, this container type expects 1 or more :ref:`REMARK_BLOCK `. + If no remarks are emitted, the meta blocks are also not emitted, so the file is empty. -``Standalone: the metadata and the remark entries emitted together`` + After the remark blocks, another :ref:`META_BLOCK ` is emitted, containing: + * :ref:`RECORD_META_STRTAB ` - This container type expects only a :ref:`META_BLOCK ` containing only: + When the parser reads this container type, it jumps to the end of the file + to read the string table before parsing the individual remarks. - * :ref:`RECORD_META_CONTAINER_INFO ` - * :ref:`RECORD_META_REMARK_VERSION ` - * :ref:`RECORD_META_STRTAB ` + Standalone remarks files can be referenced by the + :ref:`RECORD_META_EXTERNAL_FILE ` + entry in the :ref:`RemarksFileExternal + ` container. - This container type expects 0 or more :ref:`REMARK_BLOCK `. - -A complete output of :program:`llvm-bcanalyzer` on the different container types: - -``SeparateRemarksMeta`` - -.. code-block:: none - - - - - blob data = 'pass\\x00key\\x00value\\x00' - blob data = '/path/to/file/name' - - -``SeparateRemarksFile`` - -.. code-block:: none - - - - - - - - - - - - - -``Standalone`` - -.. code-block:: none - - - - - - blob data = 'pass\\x00remark\\x00function\\x00path\\x00key\\x00value\\x00argpath\\x00' - - - - - - - +.. FIXME: Add complete output of :program:`llvm-bcanalyzer` on the different container types (once format changes are completed) opt-viewer ========== diff --git a/llvm/include/llvm/IR/LLVMRemarkStreamer.h b/llvm/include/llvm/IR/LLVMRemarkStreamer.h index 376acdec49fbb..5463d358e8ca7 100644 --- a/llvm/include/llvm/IR/LLVMRemarkStreamer.h +++ b/llvm/include/llvm/IR/LLVMRemarkStreamer.h @@ -17,6 +17,7 @@ #include "llvm/Remarks/Remark.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Error.h" +#include "llvm/Support/ToolOutputFile.h" #include #include #include @@ -82,20 +83,81 @@ struct LLVMRemarkSetupFormatError LLVMRemarkSetupFormatError>::LLVMRemarkSetupErrorInfo; }; -/// Setup optimization remarks that output to a file. -LLVM_ABI Expected> setupLLVMOptimizationRemarks( +/// RAII handle that manages the lifetime of the ToolOutputFile used to output +/// remarks. On destruction (or when calling releaseFile()), this handle ensures +/// that the optimization remarks are finalized and the RemarkStreamer is +/// correctly deregistered from the LLVMContext. +class LLVMRemarkFileHandle final { + struct Finalizer { + LLVMContext *Context; + + Finalizer(LLVMContext *Ctx) : Context(Ctx) {} + + Finalizer(const Finalizer &) = delete; + Finalizer &operator=(const Finalizer &) = delete; + + Finalizer(Finalizer &&Other) : Context(Other.Context) { + Other.Context = nullptr; + } + + Finalizer &operator=(Finalizer &&Other) { + std::swap(Context, Other.Context); + return *this; + } + + ~Finalizer() { finalize(); } + + LLVM_ABI void finalize(); + }; + + std::unique_ptr OutputFile; + Finalizer Finalize; + +public: + LLVMRemarkFileHandle() : OutputFile(nullptr), Finalize(nullptr) {} + + LLVMRemarkFileHandle(std::unique_ptr OutputFile, + LLVMContext &Ctx) + : OutputFile(std::move(OutputFile)), Finalize(&Ctx) {} + + ToolOutputFile *get() { return OutputFile.get(); } + explicit operator bool() { return bool(OutputFile); } + + /// Finalize remark emission and release the underlying ToolOutputFile. + std::unique_ptr releaseFile() { + finalize(); + return std::move(OutputFile); + } + + void finalize() { Finalize.finalize(); } + + ToolOutputFile &operator*() { return *OutputFile; } + ToolOutputFile *operator->() { return &*OutputFile; } +}; + +/// Setup optimization remarks that output to a file. The LLVMRemarkFileHandle +/// manages the lifetime of the underlying ToolOutputFile to ensure \ref +/// finalizeLLVMOptimizationRemarks() is called before the file is destroyed or +/// released from the handle. The handle must be kept alive until all remarks +/// were emitted through the remark streamer. +LLVM_ABI Expected setupLLVMOptimizationRemarks( LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, StringRef RemarksFormat, bool RemarksWithHotness, std::optional RemarksHotnessThreshold = 0); /// Setup optimization remarks that output directly to a raw_ostream. -/// \p OS is managed by the caller and should be open for writing as long as \p -/// Context is streaming remarks to it. +/// \p OS is managed by the caller and must be open for writing until +/// \ref finalizeLLVMOptimizationRemarks() is called. LLVM_ABI Error setupLLVMOptimizationRemarks( LLVMContext &Context, raw_ostream &OS, StringRef RemarksPasses, StringRef RemarksFormat, bool RemarksWithHotness, std::optional RemarksHotnessThreshold = 0); +/// Finalize optimization remarks and deregister the RemarkStreamer from the \p +/// Context. This must be called before closing the (file) stream that was used +/// to setup the remarks. +LLVM_ABI void finalizeLLVMOptimizationRemarks(LLVMContext &Context); + } // end namespace llvm #endif // LLVM_IR_LLVMREMARKSTREAMER_H diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h index 323c478691a92..3a9a7f7c25859 100644 --- a/llvm/include/llvm/LTO/LTO.h +++ b/llvm/include/llvm/LTO/LTO.h @@ -15,6 +15,7 @@ #ifndef LLVM_LTO_LTO_H #define LLVM_LTO_LTO_H +#include "llvm/IR/LLVMRemarkStreamer.h" #include "llvm/Support/Compiler.h" #include @@ -91,7 +92,7 @@ LLVM_ABI std::string getThinLTOOutputFile(StringRef Path, StringRef OldPrefix, StringRef NewPrefix); /// Setup optimization remarks. -LLVM_ABI Expected> setupLLVMOptimizationRemarks( +LLVM_ABI Expected setupLLVMOptimizationRemarks( LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, StringRef RemarksFormat, bool RemarksWithHotness, std::optional RemarksHotnessThreshold = 0, int Count = -1); @@ -579,7 +580,7 @@ class LTO { DenseSet DynamicExportSymbols; // Diagnostic optimization remarks file - std::unique_ptr DiagnosticOutputFile; + LLVMRemarkFileHandle DiagnosticOutputFile; }; /// The resolution for a symbol. The linker must provide a SymbolResolution for diff --git a/llvm/include/llvm/LTO/LTOBackend.h b/llvm/include/llvm/LTO/LTOBackend.h index 86b488c764e06..48ad5aa64f61f 100644 --- a/llvm/include/llvm/LTO/LTOBackend.h +++ b/llvm/include/llvm/LTO/LTOBackend.h @@ -65,8 +65,7 @@ thinBackend(const Config &C, unsigned Task, AddStreamFn AddStream, Module &M, AddStreamFn IRAddStream = nullptr, const std::vector &CmdArgs = std::vector()); -LLVM_ABI Error -finalizeOptimizationRemarks(std::unique_ptr DiagOutputFile); +LLVM_ABI Error finalizeOptimizationRemarks(LLVMRemarkFileHandle DiagOutputFile); /// Returns the BitcodeModule that is ThinLTO. LLVM_ABI BitcodeModule *findThinLTOModule(MutableArrayRef BMs); diff --git a/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h b/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h index 806d3c5bdfd77..caff198358caa 100644 --- a/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h +++ b/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h @@ -244,7 +244,7 @@ struct LTOCodeGenerator { bool ShouldInternalize = EnableLTOInternalization; bool ShouldEmbedUselists = false; bool ShouldRestoreGlobalsLinkage = false; - std::unique_ptr DiagnosticOutputFile; + LLVMRemarkFileHandle DiagnosticOutputFile; std::unique_ptr StatsFile = nullptr; std::string SaveIRBeforeOptPath; diff --git a/llvm/include/llvm/Remarks/BitstreamRemarkContainer.h b/llvm/include/llvm/Remarks/BitstreamRemarkContainer.h index 48a148a3adc13..d4b70e54bf6bc 100644 --- a/llvm/include/llvm/Remarks/BitstreamRemarkContainer.h +++ b/llvm/include/llvm/Remarks/BitstreamRemarkContainer.h @@ -23,35 +23,35 @@ namespace remarks { /// The current version of the remark container. /// Note: this is different from the version of the remark entry. -constexpr uint64_t CurrentContainerVersion = 0; +constexpr uint64_t CurrentContainerVersion = 1; /// The magic number used for identifying remark blocks. constexpr StringLiteral ContainerMagic("RMRK"); /// Type of the remark container. -/// The remark container has two modes: -/// * separate: the metadata is separate from the remarks and points to the -/// auxiliary file that contains the remarks. -/// * standalone: the metadata and the remarks are emitted together. enum class BitstreamRemarkContainerType { - /// The metadata emitted separately. - /// This will contain the following: - /// * Container version and type - /// * String table - /// * External file - SeparateRemarksMeta, - /// The remarks emitted separately. - /// This will contain the following: - /// * Container version and type - /// * Remark version - SeparateRemarksFile, - /// Everything is emitted together. - /// This will contain the following: - /// * Container version and type - /// * Remark version - /// * String table - Standalone, - First = SeparateRemarksMeta, - Last = Standalone, + /// Emit a link to an external remarks file + /// (usually as a section of the object file, to enable discovery of all + /// remarks files from the final linked object file) + /// RemarksFileExternal: + /// | Meta: + /// | | Container info + /// | | External file + RemarksFileExternal, + /// Emit metadata and remarks into a file + /// RemarksFile: + /// | Meta: + /// | | Container info + /// | | Remark version + /// | Remarks: + /// | | Remark0 + /// | | Remark1 + /// | | Remark2 + /// | | ... + /// | Late Meta: + /// | | String table + RemarksFile, + First = RemarksFileExternal, + Last = RemarksFile }; /// The possible blocks that will be encountered in a bitstream remark diff --git a/llvm/include/llvm/Remarks/BitstreamRemarkSerializer.h b/llvm/include/llvm/Remarks/BitstreamRemarkSerializer.h index 6236800337508..76e2d5b4fd3bc 100644 --- a/llvm/include/llvm/Remarks/BitstreamRemarkSerializer.h +++ b/llvm/include/llvm/Remarks/BitstreamRemarkSerializer.h @@ -27,31 +27,7 @@ struct Remarks; /// Serialize the remarks to LLVM bitstream. /// This class provides ways to emit remarks in the LLVM bitstream format and /// its associated metadata. -/// -/// * The separate model: -/// Separate meta: | Container info -/// | String table -/// | External file -/// -/// Separate remarks: | Container info -/// | Remark version -/// | Remark0 -/// | Remark1 -/// | Remark2 -/// | ... -/// -/// * The standalone model: | Container info -/// | String table -/// | Remark version -/// | Remark0 -/// | Remark1 -/// | Remark2 -/// | ... -/// struct BitstreamRemarkSerializerHelper { - /// Buffer used for encoding the bitstream before writing it to the final - /// stream. - SmallVector Encoded; /// Buffer used to construct records and pass to the bitstream writer. SmallVector R; /// The Bitstream writer. @@ -73,7 +49,8 @@ struct BitstreamRemarkSerializerHelper { uint64_t RecordRemarkArgWithDebugLocAbbrevID = 0; uint64_t RecordRemarkArgWithoutDebugLocAbbrevID = 0; - BitstreamRemarkSerializerHelper(BitstreamRemarkContainerType ContainerType); + BitstreamRemarkSerializerHelper(BitstreamRemarkContainerType ContainerType, + raw_ostream &OS); // Disable copy and move: Bitstream points to Encoded, which needs special // handling during copy/move, but moving the vectors is probably useless @@ -104,20 +81,15 @@ struct BitstreamRemarkSerializerHelper { /// The block info for the remarks block. void setupRemarkBlockInfo(); - /// Emit the metadata for the remarks. - void emitMetaBlock(uint64_t ContainerVersion, - std::optional RemarkVersion, - std::optional StrTab = std::nullopt, - std::optional Filename = std::nullopt); + /// Emit the main metadata at the beginning of the file + void emitMetaBlock(std::optional Filename = std::nullopt); + + /// Emit the remaining metadata at the end of the file. Here we emit metadata + /// that is only known once all remarks were emitted. + void emitLateMetaBlock(const StringTable &StrTab); /// Emit a remark block. The string table is required. - void emitRemarkBlock(const Remark &Remark, StringTable &StrTab); - /// Finalize the writing to \p OS. - void flushToStream(raw_ostream &OS); - /// Finalize the writing to a buffer. - /// The contents of the buffer remain valid for the lifetime of the object. - /// Any call to any other function in this class will invalidate the buffer. - StringRef getBuffer(); + void emitRemark(const Remark &Remark, StringTable &StrTab); }; /// Implementation of the remark serializer using LLVM bitstream. @@ -127,68 +99,57 @@ struct BitstreamRemarkSerializer : public RemarkSerializer { /// 2) The metadata block that contains various information about the remarks /// in the file. /// 3) A number of remark blocks. + /// 4) Another metadata block for metadata that is only finalized once all + /// remarks were emitted (e.g. StrTab) - /// We need to set up 1) and 2) first, so that we can emit 3) after. This flag - /// is used to emit the first two blocks only once. - bool DidSetUp = false; - /// The helper to emit bitstream. - BitstreamRemarkSerializerHelper Helper; + /// The helper to emit bitstream. This is nullopt when the Serializer has not + /// been setup yet. + std::optional Helper; /// Construct a serializer that will create its own string table. - BitstreamRemarkSerializer(raw_ostream &OS, SerializerMode Mode); + BitstreamRemarkSerializer(raw_ostream &OS); /// Construct a serializer with a pre-filled string table. - BitstreamRemarkSerializer(raw_ostream &OS, SerializerMode Mode, - StringTable StrTab); + BitstreamRemarkSerializer(raw_ostream &OS, StringTable StrTab); + + ~BitstreamRemarkSerializer() override; /// Emit a remark to the stream. This also emits the metadata associated to - /// the remarks based on the SerializerMode specified at construction. - /// This writes the serialized output to the provided stream. + /// the remarks. This writes the serialized output to the provided stream. void emit(const Remark &Remark) override; + + /// Finalize emission of remarks. This emits the late metadata block and + /// flushes internal buffers. It is safe to call this function multiple times, + /// and it is automatically executed on destruction of the Serializer. + void finalize() override; + /// The metadata serializer associated to this remark serializer. Based on the /// container type of the current serializer, the container type of the /// metadata serializer will change. - std::unique_ptr metaSerializer( - raw_ostream &OS, - std::optional ExternalFilename = std::nullopt) override; + std::unique_ptr + metaSerializer(raw_ostream &OS, StringRef ExternalFilename) override; static bool classof(const RemarkSerializer *S) { return S->SerializerFormat == Format::Bitstream; } + +private: + void setup(); }; /// Serializer of metadata for bitstream remarks. struct BitstreamMetaSerializer : public MetaSerializer { - /// This class can be used with [1] a pre-constructed - /// BitstreamRemarkSerializerHelper, or with [2] one that is owned by the meta - /// serializer. In case of [1], we need to be able to store a reference to the - /// object, while in case of [2] we need to store the whole object. - std::optional TmpHelper; - /// The actual helper, that can point to \p TmpHelper or to an external helper - /// object. - BitstreamRemarkSerializerHelper *Helper = nullptr; - - std::optional StrTab; - std::optional ExternalFilename; + std::optional Helper; + + StringRef ExternalFilename; /// Create a new meta serializer based on \p ContainerType. - BitstreamMetaSerializer( - raw_ostream &OS, BitstreamRemarkContainerType ContainerType, - std::optional StrTab = std::nullopt, - std::optional ExternalFilename = std::nullopt) - : MetaSerializer(OS), TmpHelper(std::nullopt), Helper(nullptr), - StrTab(StrTab), ExternalFilename(ExternalFilename) { - TmpHelper.emplace(ContainerType); - Helper = &*TmpHelper; + BitstreamMetaSerializer(raw_ostream &OS, + BitstreamRemarkContainerType ContainerType, + StringRef ExternalFilename) + : MetaSerializer(OS), ExternalFilename(ExternalFilename) { + Helper.emplace(ContainerType, OS); } - /// Create a new meta serializer based on a previously built \p Helper. - BitstreamMetaSerializer( - raw_ostream &OS, BitstreamRemarkSerializerHelper &Helper, - std::optional StrTab = std::nullopt, - std::optional ExternalFilename = std::nullopt) - : MetaSerializer(OS), TmpHelper(std::nullopt), Helper(&Helper), - StrTab(StrTab), ExternalFilename(ExternalFilename) {} - void emit() override; }; diff --git a/llvm/include/llvm/Remarks/RemarkSerializer.h b/llvm/include/llvm/Remarks/RemarkSerializer.h index 05ef14ae5566b..1785152b87c70 100644 --- a/llvm/include/llvm/Remarks/RemarkSerializer.h +++ b/llvm/include/llvm/Remarks/RemarkSerializer.h @@ -26,16 +26,6 @@ namespace remarks { struct Remark; -enum class SerializerMode { - Separate, // A mode where the metadata is serialized separately from the - // remarks. Typically, this is used when the remarks need to be - // streamed to a side file and the metadata is embedded into the - // final result of the compilation. - Standalone // A mode where everything can be retrieved in the same - // file/buffer. Typically, this is used for storing remarks for - // later use. -}; - struct MetaSerializer; /// This is the base class for a remark serializer. @@ -45,24 +35,27 @@ struct RemarkSerializer { Format SerializerFormat; /// The open raw_ostream that the remark diagnostics are emitted to. raw_ostream &OS; - /// The serialization mode. - SerializerMode Mode; /// The string table containing all the unique strings used in the output. /// The table can be serialized to be consumed after the compilation. std::optional StrTab; - RemarkSerializer(Format SerializerFormat, raw_ostream &OS, - SerializerMode Mode) - : SerializerFormat(SerializerFormat), OS(OS), Mode(Mode) {} + RemarkSerializer(Format SerializerFormat, raw_ostream &OS) + : SerializerFormat(SerializerFormat), OS(OS) {} - /// This is just an interface. virtual ~RemarkSerializer() = default; + + /// Finalize remark emission (e.g. finish writing metadata, flush internal + /// buffers). It is safe to call this function multiple times, and it should + /// have the same behavior as destructing the RemarkSerializer. + /// After finalizing, the behavior of emit is unspecified. + virtual void finalize() {} + /// Emit a remark to the stream. virtual void emit(const Remark &Remark) = 0; + /// Return the corresponding metadata serializer. virtual std::unique_ptr - metaSerializer(raw_ostream &OS, - std::optional ExternalFilename = std::nullopt) = 0; + metaSerializer(raw_ostream &OS, StringRef ExternalFilename) = 0; }; /// This is the base class for a remark metadata serializer. @@ -79,13 +72,12 @@ struct MetaSerializer { /// Create a remark serializer. LLVM_ABI Expected> -createRemarkSerializer(Format RemarksFormat, SerializerMode Mode, - raw_ostream &OS); +createRemarkSerializer(Format RemarksFormat, raw_ostream &OS); /// Create a remark serializer that uses a pre-filled string table. LLVM_ABI Expected> -createRemarkSerializer(Format RemarksFormat, SerializerMode Mode, - raw_ostream &OS, remarks::StringTable StrTab); +createRemarkSerializer(Format RemarksFormat, raw_ostream &OS, + remarks::StringTable StrTab); } // end namespace remarks } // end namespace llvm diff --git a/llvm/include/llvm/Remarks/RemarkStreamer.h b/llvm/include/llvm/Remarks/RemarkStreamer.h index 5b1cc81cdbf50..dd5bfcbc7ff99 100644 --- a/llvm/include/llvm/Remarks/RemarkStreamer.h +++ b/llvm/include/llvm/Remarks/RemarkStreamer.h @@ -52,6 +52,7 @@ class RemarkStreamer final { public: RemarkStreamer(std::unique_ptr RemarkSerializer, std::optional Filename = std::nullopt); + ~RemarkStreamer(); /// Return the filename that the remark diagnostics are emitted to. std::optional getFilename() const { @@ -61,6 +62,14 @@ class RemarkStreamer final { raw_ostream &getStream() { return RemarkSerializer->OS; } /// Return the serializer used for this stream. remarks::RemarkSerializer &getSerializer() { return *RemarkSerializer; } + + /// Release the underlying RemarkSerializer. Destructing the RemarkStreamer + /// will assert that the RemarkStreamer has been released, to ensure that the + /// remarks were properly finalized. + std::unique_ptr releaseSerializer() { + return std::move(RemarkSerializer); + } + /// Set a pass filter based on a regex \p Filter. /// Returns an error if the regex is invalid. Error setFilter(StringRef Filter); diff --git a/llvm/include/llvm/Remarks/YAMLRemarkSerializer.h b/llvm/include/llvm/Remarks/YAMLRemarkSerializer.h index d80464c0fe74a..69b8f9f000e1d 100644 --- a/llvm/include/llvm/Remarks/YAMLRemarkSerializer.h +++ b/llvm/include/llvm/Remarks/YAMLRemarkSerializer.h @@ -36,28 +36,22 @@ struct LLVM_ABI YAMLRemarkSerializer : public RemarkSerializer { /// The YAML streamer. yaml::Output YAMLOutput; - YAMLRemarkSerializer(raw_ostream &OS, SerializerMode Mode, - std::optional StrTab = std::nullopt); + YAMLRemarkSerializer(raw_ostream &OS); + YAMLRemarkSerializer(raw_ostream &OS, StringTable StrTabIn); void emit(const Remark &Remark) override; - std::unique_ptr metaSerializer( - raw_ostream &OS, - std::optional ExternalFilename = std::nullopt) override; + std::unique_ptr + metaSerializer(raw_ostream &OS, StringRef ExternalFilename) override; static bool classof(const RemarkSerializer *S) { return S->SerializerFormat == Format::YAML; } - -protected: - YAMLRemarkSerializer(Format SerializerFormat, raw_ostream &OS, - SerializerMode Mode, - std::optional StrTab = std::nullopt); }; struct LLVM_ABI YAMLMetaSerializer : public MetaSerializer { - std::optional ExternalFilename; + StringRef ExternalFilename; - YAMLMetaSerializer(raw_ostream &OS, std::optional ExternalFilename) + YAMLMetaSerializer(raw_ostream &OS, StringRef ExternalFilename) : MetaSerializer(OS), ExternalFilename(ExternalFilename) {} void emit() override; diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index cd14a4f57f760..57fdc8b7c5ffc 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -78,6 +78,7 @@ #include "llvm/IR/GlobalValue.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instruction.h" +#include "llvm/IR/LLVMRemarkStreamer.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" @@ -2508,6 +2509,8 @@ void AsmPrinter::emitGlobalIFunc(Module &M, const GlobalIFunc &GI) { void AsmPrinter::emitRemarksSection(remarks::RemarkStreamer &RS) { if (!RS.needsSection()) return; + if (!RS.getFilename()) + return; MCSection *RemarksSection = OutContext.getObjectFileInfo()->getRemarksSection(); @@ -2518,20 +2521,16 @@ void AsmPrinter::emitRemarksSection(remarks::RemarkStreamer &RS) { return; } - remarks::RemarkSerializer &RemarkSerializer = RS.getSerializer(); - - std::optional> Filename; - if (std::optional FilenameRef = RS.getFilename()) { - Filename = *FilenameRef; - sys::fs::make_absolute(*Filename); - assert(!Filename->empty() && "The filename can't be empty."); - } + SmallString<128> Filename = *RS.getFilename(); + sys::fs::make_absolute(Filename); + assert(!Filename.empty() && "The filename can't be empty."); std::string Buf; raw_string_ostream OS(Buf); + + remarks::RemarkSerializer &RemarkSerializer = RS.getSerializer(); std::unique_ptr MetaSerializer = - Filename ? RemarkSerializer.metaSerializer(OS, Filename->str()) - : RemarkSerializer.metaSerializer(OS); + RemarkSerializer.metaSerializer(OS, Filename); MetaSerializer->emit(); // Switch to the remarks section. diff --git a/llvm/lib/IR/LLVMRemarkStreamer.cpp b/llvm/lib/IR/LLVMRemarkStreamer.cpp index 71f8d4a4b1c7c..9e1e45998f2f1 100644 --- a/llvm/lib/IR/LLVMRemarkStreamer.cpp +++ b/llvm/lib/IR/LLVMRemarkStreamer.cpp @@ -92,7 +92,7 @@ char LLVMRemarkSetupFileError::ID = 0; char LLVMRemarkSetupPatternError::ID = 0; char LLVMRemarkSetupFormatError::ID = 0; -Expected> llvm::setupLLVMOptimizationRemarks( +Expected llvm::setupLLVMOptimizationRemarks( LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, StringRef RemarksFormat, bool RemarksWithHotness, std::optional RemarksHotnessThreshold) { @@ -102,7 +102,7 @@ Expected> llvm::setupLLVMOptimizationRemarks( Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold); if (RemarksFilename.empty()) - return nullptr; + return LLVMRemarkFileHandle(); Expected Format = remarks::parseFormat(RemarksFormat); if (Error E = Format.takeError()) @@ -119,24 +119,35 @@ Expected> llvm::setupLLVMOptimizationRemarks( return make_error(errorCodeToError(EC)); Expected> RemarkSerializer = - remarks::createRemarkSerializer( - *Format, remarks::SerializerMode::Separate, RemarksFile->os()); + remarks::createRemarkSerializer(*Format, RemarksFile->os()); if (Error E = RemarkSerializer.takeError()) return make_error(std::move(E)); - // Create the main remark streamer. - Context.setMainRemarkStreamer(std::make_unique( - std::move(*RemarkSerializer), RemarksFilename)); + auto RS = std::make_unique( + std::move(*RemarkSerializer), RemarksFilename); + + if (!RemarksPasses.empty()) + if (Error E = RS->setFilter(RemarksPasses)) { + RS->releaseSerializer(); + return make_error(std::move(E)); + } + + // Install the main remark streamer. Only install this after setting the + // filter, because this might fail. + Context.setMainRemarkStreamer(std::move(RS)); // Create LLVM's optimization remarks streamer. Context.setLLVMRemarkStreamer( std::make_unique(*Context.getMainRemarkStreamer())); - if (!RemarksPasses.empty()) - if (Error E = Context.getMainRemarkStreamer()->setFilter(RemarksPasses)) - return make_error(std::move(E)); + return LLVMRemarkFileHandle{std::move(RemarksFile), Context}; +} - return std::move(RemarksFile); +void LLVMRemarkFileHandle::Finalizer::finalize() { + if (!Context) + return; + finalizeLLVMOptimizationRemarks(*Context); + Context = nullptr; } Error llvm::setupLLVMOptimizationRemarks( @@ -153,22 +164,34 @@ Error llvm::setupLLVMOptimizationRemarks( return make_error(std::move(E)); Expected> RemarkSerializer = - remarks::createRemarkSerializer(*Format, - remarks::SerializerMode::Separate, OS); + remarks::createRemarkSerializer(*Format, OS); if (Error E = RemarkSerializer.takeError()) return make_error(std::move(E)); - // Create the main remark streamer. - Context.setMainRemarkStreamer( - std::make_unique(std::move(*RemarkSerializer))); + auto RS = + std::make_unique(std::move(*RemarkSerializer)); + + if (!RemarksPasses.empty()) + if (Error E = RS->setFilter(RemarksPasses)) { + RS->releaseSerializer(); + return make_error(std::move(E)); + } + + // Install the main remark streamer. Only install this after setting the + // filter, because this might fail. + Context.setMainRemarkStreamer(std::move(RS)); // Create LLVM's optimization remarks streamer. Context.setLLVMRemarkStreamer( std::make_unique(*Context.getMainRemarkStreamer())); - if (!RemarksPasses.empty()) - if (Error E = Context.getMainRemarkStreamer()->setFilter(RemarksPasses)) - return make_error(std::move(E)); - return Error::success(); } + +void llvm::finalizeLLVMOptimizationRemarks(LLVMContext &Context) { + Context.setLLVMRemarkStreamer(nullptr); + if (auto *RS = Context.getMainRemarkStreamer()) { + RS->releaseSerializer(); + Context.setMainRemarkStreamer(nullptr); + } +} diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp index ce9ecc35e1922..7b252627d73f9 100644 --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -1290,11 +1290,11 @@ void lto::updateMemProfAttributes(Module &Mod, Error LTO::runRegularLTO(AddStreamFn AddStream) { llvm::TimeTraceScope timeScope("Run regular LTO"); + LLVMContext &CombinedCtx = RegularLTO.CombinedModule->getContext(); // Setup optimization remarks. auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks( - RegularLTO.CombinedModule->getContext(), Conf.RemarksFilename, - Conf.RemarksPasses, Conf.RemarksFormat, Conf.RemarksWithHotness, - Conf.RemarksHotnessThreshold); + CombinedCtx, Conf.RemarksFilename, Conf.RemarksPasses, Conf.RemarksFormat, + Conf.RemarksWithHotness, Conf.RemarksHotnessThreshold); LLVM_DEBUG(dbgs() << "Running regular LTO\n"); if (!DiagFileOrErr) return DiagFileOrErr.takeError(); @@ -2177,7 +2177,7 @@ Error LTO::runThinLTO(AddStreamFn AddStream, FileCache Cache, return RunBackends(SecondRoundLTO.get()); } -Expected> lto::setupLLVMOptimizationRemarks( +Expected lto::setupLLVMOptimizationRemarks( LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, StringRef RemarksFormat, bool RemarksWithHotness, std::optional RemarksHotnessThreshold, int Count) { diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp index ce42fc526beac..c126e8efe82b3 100644 --- a/llvm/lib/LTO/LTOBackend.cpp +++ b/llvm/lib/LTO/LTOBackend.cpp @@ -540,12 +540,12 @@ static Expected initAndLookupTarget(const Config &C, return T; } -Error lto::finalizeOptimizationRemarks( - std::unique_ptr DiagOutputFile) { +Error lto::finalizeOptimizationRemarks(LLVMRemarkFileHandle DiagOutputFile) { // Make sure we flush the diagnostic remarks file in case the linker doesn't // call the global destructors before exiting. if (!DiagOutputFile) return Error::success(); + DiagOutputFile.finalize(); DiagOutputFile->keep(); DiagOutputFile->os().flush(); return Error::success(); @@ -640,7 +640,7 @@ Error lto::thinBackend(const Config &Conf, unsigned Task, AddStreamFn AddStream, auto OptimizeAndCodegen = [&](Module &Mod, TargetMachine *TM, - std::unique_ptr DiagnosticOutputFile) { + LLVMRemarkFileHandle DiagnosticOutputFile) { // Perform optimization and code generation for ThinLTO. if (!opt(Conf, TM, Task, Mod, /*IsThinLTO=*/true, /*ExportSummary=*/nullptr, /*ImportSummary=*/&CombinedIndex, diff --git a/llvm/lib/LTO/LTOCodeGenerator.cpp b/llvm/lib/LTO/LTOCodeGenerator.cpp index d8a96f73110fd..8aa404da15286 100644 --- a/llvm/lib/LTO/LTOCodeGenerator.cpp +++ b/llvm/lib/LTO/LTOCodeGenerator.cpp @@ -545,6 +545,7 @@ void LTOCodeGenerator::finishOptimizationRemarks() { if (DiagnosticOutputFile) { DiagnosticOutputFile->keep(); // FIXME: LTOCodeGenerator dtor is not invoked on Darwin + DiagnosticOutputFile.finalize(); DiagnosticOutputFile->os().flush(); } } diff --git a/llvm/lib/Remarks/BitstreamRemarkParser.cpp b/llvm/lib/Remarks/BitstreamRemarkParser.cpp index d40b40dfb2ba0..2b27a0f661d88 100644 --- a/llvm/lib/Remarks/BitstreamRemarkParser.cpp +++ b/llvm/lib/Remarks/BitstreamRemarkParser.cpp @@ -197,14 +197,9 @@ Error BitstreamRemarkParserHelper::parseNext() { Loc.reset(); Args.clear(); - if (Error E = expectBlock()) - return E; return parseBlock(); } -BitstreamParserHelper::BitstreamParserHelper(StringRef Buffer) - : Stream(Buffer) {} - Error BitstreamParserHelper::expectMagic() { std::array Result; for (unsigned I = 0; I < 4; ++I) @@ -244,14 +239,57 @@ Error BitstreamParserHelper::parseBlockInfoBlock() { return Error::success(); } -Error BitstreamParserHelper::advanceToMetaBlock() { +Error BitstreamParserHelper::parseMeta() { if (Error E = expectMagic()) return E; if (Error E = parseBlockInfoBlock()) return E; + + // Parse early meta block + if (Error E = MetaHelper.expectBlock()) + return E; + if (Error E = MetaHelper.parseBlock()) + return E; + + // Skip all Remarks blocks + while (!Stream.AtEndOfStream()) { + auto MaybeBlockID = expectSubBlock(Stream); + if (!MaybeBlockID) + return MaybeBlockID.takeError(); + if (*MaybeBlockID == META_BLOCK_ID) + break; + if (*MaybeBlockID != REMARK_BLOCK_ID) + return error("Unexpected block between meta blocks."); + // Remember first remark block + if (!RemarkStartBitPos) + RemarkStartBitPos = Stream.GetCurrentBitNo(); + if (Error E = Stream.SkipBlock()) + return E; + } + + // Late meta block is optional if there are no remarks. + if (Stream.AtEndOfStream()) + return Error::success(); + + // Parse late meta block + if (Error E = MetaHelper.parseBlock()) + return E; return Error::success(); } +Error BitstreamParserHelper::parseRemark() { + if (RemarkStartBitPos) { + RemarkStartBitPos.reset(); + } else { + auto MaybeBlockID = expectSubBlock(Stream); + if (!MaybeBlockID) + return MaybeBlockID.takeError(); + if (*MaybeBlockID != REMARK_BLOCK_ID) + return make_error(); + } + return RemarksHelper->parseNext(); +} + Expected> remarks::createBitstreamParserFromMeta( StringRef Buf, std::optional ExternalFilePrependPath) { @@ -263,45 +301,52 @@ remarks::createBitstreamParserFromMeta( return std::move(Parser); } +BitstreamRemarkParser::BitstreamRemarkParser(StringRef Buf) + : RemarkParser(Format::Bitstream), ParserHelper(Buf) {} + Expected> BitstreamRemarkParser::next() { - if (ParserHelper.atEndOfStream()) - return make_error(); + if (!IsMetaReady) { + // Container is completely empty + if (ParserHelper->Stream.AtEndOfStream()) + return make_error(); - if (!ReadyToParseRemarks) { if (Error E = parseMeta()) return std::move(E); - ReadyToParseRemarks = true; + IsMetaReady = true; + + // Container has meta, but no remarks blocks + if (!ParserHelper->RemarkStartBitPos) + return error( + "Container is non-empty, but does not contain any remarks blocks."); + + if (Error E = + ParserHelper->Stream.JumpToBit(*ParserHelper->RemarkStartBitPos)) + return std::move(E); + ParserHelper->RemarksHelper.emplace(ParserHelper->Stream); } - return parseRemark(); + if (Error E = ParserHelper->parseRemark()) + return std::move(E); + return processRemark(); } Error BitstreamRemarkParser::parseMeta() { - if (Error E = ParserHelper.advanceToMetaBlock()) - return E; - - BitstreamMetaParserHelper MetaHelper(ParserHelper.Stream); - if (Error E = MetaHelper.expectBlock()) + if (Error E = ParserHelper->parseMeta()) return E; - if (Error E = MetaHelper.parseBlock()) - return E; - - if (Error E = processCommonMeta(MetaHelper)) + if (Error E = processCommonMeta()) return E; switch (ContainerType) { - case BitstreamRemarkContainerType::Standalone: - return processStandaloneMeta(MetaHelper); - case BitstreamRemarkContainerType::SeparateRemarksFile: - return processSeparateRemarksFileMeta(MetaHelper); - case BitstreamRemarkContainerType::SeparateRemarksMeta: - return processSeparateRemarksMetaMeta(MetaHelper); + case BitstreamRemarkContainerType::RemarksFileExternal: + return processExternalFilePath(); + case BitstreamRemarkContainerType::RemarksFile: + return processFileContainerMeta(); } llvm_unreachable("Unknown BitstreamRemarkContainerType enum"); } -Error BitstreamRemarkParser::processCommonMeta( - BitstreamMetaParserHelper &Helper) { +Error BitstreamRemarkParser::processCommonMeta() { + auto &Helper = ParserHelper->MetaHelper; if (!Helper.Container) return Helper.error("Missing container info."); auto &Container = *Helper.Container; @@ -313,7 +358,16 @@ Error BitstreamRemarkParser::processCommonMeta( return Error::success(); } -Error BitstreamRemarkParser::processStrTab(BitstreamMetaParserHelper &Helper) { +Error BitstreamRemarkParser::processFileContainerMeta() { + if (Error E = processRemarkVersion()) + return E; + if (Error E = processStrTab()) + return E; + return Error::success(); +} + +Error BitstreamRemarkParser::processStrTab() { + auto &Helper = ParserHelper->MetaHelper; if (!Helper.StrTabBuf) return Helper.error("Missing string table."); // Parse and assign the string table. @@ -321,26 +375,25 @@ Error BitstreamRemarkParser::processStrTab(BitstreamMetaParserHelper &Helper) { return Error::success(); } -Error BitstreamRemarkParser::processRemarkVersion( - BitstreamMetaParserHelper &Helper) { +Error BitstreamRemarkParser::processRemarkVersion() { + auto &Helper = ParserHelper->MetaHelper; if (!Helper.RemarkVersion) return Helper.error("Missing remark version."); RemarkVersion = *Helper.RemarkVersion; return Error::success(); } -Error BitstreamRemarkParser::processExternalFilePath( - BitstreamMetaParserHelper &Helper) { +Error BitstreamRemarkParser::processExternalFilePath() { + auto &Helper = ParserHelper->MetaHelper; if (!Helper.ExternalFilePath) return Helper.error("Missing external file path."); - StringRef ExternalFilePath = *Helper.ExternalFilePath; SmallString<80> FullPath(ExternalFilePrependPath); - sys::path::append(FullPath, ExternalFilePath); + sys::path::append(FullPath, *Helper.ExternalFilePath); // External file: open the external file, parse it, check if its metadata - // matches the one from the separate metadata, then replace the current parser - // with the one parsing the remarks. + // matches the one from the separate metadata, then replace the current + // parser with the one parsing the remarks. ErrorOr> BufferOrErr = MemoryBuffer::getFile(FullPath); if (std::error_code EC = BufferOrErr.getError()) @@ -353,58 +406,19 @@ Error BitstreamRemarkParser::processExternalFilePath( return make_error(); // Create a separate parser used for parsing the separate file. - ParserHelper = BitstreamParserHelper(TmpRemarkBuffer->getBuffer()); - // Advance and check until we can parse the meta block. - if (Error E = ParserHelper.advanceToMetaBlock()) - return E; - // Parse the meta from the separate file. - // Note: here we overwrite the BlockInfo with the one from the file. This will - // be used to parse the rest of the file. - BitstreamMetaParserHelper SeparateMetaHelper(ParserHelper.Stream); - if (Error E = SeparateMetaHelper.expectBlock()) - return E; - if (Error E = SeparateMetaHelper.parseBlock()) - return E; - - if (Error E = processCommonMeta(SeparateMetaHelper)) - return E; - - if (ContainerType != BitstreamRemarkContainerType::SeparateRemarksFile) - return SeparateMetaHelper.error("Wrong container type in external file."); - - // Process the meta from the separate file. - return processSeparateRemarksFileMeta(SeparateMetaHelper); -} - -Error BitstreamRemarkParser::processStandaloneMeta( - BitstreamMetaParserHelper &Helper) { - if (Error E = processStrTab(Helper)) + ParserHelper.emplace(TmpRemarkBuffer->getBuffer()); + if (Error E = parseMeta()) return E; - return processRemarkVersion(Helper); -} -Error BitstreamRemarkParser::processSeparateRemarksFileMeta( - BitstreamMetaParserHelper &Helper) { - return processRemarkVersion(Helper); -} + if (ContainerType != BitstreamRemarkContainerType::RemarksFile) + return ParserHelper->MetaHelper.error( + "Wrong container type in external file."); -Error BitstreamRemarkParser::processSeparateRemarksMetaMeta( - BitstreamMetaParserHelper &Helper) { - if (Error E = processStrTab(Helper)) - return E; - return processExternalFilePath(Helper); -} - -Expected> BitstreamRemarkParser::parseRemark() { - BitstreamRemarkParserHelper RemarkHelper(ParserHelper.Stream); - if (Error E = RemarkHelper.parseNext()) - return std::move(E); - - return processRemark(RemarkHelper); + return Error::success(); } -Expected> -BitstreamRemarkParser::processRemark(BitstreamRemarkParserHelper &Helper) { +Expected> BitstreamRemarkParser::processRemark() { + auto &Helper = *ParserHelper->RemarksHelper; std::unique_ptr Result = std::make_unique(); Remark &R = *Result; @@ -491,5 +505,3 @@ BitstreamRemarkParser::processRemark(BitstreamRemarkParserHelper &Helper) { return std::move(Result); } -llvm::remarks::BitstreamRemarkParser::BitstreamRemarkParser(StringRef Buf) - : RemarkParser(Format::Bitstream), ParserHelper(Buf) {} diff --git a/llvm/lib/Remarks/BitstreamRemarkParser.h b/llvm/lib/Remarks/BitstreamRemarkParser.h index d756e3296a871..1e73e44a78a84 100644 --- a/llvm/lib/Remarks/BitstreamRemarkParser.h +++ b/llvm/lib/Remarks/BitstreamRemarkParser.h @@ -187,35 +187,44 @@ struct BitstreamParserHelper { BitstreamCursor Stream; /// The block info block. BitstreamBlockInfo BlockInfo; + + BitstreamMetaParserHelper MetaHelper; + std::optional RemarksHelper; + std::optional RemarkStartBitPos; + /// Start parsing at \p Buffer. - BitstreamParserHelper(StringRef Buffer); + BitstreamParserHelper(StringRef Buffer) + : Stream(Buffer), MetaHelper(Stream), RemarksHelper(Stream) {} + /// Parse and validate the magic number. Error expectMagic(); - /// Advance to the meta block - Error advanceToMetaBlock(); /// Parse the block info block containing all the abbrevs. /// This needs to be called before calling any other parsing function. Error parseBlockInfoBlock(); - /// Return true if the parser reached the end of the stream. - bool atEndOfStream() { return Stream.AtEndOfStream(); } + + /// Parse all metadata blocks in the file. This populates the meta helper. + Error parseMeta(); + /// Parse the next remark. This populates the remark helper data. + Error parseRemark(); }; /// Parses and holds the state of the latest parsed remark. struct BitstreamRemarkParser : public RemarkParser { /// The buffer to parse. - BitstreamParserHelper ParserHelper; + std::optional ParserHelper; /// The string table used for parsing strings. std::optional StrTab; /// Temporary remark buffer used when the remarks are stored separately. std::unique_ptr TmpRemarkBuffer; + /// Whether the metadata has already been parsed, so we can continue parsing + /// remarks. + bool IsMetaReady = false; /// The common metadata used to decide how to parse the buffer. /// This is filled when parsing the metadata block. uint64_t ContainerVersion = 0; uint64_t RemarkVersion = 0; BitstreamRemarkContainerType ContainerType = - BitstreamRemarkContainerType::Standalone; - /// Wether the parser is ready to parse remarks. - bool ReadyToParseRemarks = false; + BitstreamRemarkContainerType::RemarksFile; /// Create a parser that expects to find a string table embedded in the /// stream. @@ -230,20 +239,15 @@ struct BitstreamRemarkParser : public RemarkParser { /// Parse and process the metadata of the buffer. Error parseMeta(); - /// Parse a Bitstream remark. - Expected> parseRemark(); - private: - Error processCommonMeta(BitstreamMetaParserHelper &Helper); - Error processStandaloneMeta(BitstreamMetaParserHelper &Helper); - Error processSeparateRemarksFileMeta(BitstreamMetaParserHelper &Helper); - Error processSeparateRemarksMetaMeta(BitstreamMetaParserHelper &Helper); - Error processExternalFilePath(BitstreamMetaParserHelper &Helper); - Error processStrTab(BitstreamMetaParserHelper &Helper); - Error processRemarkVersion(BitstreamMetaParserHelper &Helper); - - Expected> - processRemark(BitstreamRemarkParserHelper &Helper); + Error processCommonMeta(); + Error processFileContainerMeta(); + Error processExternalFilePath(); + + Expected> processRemark(); + + Error processStrTab(); + Error processRemarkVersion(); }; Expected> createBitstreamParserFromMeta( diff --git a/llvm/lib/Remarks/BitstreamRemarkSerializer.cpp b/llvm/lib/Remarks/BitstreamRemarkSerializer.cpp index b2627196bce62..abd436e0ee561 100644 --- a/llvm/lib/Remarks/BitstreamRemarkSerializer.cpp +++ b/llvm/lib/Remarks/BitstreamRemarkSerializer.cpp @@ -12,25 +12,23 @@ //===----------------------------------------------------------------------===// #include "llvm/Remarks/BitstreamRemarkSerializer.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/Remarks/Remark.h" +#include #include using namespace llvm; using namespace llvm::remarks; BitstreamRemarkSerializerHelper::BitstreamRemarkSerializerHelper( - BitstreamRemarkContainerType ContainerType) - : Bitstream(Encoded), ContainerType(ContainerType) {} - -static void push(SmallVectorImpl &R, StringRef Str) { - append_range(R, Str); -} + BitstreamRemarkContainerType ContainerType, raw_ostream &OS) + : Bitstream(OS), ContainerType(ContainerType) {} static void setRecordName(unsigned RecordID, BitstreamWriter &Bitstream, SmallVectorImpl &R, StringRef Str) { R.clear(); R.push_back(RecordID); - push(R, Str); + append_range(R, Str); Bitstream.EmitRecord(bitc::BLOCKINFO_CODE_SETRECORDNAME, R); } @@ -41,7 +39,7 @@ static void initBlock(unsigned BlockID, BitstreamWriter &Bitstream, Bitstream.EmitRecord(bitc::BLOCKINFO_CODE_SETBID, R); R.clear(); - push(R, Str); + append_range(R, Str); Bitstream.EmitRecord(bitc::BLOCKINFO_CODE_BLOCKNAME, R); } @@ -200,75 +198,64 @@ void BitstreamRemarkSerializerHelper::setupBlockInfo() { Bitstream.Emit(static_cast(C), 8); Bitstream.EnterBlockInfoBlock(); + auto ExitBlock = make_scope_exit([&] { Bitstream.ExitBlock(); }); // Setup the main metadata. Depending on the container type, we'll setup the // required records next. setupMetaBlockInfo(); switch (ContainerType) { - case BitstreamRemarkContainerType::SeparateRemarksMeta: - // Needs a string table that the separate remark file is using. - setupMetaStrTab(); + case BitstreamRemarkContainerType::RemarksFileExternal: // Needs to know where the external remarks file is. setupMetaExternalFile(); - break; - case BitstreamRemarkContainerType::SeparateRemarksFile: - // Contains remarks: emit the version. - setupMetaRemarkVersion(); - // Contains remarks: emit the remark abbrevs. - setupRemarkBlockInfo(); - break; - case BitstreamRemarkContainerType::Standalone: + return; + case BitstreamRemarkContainerType::RemarksFile: // Contains remarks: emit the version. setupMetaRemarkVersion(); // Needs a string table. setupMetaStrTab(); // Contains remarks: emit the remark abbrevs. setupRemarkBlockInfo(); - break; + return; } - - Bitstream.ExitBlock(); + llvm_unreachable("Unexpected BitstreamRemarkContainerType"); } void BitstreamRemarkSerializerHelper::emitMetaBlock( - uint64_t ContainerVersion, std::optional RemarkVersion, - std::optional StrTab, std::optional Filename) { // Emit the meta block Bitstream.EnterSubblock(META_BLOCK_ID, 3); + auto ExitBlock = make_scope_exit([&] { Bitstream.ExitBlock(); }); // The container version and type. R.clear(); R.push_back(RECORD_META_CONTAINER_INFO); - R.push_back(ContainerVersion); + R.push_back(CurrentContainerVersion); R.push_back(static_cast(ContainerType)); Bitstream.EmitRecordWithAbbrev(RecordMetaContainerInfoAbbrevID, R); switch (ContainerType) { - case BitstreamRemarkContainerType::SeparateRemarksMeta: - assert(StrTab != std::nullopt && *StrTab != nullptr); - emitMetaStrTab(**StrTab); + case BitstreamRemarkContainerType::RemarksFileExternal: assert(Filename != std::nullopt); emitMetaExternalFile(*Filename); - break; - case BitstreamRemarkContainerType::SeparateRemarksFile: - assert(RemarkVersion != std::nullopt); - emitMetaRemarkVersion(*RemarkVersion); - break; - case BitstreamRemarkContainerType::Standalone: - assert(RemarkVersion != std::nullopt); - emitMetaRemarkVersion(*RemarkVersion); - assert(StrTab != std::nullopt && *StrTab != nullptr); - emitMetaStrTab(**StrTab); - break; + return; + case BitstreamRemarkContainerType::RemarksFile: + emitMetaRemarkVersion(CurrentRemarkVersion); + return; } + llvm_unreachable("Unexpected BitstreamRemarkContainerType"); +} +void BitstreamRemarkSerializerHelper::emitLateMetaBlock( + const StringTable &StrTab) { + // Emit the late meta block (after all remarks are serialized) + Bitstream.EnterSubblock(META_BLOCK_ID, 3); + emitMetaStrTab(StrTab); Bitstream.ExitBlock(); } -void BitstreamRemarkSerializerHelper::emitRemarkBlock(const Remark &Remark, - StringTable &StrTab) { +void BitstreamRemarkSerializerHelper::emitRemark(const Remark &Remark, + StringTable &StrTab) { Bitstream.EnterSubblock(REMARK_BLOCK_ID, 4); R.clear(); @@ -317,73 +304,49 @@ void BitstreamRemarkSerializerHelper::emitRemarkBlock(const Remark &Remark, Bitstream.ExitBlock(); } -void BitstreamRemarkSerializerHelper::flushToStream(raw_ostream &OS) { - OS.write(Encoded.data(), Encoded.size()); - Encoded.clear(); -} - -StringRef BitstreamRemarkSerializerHelper::getBuffer() { - return StringRef(Encoded.data(), Encoded.size()); -} - -BitstreamRemarkSerializer::BitstreamRemarkSerializer(raw_ostream &OS, - SerializerMode Mode) - : RemarkSerializer(Format::Bitstream, OS, Mode), - Helper(BitstreamRemarkContainerType::SeparateRemarksFile) { - assert(Mode == SerializerMode::Separate && - "For SerializerMode::Standalone, a pre-filled string table needs to " - "be provided."); - // We always use a string table with bitstream. +BitstreamRemarkSerializer::BitstreamRemarkSerializer(raw_ostream &OS) + : RemarkSerializer(Format::Bitstream, OS) { StrTab.emplace(); } BitstreamRemarkSerializer::BitstreamRemarkSerializer(raw_ostream &OS, - SerializerMode Mode, StringTable StrTabIn) - : RemarkSerializer(Format::Bitstream, OS, Mode), - Helper(Mode == SerializerMode::Separate - ? BitstreamRemarkContainerType::SeparateRemarksFile - : BitstreamRemarkContainerType::Standalone) { + : RemarkSerializer(Format::Bitstream, OS) { StrTab = std::move(StrTabIn); } -void BitstreamRemarkSerializer::emit(const Remark &Remark) { - if (!DidSetUp) { - // Emit the metadata that is embedded in the remark file. - // If we're in standalone mode, serialize the string table as well. - bool IsStandalone = - Helper.ContainerType == BitstreamRemarkContainerType::Standalone; - BitstreamMetaSerializer MetaSerializer( - OS, Helper, - IsStandalone ? &*StrTab - : std::optional(std::nullopt)); - MetaSerializer.emit(); - DidSetUp = true; - } +BitstreamRemarkSerializer::~BitstreamRemarkSerializer() { finalize(); } + +void BitstreamRemarkSerializer::setup() { + if (Helper) + return; + Helper.emplace(BitstreamRemarkContainerType::RemarksFile, OS); + Helper->setupBlockInfo(); + Helper->emitMetaBlock(); +} - assert(DidSetUp && - "The Block info block and the meta block were not emitted yet."); - Helper.emitRemarkBlock(Remark, *StrTab); +void BitstreamRemarkSerializer::finalize() { + if (!Helper) + return; + Helper->emitLateMetaBlock(*StrTab); + Helper = std::nullopt; +} - Helper.flushToStream(OS); +void BitstreamRemarkSerializer::emit(const Remark &Remark) { + setup(); + Helper->emitRemark(Remark, *StrTab); } -std::unique_ptr BitstreamRemarkSerializer::metaSerializer( - raw_ostream &OS, std::optional ExternalFilename) { - assert(Helper.ContainerType != - BitstreamRemarkContainerType::SeparateRemarksMeta); - bool IsStandalone = - Helper.ContainerType == BitstreamRemarkContainerType::Standalone; +std::unique_ptr +BitstreamRemarkSerializer::metaSerializer(raw_ostream &OS, + StringRef ExternalFilename) { return std::make_unique( - OS, - IsStandalone ? BitstreamRemarkContainerType::Standalone - : BitstreamRemarkContainerType::SeparateRemarksMeta, - &*StrTab, ExternalFilename); + OS, BitstreamRemarkContainerType::RemarksFileExternal, ExternalFilename); } void BitstreamMetaSerializer::emit() { + assert(Helper && "BitstreamMetaSerializer emitted multiple times"); Helper->setupBlockInfo(); - Helper->emitMetaBlock(CurrentContainerVersion, CurrentRemarkVersion, StrTab, - ExternalFilename); - Helper->flushToStream(OS); + Helper->emitMetaBlock(ExternalFilename); + Helper = std::nullopt; } diff --git a/llvm/lib/Remarks/RemarkLinker.cpp b/llvm/lib/Remarks/RemarkLinker.cpp index b00419bd4e51b..f0feeccbfe1b8 100644 --- a/llvm/lib/Remarks/RemarkLinker.cpp +++ b/llvm/lib/Remarks/RemarkLinker.cpp @@ -108,7 +108,7 @@ Error RemarkLinker::link(const object::ObjectFile &Obj, Format RemarkFormat) { Error RemarkLinker::serialize(raw_ostream &OS, Format RemarksFormat) const { Expected> MaybeSerializer = - createRemarkSerializer(RemarksFormat, SerializerMode::Standalone, OS, + createRemarkSerializer(RemarksFormat, OS, std::move(const_cast(StrTab))); if (!MaybeSerializer) return MaybeSerializer.takeError(); diff --git a/llvm/lib/Remarks/RemarkSerializer.cpp b/llvm/lib/Remarks/RemarkSerializer.cpp index df1da53d7c8a6..80388b4c47cb0 100644 --- a/llvm/lib/Remarks/RemarkSerializer.cpp +++ b/llvm/lib/Remarks/RemarkSerializer.cpp @@ -18,34 +18,32 @@ using namespace llvm; using namespace llvm::remarks; Expected> -remarks::createRemarkSerializer(Format RemarksFormat, SerializerMode Mode, - raw_ostream &OS) { +remarks::createRemarkSerializer(Format RemarksFormat, raw_ostream &OS) { switch (RemarksFormat) { case Format::Unknown: case Format::Auto: return createStringError(std::errc::invalid_argument, "Invalid remark serializer format."); case Format::YAML: - return std::make_unique(OS, Mode); + return std::make_unique(OS); case Format::Bitstream: - return std::make_unique(OS, Mode); + return std::make_unique(OS); } llvm_unreachable("Unknown remarks::Format enum"); } Expected> -remarks::createRemarkSerializer(Format RemarksFormat, SerializerMode Mode, - raw_ostream &OS, remarks::StringTable StrTab) { +remarks::createRemarkSerializer(Format RemarksFormat, raw_ostream &OS, + remarks::StringTable StrTab) { switch (RemarksFormat) { case Format::Unknown: case Format::Auto: return createStringError(std::errc::invalid_argument, "Invalid remark serializer format."); case Format::YAML: - return std::make_unique(OS, Mode, std::move(StrTab)); + return std::make_unique(OS, std::move(StrTab)); case Format::Bitstream: - return std::make_unique(OS, Mode, - std::move(StrTab)); + return std::make_unique(OS, std::move(StrTab)); } llvm_unreachable("Unknown remarks::Format enum"); } diff --git a/llvm/lib/Remarks/RemarkStreamer.cpp b/llvm/lib/Remarks/RemarkStreamer.cpp index bb62c8b5c2fdc..d9be2f1fcb6a4 100644 --- a/llvm/lib/Remarks/RemarkStreamer.cpp +++ b/llvm/lib/Remarks/RemarkStreamer.cpp @@ -12,6 +12,7 @@ #include "llvm/Remarks/RemarkStreamer.h" #include "llvm/Support/CommandLine.h" +#include #include using namespace llvm; @@ -31,6 +32,14 @@ RemarkStreamer::RemarkStreamer( Filename(FilenameIn ? std::optional(FilenameIn->str()) : std::nullopt) {} +RemarkStreamer::~RemarkStreamer() { + // Ensure that llvm::finalizeOptimizationRemarks was called before the + // RemarkStreamer is destroyed. + assert(!RemarkSerializer && + "RemarkSerializer must be released before RemarkStreamer is " + "destroyed. Ensure llvm::finalizeOptimizationRemarks is called."); +} + Error RemarkStreamer::setFilter(StringRef Filter) { Regex R = Regex(Filter); std::string RegexError; @@ -57,16 +66,7 @@ bool RemarkStreamer::needsSection() const { assert(EnableRemarksSection == cl::BOU_UNSET); - // We only need a section if we're in separate mode. - if (RemarkSerializer->Mode != remarks::SerializerMode::Separate) - return false; - - // Only some formats need a section: - // * bitstream - switch (RemarkSerializer->SerializerFormat) { - case remarks::Format::Bitstream: - return true; - default: - return false; - } + // Enable remark sections by default for bitstream remarks (so dsymutil can + // find all remarks for a linked binary) + return RemarkSerializer->SerializerFormat == Format::Bitstream; } diff --git a/llvm/lib/Remarks/YAMLRemarkParser.cpp b/llvm/lib/Remarks/YAMLRemarkParser.cpp index 5ff42fe6b9a9c..baad378d72bd4 100644 --- a/llvm/lib/Remarks/YAMLRemarkParser.cpp +++ b/llvm/lib/Remarks/YAMLRemarkParser.cpp @@ -385,7 +385,11 @@ Expected YAMLRemarkParser::parseArg(yaml::Node &Node) { if (!ValueStr) return error("argument value is missing.", *ArgMap); - return Argument{*KeyStr, *ValueStr, Loc}; + Argument Arg; + Arg.Key = *KeyStr; + Arg.Val = *ValueStr; + Arg.Loc = Loc; + return Arg; } Expected> YAMLRemarkParser::next() { diff --git a/llvm/lib/Remarks/YAMLRemarkSerializer.cpp b/llvm/lib/Remarks/YAMLRemarkSerializer.cpp index 846a72182d8f0..42ebfbfb3729a 100644 --- a/llvm/lib/Remarks/YAMLRemarkSerializer.cpp +++ b/llvm/lib/Remarks/YAMLRemarkSerializer.cpp @@ -19,8 +19,6 @@ using namespace llvm; using namespace llvm::remarks; -// Use the same keys whether we use a string table or not (respectively, T is an -// unsigned or a StringRef). static void mapRemarkHeader(yaml::IO &io, StringRef PassName, StringRef RemarkName, std::optional RL, StringRef FunctionName, @@ -116,11 +114,15 @@ template <> struct MappingTraits { static void mapping(IO &io, Argument &A) { assert(io.outputting() && "input not yet implemented"); + // A.Key.data() is not necessarily null-terminated, so we must make a copy, + // otherwise we potentially read out of bounds. + // FIXME: Add support for StringRef Keys in YAML IO. + std::string Key(A.Key); if (StringRef(A.Val).count('\n') > 1) { StringBlockVal S(A.Val); - io.mapRequired(A.Key.data(), S); + io.mapRequired(Key.c_str(), S); } else { - io.mapRequired(A.Key.data(), A.Val); + io.mapRequired(Key.c_str(), A.Val); } io.mapOptional("DebugLoc", A.Loc); } @@ -131,10 +133,13 @@ template <> struct MappingTraits { LLVM_YAML_IS_SEQUENCE_VECTOR(Argument) -YAMLRemarkSerializer::YAMLRemarkSerializer(raw_ostream &OS, SerializerMode Mode, - std::optional StrTabIn) - : RemarkSerializer(Format::YAML, OS, Mode), - YAMLOutput(OS, reinterpret_cast(this)) { +YAMLRemarkSerializer::YAMLRemarkSerializer(raw_ostream &OS) + : RemarkSerializer(Format::YAML, OS), + YAMLOutput(OS, reinterpret_cast(this)) {} + +YAMLRemarkSerializer::YAMLRemarkSerializer(raw_ostream &OS, + StringTable StrTabIn) + : YAMLRemarkSerializer(OS) { StrTab = std::move(StrTabIn); } @@ -145,8 +150,9 @@ void YAMLRemarkSerializer::emit(const Remark &Remark) { YAMLOutput << R; } -std::unique_ptr YAMLRemarkSerializer::metaSerializer( - raw_ostream &OS, std::optional ExternalFilename) { +std::unique_ptr +YAMLRemarkSerializer::metaSerializer(raw_ostream &OS, + StringRef ExternalFilename) { return std::make_unique(OS, ExternalFilename); } @@ -186,6 +192,5 @@ void YAMLMetaSerializer::emit() { support::endian::write64le(StrTabSizeBuf.data(), StrTabSize); OS.write(StrTabSizeBuf.data(), StrTabSizeBuf.size()); - if (ExternalFilename) - emitExternalFile(OS, *ExternalFilename); + emitExternalFile(OS, ExternalFilename); } diff --git a/llvm/test/Transforms/Inline/optimization-remarks-passed-yaml.ll b/llvm/test/Transforms/Inline/optimization-remarks-passed-yaml.ll index b65ed66fcce65..b0a238ff8efee 100644 --- a/llvm/test/Transforms/Inline/optimization-remarks-passed-yaml.ll +++ b/llvm/test/Transforms/Inline/optimization-remarks-passed-yaml.ll @@ -8,6 +8,11 @@ ; RUN: -pass-remarks-with-hotness 2>&1 | FileCheck %s ; RUN: cat %t | FileCheck -check-prefixes=YAML,YAML-NO-ANNOTATE %s +; RUN: opt < %s -S -passes=inline -pass-remarks-output=%t.bitstream -pass-remarks=inline \ +; RUN: -pass-remarks-missed=inline -pass-remarks-analysis=inline \ +; RUN: -pass-remarks-with-hotness -pass-remarks-format=bitstream 2>&1 | FileCheck %s +; RUN: llvm-remarkutil bitstream2yaml %t.bitstream | FileCheck -check-prefixes=YAML,YAML-NO-ANNOTATE %s + ; RUN: opt < %s -S -passes=inliner-wrapper -pass-remarks-output=%t -pass-remarks=inline \ ; RUN: -pass-remarks-missed=inline -pass-remarks-analysis=inline \ ; RUN: -annotate-inline-phase=false \ diff --git a/llvm/test/tools/dsymutil/ARM/remarks-linking-bundle-empty.test b/llvm/test/tools/dsymutil/ARM/remarks-linking-bundle-empty.test new file mode 100644 index 0000000000000..0a89fa1ddee3c --- /dev/null +++ b/llvm/test/tools/dsymutil/ARM/remarks-linking-bundle-empty.test @@ -0,0 +1,13 @@ +RUN: rm -rf %t +RUN: mkdir -p %t +RUN: cat %p/../Inputs/remarks/basic.macho.remarks.empty.arm64 > %t/basic.macho.remarks.empty.arm64 + +RUN: dsymutil -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%p/../Inputs %t/basic.macho.remarks.empty.arm64 + +Check that the remark file in the bundle does not exist: +RUN: not cat %t/basic.macho.remarks.empty.arm64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.arm64 2>&1 + +RUN: dsymutil --linker parallel -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%p/../Inputs %t/basic.macho.remarks.empty.arm64 + +Check that the remark file in the bundle does not exist: +RUN: not cat %t/basic.macho.remarks.empty.arm64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.empty.arm64 2>&1 diff --git a/llvm/test/tools/dsymutil/ARM/remarks-linking-bundle.test b/llvm/test/tools/dsymutil/ARM/remarks-linking-bundle.test new file mode 100644 index 0000000000000..e1b04455b0d9d --- /dev/null +++ b/llvm/test/tools/dsymutil/ARM/remarks-linking-bundle.test @@ -0,0 +1,81 @@ +RUN: rm -rf %t +RUN: mkdir -p %t/private/tmp/remarks +RUN: cat %p/../Inputs/remarks/basic.macho.remarks.arm64> %t/basic.macho.remarks.arm64 +RUN: llvm-remarkutil yaml2bitstream %p/../Inputs/private/tmp/remarks/basic1.macho.remarks.arm64.opt.yaml -o %t/private/tmp/remarks/basic1.macho.remarks.arm64.opt.bitstream +RUN: llvm-remarkutil yaml2bitstream %p/../Inputs/private/tmp/remarks/basic2.macho.remarks.arm64.opt.yaml -o %t/private/tmp/remarks/basic2.macho.remarks.arm64.opt.bitstream +RUN: llvm-remarkutil yaml2bitstream %p/../Inputs/private/tmp/remarks/basic3.macho.remarks.arm64.opt.yaml -o %t/private/tmp/remarks/basic3.macho.remarks.arm64.opt.bitstream + +RUN: dsymutil -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%t %t/basic.macho.remarks.arm64 + +Check that the remark file in the bundle exists and is sane: +RUN: llvm-bcanalyzer -dump %t/basic.macho.remarks.arm64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.arm64 | FileCheck %s + +RUN: dsymutil --linker parallel -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%t %t/basic.macho.remarks.arm64 + +Check that the remark file in the bundle exists and is sane: +RUN: llvm-bcanalyzer -dump %t/basic.macho.remarks.arm64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.arm64 | FileCheck %s + +Now emit it in a different format: YAML. +RUN: dsymutil -remarks-output-format=yaml -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%t %t/basic.macho.remarks.arm64 +RUN: cat %t/basic.macho.remarks.arm64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.arm64 | FileCheck %s --check-prefix=CHECK-YAML + +RUN: dsymutil --linker parallel -remarks-output-format=yaml -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%t %t/basic.macho.remarks.arm64 +RUN: cat %t/basic.macho.remarks.arm64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.arm64 | FileCheck %s --check-prefix=CHECK-YAML + +CHECK: FP;ns6E4O?jd5o8ZGjDm_>y^VW_ISc^Yz|`pWpuM zA%qfGxcPzlaEk!J3IVNhHoNV%=5y4O=mX1@tAR(VMI|gzwA34x!#ncW>B+GT+2t4v zK|F*$2OxHEelqXc;3txe@bLJB4GR}%iK#BTiVYJMxuX!ptSZk=iIOav zY8ml|Ceov4D%Q)48*w!Om#LiF;%SAPffio8AIvSu&XFDBl`K;H88w%mBVD*{yObuU(w&`M?un6?6DW`H^a*? zk1@d8(g2Srii)8ZCB+hF3)i(m7UpHB@-tvE%sIl8%YcVtKlzXN@>)Sf7jJw;hIfhK zy=D1c-2tA6P4>*+dxjTgc%6XbSzFSN!^izVPMPW}rf7uvY4FFEuEH6C6Yr^8OUxSy zeev3`QUmv2D>!;#^gP`~NF%sa)0Zb!PNqJd>Khz)yMhP9ZO?=2cf;?};m;jypXi?9jsu^bwFPT}gml0|)eKm0kf(PDi4{$)ELm#I z(u*X)q$%CJE-BLn&y>7m>b(ixC|bO%Sx{Y7(pf6Bkw&A<0WNy)cGPTXXladp znF}?xHdU2cV1jsx?AN)_%@7xbqMRdh&G%^NE^UR%@Pv!@*ACPk4h@EmhrkUWj{yY; zCXHn~K&a1VLE`LEqU5u=0EaCC7(eMGZNRt}46n~EAV`or0$K!8@={?cQdZ59W)vdv zI4|(Rlx9Vaz;*&?dRFFPzWXgh)}&Hb$&#{p)r{ryWxcCt8Z)Y5@o1muQ+s4pNgnG- zWqXBGT}CXrnu2U3-^NUFQJ!n|V>Rg^Ti(2}XMD@7!_jtMeIQKtq07?!?=ziO%9+KpE9>d;v$CHAcJC%N6=*I>eSSdMZp=37 zgGg*aY+aZe{K~%Vc%El6-nlwE2FJJwW%w1#$1YWQzzazltikt*#X#DxnWAp{Z!&|X2}!U0fsd2c*Ui?`C|NpIfA%=>xX zdo$ywUq1ZPLWn?saHsv=w+sWa_%Z-vQS>jWIx;-2ggrGdh73#i74DuI}1L zex5$EYJ1vlt{@&lrvZd*u8u5tYfvhRO-!1uShg27i! zMafcaZbnfx&8B6^pytIbIk)2Gj*OKKd^GI86Qs?3Ssux)c|o z|2V{BOYee=fW&+1)e`eY##p>Iywsr8PXAWO^Obqw&dNS=>CZ>qOK+RWgLfkN{I)s$ z08p;1%xCVvnoEC)%FC(4Q-_2`LfT-WLAaN`Kbm^BZ+K+nVc&9PFKD+bd#_YR7BYL5 zDyij1nT6r{#`f*u&YSHY&xN04!f$#yUkNP}JzcMEbhbCO6Vd|@8VCY{T)#y~tY{l$ z)uA!REXMe=5!2L?p$|x=s-LhV?v$umbWTdDZ4MG7dE5Nim)(Pwa5?-5m z;M2gDf%Uvvn2D6BT{5gfBp#P!NuDvBNFNMo;1hG21ZR4WV`+w3>MuEJHc#zXK3_Kb zi?%gObw|SWiD5dZQ9b$7U@AK#r{elhDk;-cP9D?~i4@Jsi3HUL)#NV1OQMt5x+No~ zY7|&egDeTyqe~MYFpIV41a;&lV9Xd_XE`a$pfdmL*~L?sC6XYCTk7yfBlI$R?SK^n z`p@gFf)lrq1Str@*U&~3{HvgJqe?`fJJ1>o3qPQ7`{JkB9mmR(mk-?km^pet1I(uC zoe_J5U}!_*TyR7Ecu;H}53~T@dIx86o4s-wj literal 0 HcmV?d00001 diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.empty.x86_64.opt.bitstream b/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic1.macho.remarks.empty.arm64.opt.bitstream similarity index 100% rename from llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.empty.x86_64.opt.bitstream rename to llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic1.macho.remarks.empty.arm64.opt.bitstream diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.arm64.o b/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.arm64.o new file mode 100644 index 0000000000000000000000000000000000000000..81a972e9510d735418d2b1a21ab12665c878c326 GIT binary patch literal 2816 zcma)8O>7%g5Pr|=-8godG>uVe<-e+FipbhYogXKu8bb;wNkxewno6L}+TJ7v|3vFe zKnYcnriX$+0@Opr0fnln%7p{s&{UOZ#RYL82S7P+fCHizB*YC+5Z~;+jbkg7GSa-6 zd2img^JeBf`}=?X_^*aB&OkKC;KyDJ?O;#{JWci!XjrWIXd|d!*j3PpkI*DY(=6j{ z%h4Ts>iqOn$#%7Ap%9)2`bafnh>tNZTO;9;rloaDcP+vnO-v<9_8yLynh|&2mhl_kUc$xfcfgEt&GQ4X7&n?mWhr}yd zrdF7pEmq>~2)s@a%`bo@Kw@SP_!rP7S3xT(Z{u4Dn z5HGLi461P@-nQ_*E@IjNUKv1zscES~Zb463+G75#Og@c%85LV?F)caPh?t!5F-B7l z5ud;=u z=Ua7qt}3*n;2rEINt?*;F>HDV?)vc_K?cAV!9-LlVmcC*-F!ehJmL5sGCs0}9l_m| zuRq_F*he(y<0F5Aw-6|O@&?US!#*vu`fAR$$o9h?haG_3$^8NH-CcQf_o1ZyMCW@3 zJb7VqoWr>udKLe2_F7^rdQ}D;&Ti{ey&(F0l8D=q4$hY_Os8KaKm$BMA zF^quc7n3S(=%7_dX7plL(bCgd!;ECJOS!HEv+#zIvQ+Yq4H&&iBh`PVH=gc`#(PqI z@&2e0pN;mWVzIc9j>cj}s#otn%|vlhEOKD+*kXRMXr#O0XR=H_#byfyaT+%($Q>dl zqAnonbOgq0U^=(B%l16o4`S*;+DX4i(f()@YMI}=#p{8#wd(=@4}(LL8#hnnN6$8; zn5$BQ7ghGOKvE;}0SwG@jz%I*nJRX1{~AV|C-jzJ^UN=CH(keu^>Ymbni zQ-Pth*$0$(o2O20-lru$mnG$@%#=y_ zn14gASMJOHG3ESy`Q*!Tqw<&Bri{TMFoyQy{Gf|fsvR43BAFN#lCpr1&c-0|#ffKy zq{_fPOIg7i)kSX_nm>!HO!9TA2hCFgu-{Gx;j}xpLjJH7JNJ;}Pqw=b)3(Qj^mv$; zdpZZaQt)^)<}QM3vB4!$YZ1_EVuI>gi{^0u=Oo1Xv{)aiSnnkp!On>F2-!G@`#VMP z*5M;=eP0x|aAzmT#`j%(yM^3E$QJOvaPb3{)R&niUO6q3w`j&>8eI!*NzXF;aMFcw Z{ugHP48|CZXY8@Z9=lzqZrh~B{~ucyRFePz literal 0 HcmV?d00001 diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.arm64.opt.yaml b/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.arm64.opt.yaml new file mode 100644 index 0000000000000..4aa53015a988f --- /dev/null +++ b/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.arm64.opt.yaml @@ -0,0 +1,194 @@ +--- !Missed +Pass: inline +Name: NoDefinition +DebugLoc: { File: basic2.c, Line: 11, Column: 3 } +Function: unused1 +Args: + - Callee: bar + DebugLoc: { File: basic2.c, Line: 0, Column: 0 } + - String: ' will not be inlined into ' + - Caller: unused1 + DebugLoc: { File: basic2.c, Line: 10, Column: 0 } + - String: ' because its definition is unavailable' +... +--- !Missed +Pass: inline +Name: NoDefinition +DebugLoc: { File: basic2.c, Line: 20, Column: 10 } +Function: foo +Args: + - Callee: bar + DebugLoc: { File: basic2.c, Line: 0, Column: 0 } + - String: ' will not be inlined into ' + - Caller: foo + DebugLoc: { File: basic2.c, Line: 19, Column: 0 } + - String: ' because its definition is unavailable' +... +--- !Passed +Pass: inline +Name: Inlined +DebugLoc: { File: basic2.c, Line: 20, Column: 25 } +Function: foo +Args: + - String: '''' + - Callee: inc + DebugLoc: { File: basic2.c, Line: 14, Column: 0 } + - String: ''' inlined into ''' + - Caller: foo + DebugLoc: { File: basic2.c, Line: 19, Column: 0 } + - String: '''' + - String: ' with ' + - String: '(cost=' + - Cost: '-15015' + - String: ', threshold=' + - Threshold: '75' + - String: ')' + - String: ' at callsite ' + - String: foo + - String: ':' + - Line: '1' + - String: ':' + - Column: '25' + - String: ';' +... +--- !Missed +Pass: gvn +Name: LoadClobbered +DebugLoc: { File: basic2.c, Line: 15, Column: 10 } +Function: foo +Args: + - String: 'load of type ' + - Type: i32 + - String: ' not eliminated' + - String: ' because it is clobbered by ' + - ClobberedBy: call + DebugLoc: { File: basic2.c, Line: 20, Column: 10 } +... +--- !Missed +Pass: gvn +Name: LoadClobbered +DebugLoc: { File: basic2.c, Line: 20, Column: 36 } +Function: foo +Args: + - String: 'load of type ' + - Type: i32 + - String: ' not eliminated' + - String: ' because it is clobbered by ' + - ClobberedBy: call + DebugLoc: { File: basic2.c, Line: 20, Column: 10 } +... +--- !Analysis +Pass: prologepilog +Name: StackSize +DebugLoc: { File: basic2.c, Line: 10, Column: 0 } +Function: unused1 +Args: + - NumStackBytes: '0' + - String: ' stack bytes in function ''' + - Function: unused1 + - String: '''' +... +--- !Analysis +Pass: prologepilog +Name: StackSize +DebugLoc: { File: basic2.c, Line: 19, Column: 0 } +Function: foo +Args: + - NumStackBytes: '16' + - String: ' stack bytes in function ''' + - Function: foo + - String: '''' +... +--- !Analysis +Pass: asm-printer +Name: InstructionMix +DebugLoc: { File: basic2.c, Line: 11, Column: 7 } +Function: unused1 +Args: + - String: 'BasicBlock: ' + - BasicBlock: entry + - String: "\n" + - String: ADRP + - String: ': ' + - INST_ADRP: '1' + - String: "\n" + - String: LDRWui + - String: ': ' + - INST_LDRWui: '1' + - String: "\n" + - String: TCRETURNdi + - String: ': ' + - INST_TCRETURNdi: '1' + - String: "\n" +... +--- !Analysis +Pass: asm-printer +Name: InstructionCount +DebugLoc: { File: basic2.c, Line: 10, Column: 0 } +Function: unused1 +Args: + - NumInstructions: '3' + - String: ' instructions in function' +... +--- !Analysis +Pass: asm-printer +Name: InstructionMix +Function: foo +Args: + - String: 'BasicBlock: ' + - BasicBlock: entry + - String: "\n" + - String: ADDWrs + - String: ': ' + - INST_ADDWrs: '3' + - String: "\n" + - String: ADRP + - String: ': ' + - INST_ADRP: '3' + - String: "\n" + - String: LDRWui + - String: ': ' + - INST_LDRWui: '3' + - String: "\n" + - String: ADDWri + - String: ': ' + - INST_ADDWri: '2' + - String: "\n" + - String: STRWui + - String: ': ' + - INST_STRWui: '2' + - String: "\n" + - String: ADDXri + - String: ': ' + - INST_ADDXri: '1' + - String: "\n" + - String: BL + - String: ': ' + - INST_BL: '1' + - String: "\n" + - String: LDPXpost + - String: ': ' + - INST_LDPXpost: '1' + - String: "\n" + - String: LDRXui + - String: ': ' + - INST_LDRXui: '1' + - String: "\n" + - String: RET + - String: ': ' + - INST_RET: '1' + - String: "\n" + - String: STPXpre + - String: ': ' + - INST_STPXpre: '1' + - String: "\n" +... +--- !Analysis +Pass: asm-printer +Name: InstructionCount +DebugLoc: { File: basic2.c, Line: 19, Column: 0 } +Function: foo +Args: + - NumInstructions: '19' + - String: ' instructions in function' +... diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.empty.arm64.o b/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.empty.arm64.o new file mode 100644 index 0000000000000000000000000000000000000000..8c55fb3d9d9b813cb54b0d5dbf0d7d985049bcf9 GIT binary patch literal 2800 zcma)8O-y4|6uz&ISAIHEV8AeB7$^iBW(;j%%1`-8S_dZvI*AfgOf+|1Umwu1e`y~$ z0!9QDjKKs9D;EaQ1WD zcg{Wc-uBBse*XImV-f?=Py{}p!374@g2%}I4{8;2zX{nSWHI82&x&=N8~SY{2g3R2 zQ)8n!+tOBqLU=alu2O+f#OAFSlAK3WL(O?O9}JELbGC(3B3w&K7B3fZT;n{P$>g~T z@tQ?lLYR@1pGCBH`NVlzkE`idEKJTrq33VpBG!evCFBb7E1-OMs#gzBO>i|FPV3WD z|KJP3k?TiG`b7dh;qlpzrYz+|yl7%PNdbj;DS_83R!^Q1FJq*6a(p~fh<8`uH4D7W z)8m;d3h}-Wc$)(6(^KN9kw}`B6yl}C?zjZrBpqJRGR~izRZrZ%gc{eW$Ax&SB6=>n zmMsJC7(ju^xt5HlRL$U1iC3eE2+qr(SZaz2k;F~mEWyDh*T(N3BEP?^izjS|V|X2KoCjyWRelsjLFB(L?)_>R zV>e+tz|Vk*2%4BmApbF7*r%bx*-y3)Wwr*KRVD>?v1a{n_QBSDnSb}sBK!JqR@y$i z#@06W8+Nw#Ic>}8WhwAGc$Z0~^x5@?4rZ?VNoIE+Is&^Tti*wd)hJ@FD6I09gn7gs z&IY%ExklLZy;97(FpuJQ$wzx|1w3+NWLQE#CG=wHqrk^c`oFr?)8GG~_1obyI!aX7w*`)_)$X|Gu&AKspm@ym;__U3F4zj(UEPNj6i3 zB{O=f$+EFJj72u-B?v{fQSNr;A_GiBS9cctI`|#%yWsc0T1-t$xTf`VCYnsRIy&55 zw|63HxLPp;z>`y9H||%jkqk%GOk2iKBQZVgiN&VlZK-tfmaZ9Yiud*Conc+;zS`-J zbb0+9T9?1utNX{jotn?**CSq^PuDut?#oPUo5nmRZY!HgOl9;)I~z|XSu~-Ul__SG zNEbwv65Y-UQ&N@U?wMXX-^4h3=1Ten@pgN?G?^cFC$sEmm|u33ebd`#?Fj7-5j~64 zf5|OZ7158m^aKVb(fwnR^%|3rC6Sl7&6YQpFSQ2r$h=ht^$hgLm0X3B>hFe>BY{aiX z5(U8d^Yr`g#Llln5>Y))6lVP%QQqai7w3kBgbiWRC5+{H_*Jm;(#1<~+-5wi&M+=s vDjrQ30>1+|+dH30N4({yZ& literal 0 HcmV?d00001 diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic2.macho.remarks.empty.x86_64.opt.bitstream b/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.empty.arm64.opt.bitstream similarity index 100% rename from llvm/test/tools/dsymutil/Inputs/remarks/basic2.macho.remarks.empty.x86_64.opt.bitstream rename to llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.empty.arm64.opt.bitstream diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic3.macho.remarks.arm64.o b/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic3.macho.remarks.arm64.o new file mode 100644 index 0000000000000000000000000000000000000000..3497e3add648ad038dc25025214f0d94fb1ed79a GIT binary patch literal 2528 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 literal 0 HcmV?d00001 diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.empty.x86_64.opt.bitstream b/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic3.macho.remarks.empty.arm64.opt.bitstream similarity index 100% rename from llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.empty.x86_64.opt.bitstream rename to llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic3.macho.remarks.empty.arm64.opt.bitstream diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/fat.macho.remarks.x86.o b/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/fat.macho.remarks.x86.o new file mode 100644 index 0000000000000000000000000000000000000000..14094faf1a3cbfea3389f130e1e19d912e8397a3 GIT binary patch literal 34800 zcmeI4U1%d!6vyu*O+R+~-AI*fyQvtdU?*cun`XC2<9<-Ei&9oAs0@?Iq{(i+m`rO~ zD^?4#il7fZh#>BYD++=jf{QG&QbgGo`=HPVeH49B`s~N*IWu?CG^S9&hXwx^?woUP z?)}fbzd3XBbmqp*&psDI1Qa3K$OeU&CDXP;mu}hDF2s7Rj~o;b009sH0T2KI5C8!X z009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH z0T2KI5C8!X009sH0T2KI5C8!X009sH0T2Lz|Cqoxzx{HP68{xS{1=q(FIuQx=806^mt*`ke@uXDC;v!A*Bxus@qDj+_SEBNciX<#BOTV;bK4fN?vG)s z>$X)i?DJLGsq6FekDb{a;p<$IU7zj|b2|gOqggLwrI(jgtgOf8(Q4f#lV zcT2k%s{Q0UP4)7nY?%i%>U}3?-7D?02h^)NwqDL=tBraJKRhZ!o)I4$T+f}+s5dP2 z-jjM?9#GH7WNe<&sJAKgdZpg^R?oT4!RNV6`IU^K#m~4=?^`+P5vjLEdV2&Kn!0Y5 zixtCk^ySji`BH}B<)obInlU*!B0IN8k3;+Geb;B@^sG&*^Csx}-gusqdb3h*N9xI@ zI4nfY_u2aKSIC!K#m4DKn}og+i< zgm<1Fxse+AespMC>6{-O-o88(?g$GpO6OERY4LG&=@}tn6+6FTI9ALlR$}s`iDeB( zEgEL7tjZpBb$UvlimT;{qo(r?VYZASDbP0ilxTDy6pX&G7PSX^2aiPij`X)y2ML%e z*bPQ$)EL!};C(QdVW9+Ems&x=h`AMTy%ra~{|@pS_A=F1s9vUO7L3wTWW}n}1w>!sbF=~=r)xv(IV z)n28yv#tF#8pR5HcE0iFUv8;Ic&fYi#lVR!d0dGnXbf*6K~_t!dfDfGlnVofn;pfVRLEGh>vZEPxwdCqfx_uP-o`FiBHu?i8N!2IyJa4R5kKrHk`=EK*(jcHxEy5-51M>p!|WV07f z9=b|to}b~yw6(OiO%B`ZW0S|k(LoHWYi(-A|0wY%0{6_A46 zIzPtj=-Zju~0)o|MlScN=}qW)xt|s+Dak-BGkL2QpgQO4>3E zx~_3!67hUodqtZrAId3OZ05R*>CENaxoAuC1+ZSZP2@x0`Wn4^dK1uU3*cJE)4wiUx9n`= z`yXwtTk%KxUHg_}%z_u6sY>LAD!Z>|Ljqq07NfDBPc`fgJfG(2@V+=`-B+JqW5xHl z8js_+Idj_&#V z*l?No&YmBR4c#&*+YgGgS(qnb8Pb@Ac|VSi*JxQc!L_yEY8Jf6LHx>U6|}m3&uZHD zn)0r|7g=j(vA+wSb3U9E-r4Mv011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg zz<)zP|4&RK0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH* zAOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*`2Pu5 zC;|7T+pg8z zCz4qScgC|)*`3MAymUO(CpG=?Ui+@@OQFDeO}7L-TQA>^73)~48b!GG(`#)BPl5NT zhP$>29k1R3-Hj(|PJGy-b98A0KY9na_APk5N9$NU9AVp3Zzzd-_kS62?|yHV=#$V> z?VrE~np^LI*Zp0sWA$(w23pm+zZ<^@-B7}(0lB8*a~bm!aMwoA@#-?<*81)#;d2T( zb?+PDTA!3CO9CgQA##IxzUnR2pE2R`$kYk#nrA4pamK8T(_{rh*G4W> z41?s`(E6&>sxgMw&5`TP tf35YeR~|Y1>VrcaPh5QXq2T>reRK50(!rg#pL(OLFlWi0=g*Ic{0+b?v-to3 literal 0 HcmV?d00001 diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.empty.arm64 b/llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.empty.arm64 new file mode 100755 index 0000000000000000000000000000000000000000..49c0a2749f35017ead09b3cbfee227719158afd7 GIT binary patch literal 34416 zcmeI5ZHSar6vxl(&e{z7rnaP_)fCH?o6Xd!r9n7bF0NE6w%}IEbzYgtotbrJTwkdT zwUqXQ!a@;}_904BC=uKxtOe->Bw{~Q5G31|T7!bZJ|yb)KhHdmK0EHNlpiAaA2`o_ z&OPUzd+zVvXTA;h>r200tr77Eqyjnv8t{tjl>pvE=0Mw_#;j>w(e`}X+SS@SUaZ06 zyKb;F&nVQGj<(K@@osB;czmDOb``o+wKf%FiivH-(tF7spKl{-*L*&^D7Brj)+n#^ zTCM#sW=nQ!IvY3XY%+(w^7>MkTvMg&c(upnv-_P!*SQ1(j9K2=(dzV~4cm~>T2j_l zqSI0J8xxNdBl=d7$?{=&B?(Vmmod>o!HGp%p3jT%y3T9)@a|rx`rKknESJgTvQA%l zK418s<-2~)o?f}?skY@Soiox~#tpVg_q0;0b-8O>B+@%wUA@=`Gz)Ee3G6knbxpIO z2Vg&lcH?f5P9&(tyZTk`w^h%b#{3(p!=L~Z-Je! z@16Ph+`g`t_O~pH6ruoU9I7go4 z!SeYu=cwj7Dw|J;bYN)>*u#FU0~{K3yw4vVynq<3dGSXhd8tk2axya$NoQqNPo&Gb%X-AOV0}ZU z2=4KgIt(7g#9GHgw%uXfUM{j&ZM_6LT=GArHe#Lo>vc?AAGWMO8+Qz}8_Mh?>?CGd z5+6uum<|o%p?7iXdjQ(#vbC=fx&W%8_Np?!d;YiKch7&S%svBqqWSym`SqT7o!_yY z`PZXg#hKsj*ZLiPeswmJ z_p-gdJM8)#+o=yn!4kEVuiLNdbIyaF4_%*QYkVWLe0`2z@3#*?9npCAe(7H&P(G1~Ovk?AgO4@UBt zM-~Nh6OSvUZJ9D{OK_^R)=H)*dEu0~7fzWQeBE;Ce9aI@A4i{VrAh<(u#KKKr2>bn z!uo~UhJNQr`9<~&1uCS*ioWT?*} zexYa4?7APWHYH|84<9>O(Y&tVuFd}1WuKhhaQ@v{{kNL`X5-J@lS-b;f0aDF`_O%T c1BZWk=HgF@=Xzf4xb2;~(Rr_Y*{U4>22n&0Jpcdz literal 0 HcmV?d00001 diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.empty.x86_64 b/llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.empty.x86_64 deleted file mode 100755 index a730148ba387047682c588a62a9601da8a7cfcc0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9296 zcmeHNU1%It6uy&WZK$=o6eg<|^7@-K!tZuQXi;Yy2a+%$oC5xHevOhIZ z0>xEuSo{H>d=d4@$G%nY#k2*BFH!KJeUTyvTeRSV;3A9h`)1~5XE!me55CAfaOU3c z+8LLKwqBoE;KE#G&Sh5bp>RH6g~J8K{)m+2_))q+fi2)_yVi z;kJl=+E6JM(l0Occk#z3`fVb_F_@{$jUr{;S*{250QdVlw-=K^!);+w#F$P`M#R}3 zpua}>^-{SYOXXq(4TJf82}00%6ZOUfRuBy3$u|n%*Rhj&2yjx|3WE8 zNm;P#c5nPY`P-Zu{Oy#Nl(|~1=Wa`WBVm4<{?Iq-&(FPYe7@qkm9jDo<~RB;{q@$_ zv7^VIPtP4yYs4Jj4VaP*6J=h}+#bL>PWe4qA$(tJ>e6dc}88Gy|Fe&46Y=Gw@$C@KVP6In(?#@lCqR zP~K`M<28P3t#;b`05i=?iBlIpjEL%=c`r7GcW7_5+nVpT62|x5dYkX}Ub@r9JF{rb zcZ{`G>;_F2nimXj|4*nIYu@F+XZ*n1z(UYpEA}mF&94nFwuVYyKot*(HCH%;rR}dcy(iA15K@THwaX;RH*oYxgZ`!obpFB*9>peyUc+6 z9=HceiI#k~=ez$DO6qxhuTog&H^Uyh^CyC@37QRlKWNbmXa+O`ngPv#WaM%0xzKq#{U@h zX#CHCw~K!bdoFad4rP3WX=5zzHBpEeKZ=>Z;_C;rbG*Xr&++@A6k?87_$u&tgwG#| zM|ym+|4#G!h3!x!zoW9<{IcQwyB`jjpThKiEAvzLe>@zouo};uF$yu~r|==vO*VwW z_UL@L9^(cU6NGIX7e__q$8&XJbwA7ytM$V3?Kn=t)&B~IfYF_!kB4vK(Wk=q HND}@AAlzFj diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.x86_64 b/llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.x86_64 deleted file mode 100755 index 59e53c8de9acbfd3a4c3b28fe28346d910c12db7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9280 zcmeHN-)me&6rP)8O{lTE6)LS(d#R;rZSTf3ED=PEX4@^AHq;1G3B%nVAs4f|vOi*4 z8Yr#>FBhx$;-mco`p~|#f-j~O4ZhU=2c;maV4;tTY#YDt-aFa5o21qUUt|uPJM*2H zIdjgpGjQ+B-umm_!$Bd8ej(2H2_fQ8b3lj-!bDAo-OvnF%IS$?>C@>`Cu!{#qZ@9D z=%)#lawh%ZOm`Q5e4^VXLL7sc%GfAU)(T6tpdR3Ee^<6688kc*21Sf?Ix-;6cL4p> zOP@NWymU%)Wi<50_dN)qD{?>~R`!QZ3ek}_MZcHC`f!{rRzXjn9>f#d1lRdgB}Vm;O5I?7ibB z-c3&)S8K%V;SHGbRv0MbipI7N>v+WP@edC(_)VGPF6cDyVU*^JP&j;&HYnw#P`M5d zL8J2lK9*n^3KKdEP1dWGuA?VKbrr zobhegpxgX9*9sPP-$4|hdR<;d{`A9j9~I6!4rN>LyBbKx=){6}-ak{V6^ho|7UFWU z!RP}h=s#l$F@*A!5R)%0ngPv#WIoWnZ}=qU(#((6U|v_s`%c?U_OkP^+z;T40p&~<%Ikm*aM|R zOTOFl-G2-v^*X*+DXjCGVHofHiQsF3W`o}kS~LTi0nLDBKr^5j&Gy|Fe&46Y= zGoTsxpEF=c+^@%Eab6ad3b}f%Amiy;>|^SLA=BBg?@46 zc|7j$@!Jb{d||>eGHv2OE<-uL!nAQNo)uAuIe!#0{t=wB zueMUEo v8nw0>!I2HVj%?}6&(Qb9+~8v~uR{C{BSBEG diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.empty.x86_64.o b/llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.empty.x86_64.o deleted file mode 100644 index aef4841d64c728c81d7600a885f9beea7497e613..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2088 zcmbVN%TE(w5TB*AR4An=5tUMlj|3kqtr$b02a2LKVqy>#59Z6ZE>NWpOF=LqkS0dr zg@Y$fYWxe-1BqOSMiUNd42hVKcrxLDi3bnF7tZX?meOEooOE^`-^}lu@0*?NyB}Zw z6ah#kzz1?6@&Y~F$VfYpyU6|reJaowRyfA65fg|@IZud`I+S7qg%F)>U7c&Tq3vUZ z@Cb6AiX&ekjFB)%h@=`-lGpp$Aw+xo#k0mLfPpj3E~j~IjWw=Zw}iN=h6Z{>e=4at zgg9|2&~Y-8w8+{imh*YyDWOnO9i;QF$J?tN3Sc+mRar7y8OnzBMPl7?3dqH4WjsG; zH!mlj^Nr3WbN9^iUEj`2!{N>FpqSn6~KlP>w$B~*+jVpXZ!QfF9avP z1k=loH*LQtd}3rJI5F_;{>aJ_nZfic$CZ~IXFJYFxPK*jilnD4&s%-(k2m`Lv$Zqn zX4Iafn;)e8V}YjWv~T8RV64$%t=Qw5QnoJzTpwnu-%7Tn8t1F=>bby;mfguEsS z=fmFt;4Q+LO(Cj8Vjz`E`|aDzCcC4u%3dyQ#W%P>22xCR+@%qjDh9A>O|*eWvjBW7 zNzi=qtDzgM+G6m0AZWCXB(<1G_vy28ZFK53jSppz{~$6^b}reuxvNP36GN>a(*FuA zD9w1l5+FQ%1)p>tB&uf}8OhSE4v>Z%lEYSHox~`LcOp;zCYaS#&c`O%9d`?kml~gi zHjF6*H$Ejv`e`pEL7N~;YYjpNz?RH?n%t7vUTnQ=F1Gm1rmg}DW?{fCWR!J>bZK$1 bL_vN_9ZTA~j1rhg%`$Q5yW?>X+RN}44(bA8 diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.x86_64.o b/llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.x86_64.o deleted file mode 100644 index f8aa44116ebe3020b91be19781527e31737bcb32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2416 zcmbVN&2Jl35PuuTj*~jB3l=5dxEoZY1jyPBCUIIL*-e66kyI!t5DwMqdA+u`-4C<7 zcGIe*sVpHPKq(6xm2wL^Z*g39ys)Zlmke)AXQKiW_I8DORgF*t9kQg z-pudKys!P`??3+?B82l1Xn+TScd+4sfyRK>QGWtWv9UcSJsmI!@+gZFMO)sm+aRKN zc4_@=Tlad$SqJeDGB)hy1$tJ_&nXv|VXi9tcqqWVhgDA>Xv24O_czXAJyT$Nw?l8H* z@R&*t5mNQ~D82ikD!PN%yM7ND-f0%J!|KgGAwS%=2>Ko#aUyVWp9fxK=d}bf1UlqF z-U03;Jd+-G+7Hryx3Kklq4`JTho#5pzIF9cVXMCP>D5QOs1};{BIoX|uB^VzLH_qcVkK*ZG(56 zO#%ZFty?f^TYRZC0k2qmU8fDIsI;icfJdbZYszJr)J#J)DsoMMmYk_;&d8}tHk|XB zG~q3Do%d5HeG`xZP`Saj&X~mQUroq0o_Pn!dXhN z=RLt{hj*%K2+SyKWM;+Lv|!Y1p$KK!rc5Rbl)9z>kWx*kYC{vimzUGhY_gclB&Fnhsw~gV&CSwM zDMRJ*>!mlO8Je1bFC(R=+8gAhO`Lt>j&LuBpY{8~k)tn$k8sbxKVv{3*ztuS*9DG;Lj>`hfp&w10AW^L_HwKS1bpEdT%j diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.x86_64.opt.bitstream b/llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.x86_64.opt.bitstream deleted file mode 100644 index ac700c36c6c7b7002403f87531b638b8964d94fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384 zcmWIY4f1B>U|?`yU|?Wp+~lyu$?}4;g^kTYjXllQK-Q9G>nY7P4USejnl1Mnc5JX< z;}B7jlXDb1wNUnuquez{o;M3+o+Qd$dMJCxG0-XPD%}gPJJ|Wo{_~704c7 zkUga+a{{RNp@N4Fcgh4s=NAW!5Yi1YryONoJ(M}nAbT%S=1?QV#7hl*4vGObHtjl7 zoUL1$ZPqYLEI4d^0qCg1HfNe2F)nQ9<7BP0Xs^m>FDhWKVrZ`RV6SpuH&AFV5@@fo zU^hr;FPCU9SkPWl!CrpBWr1@$*gO?ajT470uQ&t!1~e?0N!AMJeFjAy1_ovz%>u+L zKmtIZD!{-13?2p*1%VX@*%%lan1CE1t_%wqCxZ(h1wi27%mh})3S^t43a)4bssjTf Ysf+?317rqBZVS5*Le5PkV+K$R0990TCIA2c diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic2.macho.remarks.empty.x86_64.o b/llvm/test/tools/dsymutil/Inputs/remarks/basic2.macho.remarks.empty.x86_64.o deleted file mode 100644 index 9bb1405bf9e0d021743c7ba43971aa87dda4dda2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2892 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 K2)Qgfus#3-qLPFF diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.empty.x86_64.o b/llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.empty.x86_64.o deleted file mode 100644 index fff0a7122fb637c78da911750a42f2ade68ad816..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2624 zcmbVOT}&KR6h6c33=1sFmSS5YKZB`BtulpT2o!3Vwir^uRIEx&>ScBrV3qxG8Gc$* zrCmeVkQg3(@}W^o_p^3 zx!*l=&;8l^fBx}zIe?-9Hpl_wb!rS`q(_m5N&gobXJ4MBrz0j1SMxX_TxZVR1`*<7 z-|)q4-RmuIhwun;qyj)ETL9)scqBx|N!Xb;r`RCGz`!emo)^Hwxy`0`v~3^v%1SLl zj5^WjaWUm)q*;h_uUbRT6+@n-#X%Y>2+m>=(<9r>L^-w|Z#tEmJaMxr3HKfrNx zWDPVMC@~+nfJ{VVh$)t)-2sgHe(2@?+^_vh@={pp+@KMcR>#bmruXFFv1RGc{vOF) z&1bLXkJr3U7nzL9^=s67>rwVQYoOr%UUnoc6^UN+}CJ4DAbW-9HP(YT9uqhlvj2& z2b3qm2Q@VuIs91ofKrRsSD6XaQNuXlYsi#5Kv3?O5VT4Spo=Am1?1vppzl6I1_K)+ z3;8^9S(-E?s^SZ>*Z-2$Pq?(3h;g|jkxePQKN5Hg>6?+os;2qHs;VDPbz@q5($+D>8(48!S%?Co0P}amKO(BII>W7w%U9CD2`Tj zp5r(VtlsXpNsPP2aa2o5zPPv17ytuXMN$3=SCgQmk(KRji3Wg*;?_B$g)2YTDs@v+ zhc(cD)~Zk~*UxJqeO%M@VKsSO3+w7ZSF6RC${tO1HAO$IfjS#>wMqd4CbcyuzZSTBg$6#I-z1Ll>#wiPlBMsif>fm^aA_?lY&sm diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.x86_64.o b/llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.x86_64.o deleted file mode 100644 index 9508c979596385d4111997f602bd88b76a834292..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3080 zcmbVOU2GIp6h71KY?rod7pQ=-w6_M6f_C~tZMQ!pUD}$Wg=neTnBXuwJKG(ZomqBf zwgrP0*ANsvu_@KrIUrdbgp&`5wcpyAjVtnAis4pfp(S%2WL_Fv2o$hw2fp|9O zo_p^7?sw0*f3vIi|N5s6KnejCsI{oKsbHumPovI~{~t0CE_K`$n7~I)Al)j)sj6oz zc)~%WsxuR_Gi5)hofj42Bg&2j06s-6ECv{|s+u>lTK=Rf8dY^_>Ww31M8Gp%Q)(;7 zw|6y^kvaC)Iqv3BKS6+42t0Ze`!yT-g zFH*cFEk%}Y9=|?)Wcn2;0ZI>Rzdtm1dn`UOa;@WPaTse~6^AbsM-~%9E5*U9 z*At8JaHRR!)=#yaYl+q$ukHCkYFuk?xp8jKt;DI(ww5oO@1ASDm1zCBz2%P7IMu%A z&KE7sTbhx(y%E4iONZxkB?L#EaU*Tore``fm^R-`-}YT2)eA|@HT46E4r7{S83v>s z2ab7p)1Cu1Z(0_!9gigqRvMN<>p83h&I5Mn8uBpHb6IMA4raQ{x3z+1T3XUFaE?42 zH3~-laA|JS)`9bGB&}d$ZpQJg6tihm<@C^@JFa(-x9@`?2GfS-Vpg`pG;3Zv?UpE+ z=3x#=-!m{7O+R_eJYzsE?^w>9ku$M`qkfk696IgcO^yR|3CEJ;Vv;QF+d5yb!!~{# zd|n@OeA@%f&35K+fjk4V^0O8FE(`#UUB_=E>g|J`K^Vk6`2>$~m-vu%i4DLPIpZjz zQCW!htNne7lk=1$uC13hv@8xp(JjrMW4J0VZYJyLR`AC6SYLiKGI*gatL{(KbTuOGY!&0Oo}zuMV1k@ z7r`y4EB7gihYtfBB%-nNHDg|XgI!8*cjR<5(N81xi(?J(2_ibN`4@;?iDWoZlaID3sLFq VRq0Vz3z`KgT~++AQF{9U{sp`i_45D# diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.x86_64.opt.bitstream b/llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.x86_64.opt.bitstream deleted file mode 100644 index e29471cd769055d4d82762c7a64d4b6aaed0463e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 592 zcmWIY4f1B>U|?`yU|?Wp+~lyu$?}4;g^kTYjXllQK-Q9G>nY7P4USejnl1Mnc5JX< z;}B7jlXDb1wNUnuquez{o;M3+o+Qd$dMJCxG0-XPD%}gPJJ|Wo{_~704c7 zkUga+a{{RNp@N4Fcgh4s=NAW!5Yi1YryONoJ(M}nAbT%S=1?QV#7hl*4vGObHtjl7 zoUL1$ZPqYLEI4d^0qCg1HfNe2F)nQ9<7BP0Xs^m>FDhWKVrZ`RV6SpuH&AFV5@@fo zU^hr;FPCU9SkPWl!CrpBWr1@$*gO?ajT470uQ&t!1~e?0N!AMJeFjAy1_ovz%>u+L zKmtIZD!{-13?2p*1%VZeObiSSK+GV-m0=;{WMBbO00a)sOi1biRvZKxfTYf_0jvt4 z4rmR-64ihejUbDF79J3kXl8|~F)`s=DB%F*EI8QM#xA8GF%jYpkeV%>LMsk3LgmAB zGIju&AUA^KOmu`1a#>~>50K=xbOxU|?`yU|?Wp+~lyu$?}4;g^kTYjXllQK-Q9G>nY7P4USejnl1Mnc5JX< z;}B7jlXDb1wNUnuquez{o;M3+o+Qd$dMJCxG0-XPD%}gPJJ|Wo{_~704c7 zkUga+a{{RNp@N4Fcgh4s=NAW!5Yi1YryONoJ(M}nAbT%S=1?QV#7hl*4vGObHtjl7 zoUL1$ZPqYLEI4d^0qCg1HfNe2F)nQ9<7BP0Xs^m>FDhWKVrZ`RV6SpuH&AFV5@@fo zU^hr;FPCU9SkPWl!CrpBWr1@$*gO?ajT470uQ&t!1~e?0N!AMJeFjAy1_ovz%>u+L zKmtIZD!{rhd@DKV30lPuV-=gpOF6-#-qSel&1!rJ^s zOuR93Nd0OqcATnR<25)ibTM~spjs>HsjJh}w`kz$V9Yqw36X_(3m#d_95;RzeiwYr zVJ~zB{tk>zhe!pZ+9ObvR-?LC=l@1_;gADugSvCGWp}DL?&jyG^6*vmLp6_}`QhWG z=cj}FgW>ykJ+~hn!<++6YQnFvEgjpyhacos(@_jaeN_&lK8>Tlmo562900910S&Di1C%zX3CZRdtYAXerm|>6yQ8?q4gU~PEm~~~+k20Y@QJBt{sZ1q%Dl;ML?p}Yh zeu$uu011!)36KB@kN^pg011!)36Q`h5~$w)>m6y_3uEN{e+@A2|3w_&*y#TM^T(6t z@Ah^tJvrFnf4ctQJMaHRc>iDfKcYnfBtQZrKmsH{0wh2JB(OCII7nkl-~YG#fA{~t E0K<|ACIA2c literal 24876 zcmeI4O-NKx7>3WNQIur0h@zlL>=&DvqRgOz!a=1-ON9vHI^&EvI}QFoKNjx?-#zC$_uO;OdG2h!d*;1w z=BJ(;V=6<&tVX%Um<=d4cH>aZwsD*@CRS)eh5gXh&bE3Ss^Kyb5CIVo0TB=Z5fA|p z5CIVo0TB>^6-?mWx4C&F^dThvrUJemK8wmt6GqLLt?(AOWwoDbj$evjXk%;8@Sb2% z<2bW$%j%3@>?nq}qE`J7XC;^27qYp@ucKw%r>Dz|PIRc72D zTGr^mwah@u$_(@l;za5E9=qd_0gbUY7pEn7Eb= z4_Ir=cq}+{`3U2%ALq0M-iUY|%2||ol&rVIX?(_X_FW72-w)xEjK7aCoG*Q%qa(x7 z{!B8O8tYFXrfq|B9(AqnyXQ^Al}8_5ne!iyJv@ZAFxfIIO6;`&-O6Su(qq(%zmrkV8!)9kTkr^<%IB=!8zr*f~d$^SY zh`pSTr;e7yZHRlnzqd!iulWUw-O~^^! z*u2?}i{q0G+6z~Nk=g&eM$29!(^qRGH=4APcoTr7M~Bnd#PHRTsOe4QBH2Vw-(bXT zisTy`B0a?(YKm6F1^WLG|2$8v zby@BI0=j8lH*H@R+)K9w*xq$0`60n&Y5So)*o14SA*e!GFrTJ>F+Kkz#%RHXlNf{R zEoa4bmuUFI=*{`V>(PnxXJ5~1@gItq7c5lrdYtF|sbi-mojUzVlzEiDL$gmkL^;jA zr`MnR`gFSK(~)Pln&daW diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.x86.c b/llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.x86.c index 8153fc294680d..830456141be1c 100644 --- a/llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.x86.c +++ b/llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.x86.c @@ -4,11 +4,11 @@ * - fat.macho.remarks.x86 */ -/* for ARCH in x86_64 x86_64h i386 +/* for ARCH in x86_64 x86_64h * do * clang -gline-tables-only -c fat.macho.remarks.x86.c -fsave-optimization-record=bitstream -foptimization-record-file=fat.macho.remarks."$ARCH".opt.bitstream -mllvm -remarks-section -arch "$ARCH" * done - * lipo -create -output fat.macho.remarks.x86.o fat.macho.remarks.x86_64.o fat.macho.remarks.x86_64h.o fat.macho.remarks.i386.o - * clang -gline-tables-only fat.macho.remarks.x86.o -arch x86_64 -arch x86_64h -arch i386 -o fat.macho.remarks.x86 + * lipo -create -output fat.macho.remarks.x86.o fat.macho.remarks.x86_64.o fat.macho.remarks.x86_64h.o + * clang -gline-tables-only fat.macho.remarks.x86.o -arch x86_64 -arch x86_64h -o fat.macho.remarks.x86 */ int main(void) { return 0; } diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.x86.o b/llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.x86.o deleted file mode 100644 index 2f5b8f3c4bc09d5583092b96a76797dbd4708358..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14440 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 oKmtIZD!{ %t/basic.macho.remarks.empty.x86_64 - -RUN: dsymutil -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%p/../Inputs %t/basic.macho.remarks.empty.x86_64 - -Check that the remark file in the bundle does not exist: -RUN: not cat %t/basic.macho.remarks.empty.x86_64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.empty.x86_64 2>&1 - -RUN: dsymutil --linker parallel -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%p/../Inputs %t/basic.macho.remarks.empty.x86_64 - -Check that the remark file in the bundle does not exist: -RUN: not cat %t/basic.macho.remarks.empty.x86_64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.empty.x86_64 2>&1 diff --git a/llvm/test/tools/dsymutil/X86/remarks-linking-bundle.test b/llvm/test/tools/dsymutil/X86/remarks-linking-bundle.test deleted file mode 100644 index d85cd54c8f640..0000000000000 --- a/llvm/test/tools/dsymutil/X86/remarks-linking-bundle.test +++ /dev/null @@ -1,67 +0,0 @@ -RUN: rm -rf %t -RUN: mkdir -p %t -RUN: cat %p/../Inputs/remarks/basic.macho.remarks.x86_64 > %t/basic.macho.remarks.x86_64 - -RUN: dsymutil -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%p/../Inputs %t/basic.macho.remarks.x86_64 - -Check that the remark file in the bundle exists and is sane: -RUN: llvm-bcanalyzer -dump %t/basic.macho.remarks.x86_64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.x86_64 | FileCheck %s - -RUN: dsymutil --linker parallel -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%p/../Inputs %t/basic.macho.remarks.x86_64 - -Check that the remark file in the bundle exists and is sane: -RUN: llvm-bcanalyzer -dump %t/basic.macho.remarks.x86_64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.x86_64 | FileCheck %s - -Now emit it in a different format: YAML. -RUN: dsymutil -remarks-output-format=yaml -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%p/../Inputs %t/basic.macho.remarks.x86_64 -RUN: cat %t/basic.macho.remarks.x86_64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.x86_64 | FileCheck %s --check-prefix=CHECK-YAML - -RUN: dsymutil --linker parallel -remarks-output-format=yaml -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%p/../Inputs %t/basic.macho.remarks.x86_64 -RUN: cat %t/basic.macho.remarks.x86_64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.x86_64 | FileCheck %s --check-prefix=CHECK-YAML - -CHECK: %t/fat.macho.remarks.x86 +RUN: llvm-remarkutil yaml2bitstream %p/../Inputs/private/tmp/remarks/fat.macho.remarks.x86_64.opt.yaml -o %t/private/tmp/remarks/fat.macho.remarks.x86_64.opt.bitstream +RUN: llvm-remarkutil yaml2bitstream %p/../Inputs/private/tmp/remarks/fat.macho.remarks.x86_64h.opt.yaml -o %t/private/tmp/remarks/fat.macho.remarks.x86_64h.opt.bitstream -RUN: dsymutil -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%p/../Inputs %t/fat.macho.remarks.x86 +RUN: dsymutil -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%t %t/fat.macho.remarks.x86 Check that the remark files in the bundle exist and are all sane: RUN: llvm-bcanalyzer -dump %t/fat.macho.remarks.x86.dSYM/Contents/Resources/Remarks/fat.macho.remarks.x86-x86_64h | FileCheck %s RUN: llvm-bcanalyzer -dump %t/fat.macho.remarks.x86.dSYM/Contents/Resources/Remarks/fat.macho.remarks.x86-x86_64 | FileCheck %s -RUN: llvm-bcanalyzer -dump %t/fat.macho.remarks.x86.dSYM/Contents/Resources/Remarks/fat.macho.remarks.x86-i386 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-i386 -RUN: dsymutil --linker parallel -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%p/../Inputs %t/fat.macho.remarks.x86 +RUN: dsymutil --linker parallel -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%t %t/fat.macho.remarks.x86 Check that the remark files in the bundle exist and are all sane: RUN: llvm-bcanalyzer -dump %t/fat.macho.remarks.x86.dSYM/Contents/Resources/Remarks/fat.macho.remarks.x86-x86_64h | FileCheck %s RUN: llvm-bcanalyzer -dump %t/fat.macho.remarks.x86.dSYM/Contents/Resources/Remarks/fat.macho.remarks.x86-x86_64 | FileCheck %s -RUN: llvm-bcanalyzer -dump %t/fat.macho.remarks.x86.dSYM/Contents/Resources/Remarks/fat.macho.remarks.x86-i386 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-i386 CHECK: 5MZcn=ons0A^kWZ~y=R diff --git a/llvm/test/tools/llvm-remarkutil/Inputs/two-remarks.v0.bitstream b/llvm/test/tools/llvm-remarkutil/Inputs/two-remarks.v0.bitstream new file mode 100644 index 0000000000000000000000000000000000000000..2a528436791aeb4b28ef64cf6f9746804a6047eb GIT binary patch literal 500 zcmWIY4f1B>U|?`%U|?Wp+~lyu$?}4;g^kTYjXllQK-Q9G>nY7P4USejnl1Mnc5JX< z;}B7jlXDb1wNUnuquez{o;M3+o+Qd$dMJCxG0_-`GIVQ0>!}L5nsF|`*=9VH*pX>n!*;9%#CxB)=RPfN@PMM(S{NkVyLb^fbl%ve6 zhcX8mWbY-)9BPDEbg7}wK{3F_rd?->vvo_e%^GHj1&6IK0Nr}n=1lV=#)a*CoUD}= z?Nu4=MFs3t49(RZ>{Slz1`6#(0_{~mmnF29OSBg(XfLT?FTdcjz_}f4o{Fc&iNlsx zoPk~j8kWo?YsH|*!@!^k3>y|8-T=f5%QzVdit=;v(^CsFfh0q4Nn&z#aAs91Lt1HG zvH^o%X)ajEsj?)sn86SzUzC}b&Y(~XQm2pv5>?2|QvfM0$;{7VNG#6PEdVMhNiAaV z%quP_Dg}!>=a=S{fDA(tD`o)dgsVU`2IMqV0R{$UAiae_-~b~dHyg5;$rFJCER5V- GATa>F(5cP< literal 0 HcmV?d00001 diff --git a/llvm/test/tools/llvm-remarkutil/convert.test b/llvm/test/tools/llvm-remarkutil/convert.test index 0d7ab8e4682a5..2b1bdcb0a5b3a 100644 --- a/llvm/test/tools/llvm-remarkutil/convert.test +++ b/llvm/test/tools/llvm-remarkutil/convert.test @@ -1,8 +1,11 @@ RUN: llvm-remarkutil bitstream2yaml %p/Inputs/two-remarks.bitstream -o %t.yaml RUN: FileCheck %s -strict-whitespace < %t.yaml +RUN: not llvm-remarkutil bitstream2yaml %p/Inputs/two-remarks.v0.bitstream 2>&1 -o - | FileCheck %s --check-prefix=ERR RUN: llvm-remarkutil yaml2bitstream %p/Inputs/two-remarks.yaml -o %t.bitstream RUN: llvm-remarkutil bitstream2yaml %t.bitstream -o - | FileCheck %s -strict-whitespace +; ERR: error: Unsupported remark container version (expected: 1, read: 0). Please upgrade/downgrade your toolchain to read this container. + ; CHECK: --- !Analysis ; CHECK-NEXT: Pass: prologepilog ; CHECK-NEXT: Name: StackSize diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp index 138c5d0a513ed..b91c27e6a0f86 100644 --- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp +++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp @@ -291,6 +291,7 @@ ErrorOr> DwarfLinkerForBinary::loadObject( [&](StringRef FileName) { BinHolder.eraseObjectEntry(FileName); }); Error E = RL.link(*ErrorOrObj); + // FIXME: Remark parsing errors are not propagated to the user. if (Error NewE = handleErrors( std::move(E), [&](std::unique_ptr EC) -> Error { return remarksErrorHandler(Obj, *this, std::move(EC)); diff --git a/llvm/tools/llc/llc.cpp b/llvm/tools/llc/llc.cpp index b3d7185e7f144..a2327fbc3b66a 100644 --- a/llvm/tools/llc/llc.cpp +++ b/llvm/tools/llc/llc.cpp @@ -387,13 +387,13 @@ int main(int argc, char **argv) { // Set a diagnostic handler that doesn't exit on the first error Context.setDiagnosticHandler(std::make_unique()); - Expected> RemarksFileOrErr = + Expected RemarksFileOrErr = setupLLVMOptimizationRemarks(Context, RemarksFilename, RemarksPasses, RemarksFormat, RemarksWithHotness, RemarksHotnessThreshold); if (Error E = RemarksFileOrErr.takeError()) reportError(std::move(E), RemarksFilename); - std::unique_ptr RemarksFile = std::move(*RemarksFileOrErr); + LLVMRemarkFileHandle RemarksFile = std::move(*RemarksFileOrErr); if (InputLanguage != "" && InputLanguage != "ir" && InputLanguage != "mir") reportError("input language must be '', 'IR' or 'MIR'"); diff --git a/llvm/tools/llvm-remarkutil/RemarkConvert.cpp b/llvm/tools/llvm-remarkutil/RemarkConvert.cpp index 207c5e0a8048b..203c8266b077d 100644 --- a/llvm/tools/llvm-remarkutil/RemarkConvert.cpp +++ b/llvm/tools/llvm-remarkutil/RemarkConvert.cpp @@ -80,8 +80,8 @@ static Error tryReserializeYAML2Bitstream( if (!MaybeOF) return MaybeOF.takeError(); auto OF = std::move(*MaybeOF); - auto MaybeSerializer = createRemarkSerializer( - OutputFormat, SerializerMode::Standalone, OF->os(), std::move(StrTab)); + auto MaybeSerializer = + createRemarkSerializer(OutputFormat, OF->os(), std::move(StrTab)); if (!MaybeSerializer) return MaybeSerializer.takeError(); auto Serializer = std::move(*MaybeSerializer); @@ -110,8 +110,7 @@ static Error tryBitstream2YAML() { if (!MaybeOF) return MaybeOF.takeError(); auto OF = std::move(*MaybeOF); - auto MaybeSerializer = createRemarkSerializer( - OutputFormat, SerializerMode::Standalone, OF->os()); + auto MaybeSerializer = createRemarkSerializer(OutputFormat, OF->os()); if (!MaybeSerializer) return MaybeSerializer.takeError(); diff --git a/llvm/tools/opt/optdriver.cpp b/llvm/tools/opt/optdriver.cpp index 26902b213571f..d4fa6eb50cda7 100644 --- a/llvm/tools/opt/optdriver.cpp +++ b/llvm/tools/opt/optdriver.cpp @@ -510,7 +510,7 @@ extern "C" int optMain( if (!DisableDITypeMap) Context.enableDebugTypeODRUniquing(); - Expected> RemarksFileOrErr = + Expected RemarksFileOrErr = setupLLVMOptimizationRemarks(Context, RemarksFilename, RemarksPasses, RemarksFormat, RemarksWithHotness, RemarksHotnessThreshold); @@ -518,7 +518,7 @@ extern "C" int optMain( errs() << toString(std::move(E)) << '\n'; return 1; } - std::unique_ptr RemarksFile = std::move(*RemarksFileOrErr); + LLVMRemarkFileHandle RemarksFile = std::move(*RemarksFileOrErr); // Load the input module... auto SetDataLayout = [&](StringRef IRTriple, diff --git a/llvm/unittests/Remarks/BitstreamRemarksFormatTest.cpp b/llvm/unittests/Remarks/BitstreamRemarksFormatTest.cpp index ea61691f4c835..ddf744521ef13 100644 --- a/llvm/unittests/Remarks/BitstreamRemarksFormatTest.cpp +++ b/llvm/unittests/Remarks/BitstreamRemarksFormatTest.cpp @@ -21,7 +21,7 @@ TEST(BitstreamRemarksFormat, Magic) { // This should be updated whenever any of the tests below are modified. TEST(BitstreamRemarksFormat, ContainerVersion) { - EXPECT_EQ(remarks::CurrentContainerVersion, 0UL); + EXPECT_EQ(remarks::CurrentContainerVersion, 1UL); } // The values of the current blocks should not change over time. diff --git a/llvm/unittests/Remarks/BitstreamRemarksParsingTest.cpp b/llvm/unittests/Remarks/BitstreamRemarksParsingTest.cpp index 6234931b3bece..f5973f5431c9c 100644 --- a/llvm/unittests/Remarks/BitstreamRemarksParsingTest.cpp +++ b/llvm/unittests/Remarks/BitstreamRemarksParsingTest.cpp @@ -14,7 +14,7 @@ using namespace llvm; -template void parseGood(const char (&Buf)[N]) { +template static void parseGood(const char (&Buf)[N]) { // 1. Parse the YAML remark -> FromYAMLRemark // 2. Serialize it to bitstream -> BSStream // 3. Parse it back -> FromBSRemark @@ -48,11 +48,11 @@ template void parseGood(const char (&Buf)[N]) { std::string BSBuf; raw_string_ostream BSStream(BSBuf); Expected> BSSerializer = - remarks::createRemarkSerializer(remarks::Format::Bitstream, - remarks::SerializerMode::Standalone, - BSStream, std::move(BSStrTab)); + remarks::createRemarkSerializer(remarks::Format::Bitstream, BSStream, + std::move(BSStrTab)); EXPECT_FALSE(errorToBool(BSSerializer.takeError())); (*BSSerializer)->emit(*FromYAMLRemark); + (*BSSerializer)->finalize(); // 3. Expected> MaybeBSParser = @@ -256,11 +256,11 @@ TEST(BitstreamRemarks, ContentsCAPI) { std::string BSBuf; raw_string_ostream BSStream(BSBuf); Expected> BSSerializer = - remarks::createRemarkSerializer(remarks::Format::Bitstream, - remarks::SerializerMode::Standalone, - BSStream, std::move(BSStrTab)); + remarks::createRemarkSerializer(remarks::Format::Bitstream, BSStream, + std::move(BSStrTab)); EXPECT_FALSE(errorToBool(BSSerializer.takeError())); (*BSSerializer)->emit(ToSerializeRemark); + (*BSSerializer)->finalize(); StringRef Buf = BSStream.str(); LLVMRemarkParserRef Parser = diff --git a/llvm/unittests/Remarks/BitstreamRemarksSerializerTest.cpp b/llvm/unittests/Remarks/BitstreamRemarksSerializerTest.cpp index 8113d35b3aff8..3b460965fdb23 100644 --- a/llvm/unittests/Remarks/BitstreamRemarksSerializerTest.cpp +++ b/llvm/unittests/Remarks/BitstreamRemarksSerializerTest.cpp @@ -7,8 +7,8 @@ //===----------------------------------------------------------------------===// #include "llvm/Bitcode/BitcodeAnalyzer.h" -#include "llvm/Remarks/BitstreamRemarkSerializer.h" #include "llvm/Remarks/Remark.h" +#include "llvm/Remarks/RemarkSerializer.h" #include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" #include @@ -34,23 +34,24 @@ static void checkAnalyze(StringRef Input, StringRef Expected) { EXPECT_EQ(OutputOS.str(), Expected); } -static void check(remarks::SerializerMode Mode, const remarks::Remark &R, - StringRef ExpectedR, std::optional ExpectedMeta, - std::optional StrTab) { +static void check(const remarks::Remark &R, StringRef ExpectedR, + std::optional ExpectedMeta = std::nullopt, + std::optional StrTab = std::nullopt) { // Emit the remark. std::string InputBuf; raw_string_ostream InputOS(InputBuf); Expected> MaybeSerializer = [&] { if (StrTab) - return createRemarkSerializer(remarks::Format::Bitstream, Mode, InputOS, + return createRemarkSerializer(remarks::Format::Bitstream, InputOS, std::move(*StrTab)); else - return createRemarkSerializer(remarks::Format::Bitstream, Mode, InputOS); + return createRemarkSerializer(remarks::Format::Bitstream, InputOS); }(); EXPECT_FALSE(errorToBool(MaybeSerializer.takeError())); std::unique_ptr Serializer = std::move(*MaybeSerializer); Serializer->emit(R); + Serializer->finalize(); // Analyze the serialized remark. checkAnalyze(InputOS.str(), ExpectedR); @@ -66,20 +67,6 @@ static void check(remarks::SerializerMode Mode, const remarks::Remark &R, } } -static void check(const remarks::Remark &R, StringRef ExpectedR, - StringRef ExpectedMeta, - std::optional StrTab = std::nullopt) { - return check(remarks::SerializerMode::Separate, R, ExpectedR, ExpectedMeta, - std::move(StrTab)); -} - -static void -checkStandalone(const remarks::Remark &R, StringRef ExpectedR, - std::optional StrTab = std::nullopt) { - return check(remarks::SerializerMode::Standalone, R, ExpectedR, - /*ExpectedMeta=*/std::nullopt, std::move(StrTab)); -} - TEST(BitstreamRemarkSerializer, SeparateRemarkFileNoOptionals) { remarks::Remark R; R.RemarkType = remarks::Type::Missed; @@ -89,19 +76,21 @@ TEST(BitstreamRemarkSerializer, SeparateRemarkFileNoOptionals) { check(R, "\n" "\n" - " \n" + " \n" " \n" "\n" "\n" " \n" - "\n", - "\n" - "\n" - " \n" - " blob data = " + "\n" + "\n" + " blob data = " "'remark\\x00pass\\x00function\\x00'\n" - " blob data = " - "'" EXTERNALFILETESTPATH"'\n" + "\n", + "\n" + "\n" + " \n" + " blob data = " + "'" EXTERNALFILETESTPATH "'\n" "\n"); } @@ -118,19 +107,21 @@ TEST(BitstreamRemarkSerializer, SeparateRemarkFileNoOptionalsSeparateStrTab) { check(R, "\n" "\n" - " \n" + " \n" " \n" "\n" "\n" " \n" - "\n", - "\n" - "\n" - " \n" - " blob data = " + "\n" + "\n" + " blob data = " "'function\\x00pass\\x00remark\\x00'\n" - " blob data = " - "'" EXTERNALFILETESTPATH"'\n" + "\n", + "\n" + "\n" + " \n" + " blob data = " + "'" EXTERNALFILETESTPATH "'\n" "\n", std::move(StrTab)); } @@ -148,20 +139,22 @@ TEST(BitstreamRemarkSerializer, SeparateRemarkFileDebugLoc) { check(R, "\n" "\n" - " \n" + " \n" " \n" "\n" "\n" " \n" " \n" - "\n", - "\n" - "\n" - " \n" - " blob data = " + "\n" + "\n" + " blob data = " "'remark\\x00pass\\x00function\\x00path\\x00'\n" - " blob data = " - "'" EXTERNALFILETESTPATH"'\n" + "\n", + "\n" + "\n" + " \n" + " blob data = " + "'" EXTERNALFILETESTPATH "'\n" "\n"); } @@ -175,20 +168,22 @@ TEST(BitstreamRemarkSerializer, SeparateRemarkFileHotness) { check(R, "\n" "\n" - " \n" + " \n" " \n" "\n" "\n" " \n" " \n" - "\n", - "\n" - "\n" - " \n" - " blob data = " + "\n" + "\n" + " blob data = " "'remark\\x00pass\\x00function\\x00'\n" - " blob data = " - "'" EXTERNALFILETESTPATH"'\n" + "\n", + "\n" + "\n" + " \n" + " blob data = " + "'" EXTERNALFILETESTPATH "'\n" "\n"); } @@ -204,20 +199,22 @@ TEST(BitstreamRemarkSerializer, SeparateRemarkFileArgNoDebugLoc) { check(R, "\n" "\n" - " \n" + " \n" " \n" "\n" "\n" " \n" " \n" - "\n", - "\n" - "\n" - " \n" - " blob data = " + "\n" + "\n" + " blob data = " "'remark\\x00pass\\x00function\\x00key\\x00value\\x00'\n" - " blob data = " - "'" EXTERNALFILETESTPATH"'\n" + "\n", + "\n" + "\n" + " \n" + " blob data = " + "'" EXTERNALFILETESTPATH "'\n" "\n"); } @@ -237,21 +234,23 @@ TEST(BitstreamRemarkSerializer, SeparateRemarkFileArgDebugLoc) { check(R, "\n" "\n" - " \n" + " \n" " \n" "\n" "\n" " \n" " \n" - "\n", - "\n" - "\n" - " \n" - " blob data = " + "\n" + "\n" + " blob data = " "'remark\\x00pass\\x00function\\x00key\\x00value\\x00path\\x00'\n" - " blob data = " - "'" EXTERNALFILETESTPATH"'\n" + "\n", + "\n" + "\n" + " \n" + " blob data = " + "'" EXTERNALFILETESTPATH "'\n" "\n"); } @@ -276,7 +275,7 @@ TEST(BitstreamRemarkSerializer, SeparateRemarkFileAll) { check(R, "\n" "\n" - " \n" + " \n" " \n" "\n" "\n" @@ -285,14 +284,17 @@ TEST(BitstreamRemarkSerializer, SeparateRemarkFileAll) { " \n" " \n" - "\n", - "\n" - "\n" - " \n" - " blob data = " + "\n" + "\n" + " blob data = " "'remark\\x00pass\\x00function\\x00path\\x00key\\x00value\\x00argpa" - "th\\x00'\n blob data = " - "'" EXTERNALFILETESTPATH"'\n" + "th\\x00'\n" + "\n", + "\n" + "\n" + " \n" + " blob data = " + "'" EXTERNALFILETESTPATH "'\n" "\n"); } @@ -323,15 +325,12 @@ TEST(BitstreamRemarkSerializer, Standalone) { R.Args.back().Loc->SourceFilePath = "argpath"; R.Args.back().Loc->SourceLine = 11; R.Args.back().Loc->SourceColumn = 66; - checkStandalone( + check( R, "\n" - "\n" - " \n" + "\n" + " \n" " \n" - " blob data = " - "'pass\\x00remark\\x00function\\x00path\\x00key\\x00value\\x00argpath\\x0" - "0'\n" "\n" "\n" " \n" @@ -339,6 +338,11 @@ TEST(BitstreamRemarkSerializer, Standalone) { " \n" " \n" - "\n", - std::move(StrTab)); + "\n" + "\n" + " blob data = " + "'pass\\x00remark\\x00function\\x00path\\x00key\\x00value\\x00argpath\\x0" + "0'\n" + "\n", + std::nullopt, std::move(StrTab)); } diff --git a/llvm/unittests/Remarks/RemarksLinkingTest.cpp b/llvm/unittests/Remarks/RemarksLinkingTest.cpp index 89de9e8f4f95d..54942ff681b47 100644 --- a/llvm/unittests/Remarks/RemarksLinkingTest.cpp +++ b/llvm/unittests/Remarks/RemarksLinkingTest.cpp @@ -133,16 +133,18 @@ TEST(Remarks, LinkingGoodBitstream) { "...\n", remarks::Format::Bitstream, "\n" - "\n" - " \n" + "\n" + " \n" " \n" - " blob data = " - "'inline\\x00NoDefinition\\x00foo\\x00file.c\\x00'\n" "\n" "\n" " \n" " \n" - "\n"); + "\n" + "\n" + " blob data = " + "'inline\\x00NoDefinition\\x00foo\\x00file.c\\x00'\n" + "\n"); // Check that we keep remarks without debug info. check(remarks::Format::YAML, @@ -153,15 +155,17 @@ TEST(Remarks, LinkingGoodBitstream) { "...\n", remarks::Format::Bitstream, "\n" - "\n" - " \n" + "\n" + " \n" " \n" - " blob data = " - "'inline\\x00NoDefinition\\x00foo\\x00'\n" "\n" "\n" " \n" - "\n"); + "\n" + "\n" + " blob data = " + "'inline\\x00NoDefinition\\x00foo\\x00'\n" + "\n"); // Check that we deduplicate remarks. check(remarks::Format::YAML, @@ -179,16 +183,18 @@ TEST(Remarks, LinkingGoodBitstream) { "...\n", remarks::Format::Bitstream, "\n" - "\n" - " \n" + "\n" + " \n" " \n" - " blob data = " - "'inline\\x00NoDefinition\\x00foo\\x00file.c\\x00'\n" "\n" "\n" " \n" " \n" - "\n"); + "\n" + "\n" + " blob data = " + "'inline\\x00NoDefinition\\x00foo\\x00file.c\\x00'\n" + "\n"); } TEST(Remarks, LinkingGoodStrTab) { @@ -209,11 +215,9 @@ TEST(Remarks, LinkingGoodStrTab) { "...\n", remarks::Format::Bitstream, "\n" - "\n" - " \n" + "\n" + " \n" " \n" - " blob data = " - "'inline\\x00NoDefinition\\x00foo\\x00file.c\\x00Ok\\x00'\n" "\n" "\n" " \n" @@ -222,7 +226,11 @@ TEST(Remarks, LinkingGoodStrTab) { "\n" " \n" " \n" - "\n"); + "\n" + "\n" + " blob data = " + "'inline\\x00NoDefinition\\x00foo\\x00file.c\\x00Ok\\x00'\n" + "\n"); } // Check that we propagate parsing errors. diff --git a/llvm/unittests/Remarks/YAMLRemarksSerializerTest.cpp b/llvm/unittests/Remarks/YAMLRemarksSerializerTest.cpp index 7e994ac4d58bc..974356d9cf30a 100644 --- a/llvm/unittests/Remarks/YAMLRemarksSerializerTest.cpp +++ b/llvm/unittests/Remarks/YAMLRemarksSerializerTest.cpp @@ -23,23 +23,23 @@ using namespace llvm; static void check(remarks::Format SerializerFormat, - remarks::SerializerMode Mode, ArrayRef Rs, - StringRef ExpectedR, std::optional ExpectedMeta, + ArrayRef Rs, StringRef ExpectedR, + std::optional ExpectedMeta, std::optional StrTab = std::nullopt) { std::string Buf; raw_string_ostream OS(Buf); Expected> MaybeS = [&] { if (StrTab) - return createRemarkSerializer(SerializerFormat, Mode, OS, - std::move(*StrTab)); + return createRemarkSerializer(SerializerFormat, OS, std::move(*StrTab)); else - return createRemarkSerializer(SerializerFormat, Mode, OS); + return createRemarkSerializer(SerializerFormat, OS); }(); EXPECT_FALSE(errorToBool(MaybeS.takeError())); std::unique_ptr S = std::move(*MaybeS); for (const remarks::Remark &R : Rs) S->emit(R); + S->finalize(); EXPECT_EQ(OS.str(), ExpectedR); if (ExpectedMeta) { @@ -54,8 +54,7 @@ static void check(remarks::Format SerializerFormat, static void check(remarks::Format SerializerFormat, const remarks::Remark &R, StringRef ExpectedR, StringRef ExpectedMeta, std::optional StrTab = std::nullopt) { - return check(SerializerFormat, remarks::SerializerMode::Separate, - ArrayRef(&R, &R + 1), ExpectedR, ExpectedMeta, + return check(SerializerFormat, ArrayRef(&R, &R + 1), ExpectedR, ExpectedMeta, std::move(StrTab)); } @@ -63,8 +62,7 @@ static void checkStandalone(remarks::Format SerializerFormat, const remarks::Remark &R, StringRef ExpectedR, std::optional StrTab = std::nullopt) { - return check(SerializerFormat, remarks::SerializerMode::Standalone, - ArrayRef(&R, &R + 1), ExpectedR, + return check(SerializerFormat, ArrayRef(&R, &R + 1), ExpectedR, /*ExpectedMeta=*/std::nullopt, std::move(StrTab)); } @@ -165,3 +163,33 @@ TEST(YAMLRemarks, SerializerRemarkParsedStrTabStandaloneNoStrTab) { "...\n"), std::move(PreFilledStrTab)); } + +TEST(YAMLRemarks, SerializerRemarkStringRefOOBRead) { + remarks::Remark R; + R.RemarkType = remarks::Type::Missed; + R.PassName = StringRef("passAAAA", 4); + R.RemarkName = StringRef("nameAAAA", 4); + R.FunctionName = StringRef("funcAAAA", 4); + R.Loc = remarks::RemarkLocation{StringRef("pathAAAA", 4), 3, 4}; + R.Hotness = 5; + R.Args.emplace_back(); + R.Args.back().Key = StringRef("keyAAAA", 3); + R.Args.back().Val = StringRef("valueAAAA", 5); + R.Args.emplace_back(); + R.Args.back().Key = StringRef("keydebugAAAA", 8); + R.Args.back().Val = StringRef("valuedebugAAAA", 10); + R.Args.back().Loc = + remarks::RemarkLocation{StringRef("argpathAAAA", 7), 6, 7}; + checkStandalone(remarks::Format::YAML, R, + "--- !Missed\n" + "Pass: pass\n" + "Name: name\n" + "DebugLoc: { File: path, Line: 3, Column: 4 }\n" + "Function: func\n" + "Hotness: 5\n" + "Args:\n" + " - key: value\n" + " - keydebug: valuedebug\n" + " DebugLoc: { File: argpath, Line: 6, Column: 7 }\n" + "...\n"); +} diff --git a/mlir/include/mlir/Remark/RemarkStreamer.h b/mlir/include/mlir/Remark/RemarkStreamer.h index 8bfd176d9bade..170d6b439a442 100644 --- a/mlir/include/mlir/Remark/RemarkStreamer.h +++ b/mlir/include/mlir/Remark/RemarkStreamer.h @@ -26,14 +26,15 @@ class LLVMRemarkStreamer final : public MLIRRemarkStreamerBase { createToFile(llvm::StringRef path, llvm::remarks::Format fmt); void streamOptimizationRemark(const Remark &remark) override; - void finalize() override {} + void finalize() override; ~LLVMRemarkStreamer() override; private: LLVMRemarkStreamer() = default; - std::unique_ptr remarkStreamer; std::unique_ptr file; + // RemarkStreamer must be destructed before file is destroyed! + std::unique_ptr remarkStreamer; }; } // namespace mlir::remark::detail diff --git a/mlir/lib/Remark/RemarkStreamer.cpp b/mlir/lib/Remark/RemarkStreamer.cpp index 8e3544ff2c34c..d213a1a2068d6 100644 --- a/mlir/lib/Remark/RemarkStreamer.cpp +++ b/mlir/lib/Remark/RemarkStreamer.cpp @@ -20,8 +20,7 @@ LLVMRemarkStreamer::createToFile(llvm::StringRef path, if (ec) return failure(); - auto serOr = llvm::remarks::createRemarkSerializer( - fmt, llvm::remarks::SerializerMode::Separate, f->os()); + auto serOr = llvm::remarks::createRemarkSerializer(fmt, f->os()); if (!serOr) { llvm::consumeError(serOr.takeError()); return failure(); @@ -50,6 +49,12 @@ LLVMRemarkStreamer::~LLVMRemarkStreamer() { if (file && remarkStreamer) file->keep(); } + +void LLVMRemarkStreamer::finalize() { + if (!remarkStreamer) + return; + remarkStreamer->releaseSerializer(); +} } // namespace mlir::remark::detail namespace mlir::remark { diff --git a/offload/plugins-nextgen/common/src/JIT.cpp b/offload/plugins-nextgen/common/src/JIT.cpp index 00720fa2d8103..92c0eb0500628 100644 --- a/offload/plugins-nextgen/common/src/JIT.cpp +++ b/offload/plugins-nextgen/common/src/JIT.cpp @@ -189,9 +189,10 @@ Expected> JITEngine::backend(Module &M, const std::string &ComputeUnitKind, unsigned OptLevel) { - auto RemarksFileOrErr = setupLLVMOptimizationRemarks( - M.getContext(), /*RemarksFilename=*/"", /*RemarksPasses=*/"", - /*RemarksFormat=*/"", /*RemarksWithHotness=*/false); + Expected RemarksFileOrErr = + setupLLVMOptimizationRemarks( + M.getContext(), /*RemarksFilename=*/"", /*RemarksPasses=*/"", + /*RemarksFormat=*/"", /*RemarksWithHotness=*/false); if (Error E = RemarksFileOrErr.takeError()) return std::move(E); if (*RemarksFileOrErr) From b27faa20ac131bf50a447b7cc7c0130893d58d71 Mon Sep 17 00:00:00 2001 From: Tobias Stadler Date: Mon, 22 Sep 2025 11:31:57 +0100 Subject: [PATCH 2/3] Hopefully fix SerializerFormat Created using spr 1.3.7-wip --- llvm/tools/llvm-remarkutil/RemarkFilter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/tools/llvm-remarkutil/RemarkFilter.cpp b/llvm/tools/llvm-remarkutil/RemarkFilter.cpp index 5685a24d4d1c3..acfef6608677c 100644 --- a/llvm/tools/llvm-remarkutil/RemarkFilter.cpp +++ b/llvm/tools/llvm-remarkutil/RemarkFilter.cpp @@ -53,7 +53,7 @@ static Error tryFilter() { SerializerFormat = Format::YAML; } - auto MaybeOF = getOutputFileForRemarks(OutputFileName, Format::YAML); + auto MaybeOF = getOutputFileForRemarks(OutputFileName, SerializerFormat); if (!MaybeOF) return MaybeOF.takeError(); auto OF = std::move(*MaybeOF); From 626eb4a81996a410be95db68da800f19aa6c9174 Mon Sep 17 00:00:00 2001 From: Tobias Stadler Date: Wed, 24 Sep 2025 01:39:24 +0100 Subject: [PATCH 3/3] Fix stray whitespace Created using spr 1.3.7-wip --- llvm/test/tools/llvm-remarkutil/filter.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/test/tools/llvm-remarkutil/filter.test b/llvm/test/tools/llvm-remarkutil/filter.test index 51f80386a09e7..8304b9f0129a8 100644 --- a/llvm/test/tools/llvm-remarkutil/filter.test +++ b/llvm/test/tools/llvm-remarkutil/filter.test @@ -2,7 +2,7 @@ RUN: llvm-remarkutil filter %p/Inputs/filter.yaml | diff %p/Inputs/filter.yaml - RUN: llvm-remarkutil filter --rfunction=func %p/Inputs/filter.yaml | diff %p/Inputs/filter.yaml - RUN: llvm-remarkutil filter --rremark-name=Remark %p/Inputs/filter.yaml | diff %p/Inputs/filter.yaml - RUN: llvm-remarkutil filter --rpass-name=pass %p/Inputs/filter.yaml | diff %p/Inputs/filter.yaml - -RUN: llvm-remarkutil filter --rfilter-arg-by=argval %p/Inputs/filter.yaml | diff %p/Inputs/filter.yaml - +RUN: llvm-remarkutil filter --rfilter-arg-by=argval %p/Inputs/filter.yaml | diff %p/Inputs/filter.yaml - RUN: llvm-remarkutil filter --rfunction=unc1 %p/Inputs/filter.yaml | FileCheck %s --strict-whitespace --check-prefix=REMARK1 RUN: llvm-remarkutil filter --rremark-name=ark3 %p/Inputs/filter.yaml | FileCheck %s --strict-whitespace --check-prefix=REMARK3