|
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