|
7 | 7 | #include "llvm/IR/Instructions.h"
|
8 | 8 | #include "llvm/IR/Intrinsics.h"
|
9 | 9 | #include "llvm/IR/IntrinsicsARM.h"
|
| 10 | +#include "llvm/IR/LLVMRemarkStreamer.h" |
10 | 11 | #include "llvm/IR/Mangler.h"
|
| 12 | +#include "llvm/Remarks/RemarkStreamer.h" |
| 13 | +#include "llvm/Remarks/RemarkSerializer.h" |
| 14 | +#include "llvm/Remarks/RemarkFormat.h" |
| 15 | +#include "llvm/Support/ToolOutputFile.h" |
11 | 16 | #if LLVM_VERSION_GE(16, 0)
|
12 | 17 | #include "llvm/Support/ModRef.h"
|
13 | 18 | #endif
|
@@ -1855,23 +1860,41 @@ using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy;
|
1855 | 1860 | // When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise
|
1856 | 1861 | // the RemarkPasses array specifies individual passes for which remarks will be
|
1857 | 1862 | // enabled.
|
| 1863 | +// |
| 1864 | +// If RemarkFilePath is not NULL, optimization remarks will be streamed directly into this file, |
| 1865 | +// bypassing the diagnostics handler. |
1858 | 1866 | extern "C" void LLVMRustContextConfigureDiagnosticHandler(
|
1859 | 1867 | LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
|
1860 | 1868 | void *DiagnosticHandlerContext, bool RemarkAllPasses,
|
1861 |
| - const char * const * RemarkPasses, size_t RemarkPassesLen) { |
| 1869 | + const char * const * RemarkPasses, size_t RemarkPassesLen, |
| 1870 | + const char * RemarkFilePath |
| 1871 | +) { |
1862 | 1872 |
|
1863 | 1873 | class RustDiagnosticHandler final : public DiagnosticHandler {
|
1864 | 1874 | public:
|
1865 |
| - RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback, |
1866 |
| - void *DiagnosticHandlerContext, |
1867 |
| - bool RemarkAllPasses, |
1868 |
| - std::vector<std::string> RemarkPasses) |
| 1875 | + RustDiagnosticHandler( |
| 1876 | + LLVMDiagnosticHandlerTy DiagnosticHandlerCallback, |
| 1877 | + void *DiagnosticHandlerContext, |
| 1878 | + bool RemarkAllPasses, |
| 1879 | + std::vector<std::string> RemarkPasses, |
| 1880 | + std::unique_ptr<llvm::remarks::RemarkStreamer> RemarkStreamer, |
| 1881 | + std::unique_ptr<ToolOutputFile> RemarksFile |
| 1882 | + ) |
1869 | 1883 | : DiagnosticHandlerCallback(DiagnosticHandlerCallback),
|
1870 | 1884 | DiagnosticHandlerContext(DiagnosticHandlerContext),
|
1871 | 1885 | RemarkAllPasses(RemarkAllPasses),
|
1872 |
| - RemarkPasses(RemarkPasses) {} |
| 1886 | + RemarkPasses(std::move(RemarkPasses)), |
| 1887 | + RemarkStreamer(std::move(RemarkStreamer)), |
| 1888 | + RemarksFile(std::move(RemarksFile)) {} |
1873 | 1889 |
|
1874 | 1890 | virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
|
| 1891 | + if (this->RemarkStreamer) { |
| 1892 | + if (auto *OptDiagBase = dyn_cast<DiagnosticInfoOptimizationBase>(&DI)) { |
| 1893 | + LLVMRemarkStreamer Streamer(*this->RemarkStreamer); |
| 1894 | + Streamer.emit(*OptDiagBase); |
| 1895 | + return true; |
| 1896 | + } |
| 1897 | + } |
1875 | 1898 | if (DiagnosticHandlerCallback) {
|
1876 | 1899 | DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
|
1877 | 1900 | return true;
|
@@ -1912,14 +1935,51 @@ extern "C" void LLVMRustContextConfigureDiagnosticHandler(
|
1912 | 1935 |
|
1913 | 1936 | bool RemarkAllPasses = false;
|
1914 | 1937 | std::vector<std::string> RemarkPasses;
|
| 1938 | + std::unique_ptr<llvm::remarks::RemarkStreamer> RemarkStreamer; |
| 1939 | + std::unique_ptr<ToolOutputFile> RemarksFile; |
1915 | 1940 | };
|
1916 | 1941 |
|
1917 | 1942 | std::vector<std::string> Passes;
|
1918 | 1943 | for (size_t I = 0; I != RemarkPassesLen; ++I)
|
| 1944 | + { |
1919 | 1945 | Passes.push_back(RemarkPasses[I]);
|
| 1946 | + } |
| 1947 | + |
| 1948 | + // We need to hold onto both the streamer and the opened file |
| 1949 | + std::unique_ptr<llvm::remarks::RemarkStreamer> RemarkStreamer; |
| 1950 | + std::unique_ptr<ToolOutputFile> RemarkFile; |
| 1951 | + |
| 1952 | + if (RemarkFilePath != nullptr) { |
| 1953 | + std::error_code EC; |
| 1954 | + RemarkFile = std::make_unique<ToolOutputFile>( |
| 1955 | + RemarkFilePath, |
| 1956 | + EC, |
| 1957 | + llvm::sys::fs::OF_TextWithCRLF |
| 1958 | + ); |
| 1959 | + // Do not delete the file after we gather remarks |
| 1960 | + RemarkFile->keep(); |
| 1961 | + |
| 1962 | + auto RemarkSerializer = remarks::createRemarkSerializer( |
| 1963 | + llvm::remarks::Format::YAML, |
| 1964 | + remarks::SerializerMode::Separate, |
| 1965 | + RemarkFile->os() |
| 1966 | + ); |
| 1967 | + if (Error E = RemarkSerializer.takeError()) |
| 1968 | + { |
| 1969 | + // Is this OK? |
| 1970 | + report_fatal_error("Cannot create remark serializer"); |
| 1971 | + } |
| 1972 | + RemarkStreamer = std::make_unique<llvm::remarks::RemarkStreamer>(std::move(*RemarkSerializer)); |
| 1973 | + } |
1920 | 1974 |
|
1921 | 1975 | unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
|
1922 |
| - DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes)); |
| 1976 | + DiagnosticHandlerCallback, |
| 1977 | + DiagnosticHandlerContext, |
| 1978 | + RemarkAllPasses, |
| 1979 | + Passes, |
| 1980 | + std::move(RemarkStreamer), |
| 1981 | + std::move(RemarkFile) |
| 1982 | + )); |
1923 | 1983 | }
|
1924 | 1984 |
|
1925 | 1985 | extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) {
|
|
0 commit comments