|
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,44 @@ 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<ToolOutputFile> RemarksFile, |
| 1881 | + std::unique_ptr<llvm::remarks::RemarkStreamer> RemarkStreamer, |
| 1882 | + std::unique_ptr<LLVMRemarkStreamer> LlvmRemarkStreamer |
| 1883 | + ) |
1869 | 1884 | : DiagnosticHandlerCallback(DiagnosticHandlerCallback),
|
1870 | 1885 | DiagnosticHandlerContext(DiagnosticHandlerContext),
|
1871 | 1886 | RemarkAllPasses(RemarkAllPasses),
|
1872 |
| - RemarkPasses(RemarkPasses) {} |
| 1887 | + RemarkPasses(std::move(RemarkPasses)), |
| 1888 | + RemarksFile(std::move(RemarksFile)), |
| 1889 | + RemarkStreamer(std::move(RemarkStreamer)), |
| 1890 | + LlvmRemarkStreamer(std::move(LlvmRemarkStreamer)) {} |
1873 | 1891 |
|
1874 | 1892 | virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
|
| 1893 | + if (this->LlvmRemarkStreamer) { |
| 1894 | + if (auto *OptDiagBase = dyn_cast<DiagnosticInfoOptimizationBase>(&DI)) { |
| 1895 | + if (OptDiagBase->isEnabled()) { |
| 1896 | + this->LlvmRemarkStreamer->emit(*OptDiagBase); |
| 1897 | + return true; |
| 1898 | + } |
| 1899 | + } |
| 1900 | + } |
1875 | 1901 | if (DiagnosticHandlerCallback) {
|
1876 | 1902 | DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
|
1877 | 1903 | return true;
|
@@ -1912,14 +1938,64 @@ extern "C" void LLVMRustContextConfigureDiagnosticHandler(
|
1912 | 1938 |
|
1913 | 1939 | bool RemarkAllPasses = false;
|
1914 | 1940 | std::vector<std::string> RemarkPasses;
|
| 1941 | + |
| 1942 | + // Since LlvmRemarkStreamer contains a pointer to RemarkStreamer, the ordering of the three |
| 1943 | + // members below is important. |
| 1944 | + std::unique_ptr<ToolOutputFile> RemarksFile; |
| 1945 | + std::unique_ptr<llvm::remarks::RemarkStreamer> RemarkStreamer; |
| 1946 | + std::unique_ptr<LLVMRemarkStreamer> LlvmRemarkStreamer; |
1915 | 1947 | };
|
1916 | 1948 |
|
1917 | 1949 | std::vector<std::string> Passes;
|
1918 | 1950 | for (size_t I = 0; I != RemarkPassesLen; ++I)
|
| 1951 | + { |
1919 | 1952 | Passes.push_back(RemarkPasses[I]);
|
| 1953 | + } |
| 1954 | + |
| 1955 | + // We need to hold onto both the streamers and the opened file |
| 1956 | + std::unique_ptr<ToolOutputFile> RemarkFile; |
| 1957 | + std::unique_ptr<llvm::remarks::RemarkStreamer> RemarkStreamer; |
| 1958 | + std::unique_ptr<LLVMRemarkStreamer> LlvmRemarkStreamer; |
| 1959 | + |
| 1960 | + if (RemarkFilePath != nullptr) { |
| 1961 | + std::error_code EC; |
| 1962 | + RemarkFile = std::make_unique<ToolOutputFile>( |
| 1963 | + RemarkFilePath, |
| 1964 | + EC, |
| 1965 | + llvm::sys::fs::OF_TextWithCRLF |
| 1966 | + ); |
| 1967 | + if (EC) { |
| 1968 | + std::string Error = std::string("Cannot create remark file: ") + |
| 1969 | + toString(errorCodeToError(EC)); |
| 1970 | + report_fatal_error(Twine(Error)); |
| 1971 | + } |
| 1972 | + |
| 1973 | + // Do not delete the file after we gather remarks |
| 1974 | + RemarkFile->keep(); |
| 1975 | + |
| 1976 | + auto RemarkSerializer = remarks::createRemarkSerializer( |
| 1977 | + llvm::remarks::Format::YAML, |
| 1978 | + remarks::SerializerMode::Separate, |
| 1979 | + RemarkFile->os() |
| 1980 | + ); |
| 1981 | + if (Error E = RemarkSerializer.takeError()) |
| 1982 | + { |
| 1983 | + std::string Error = std::string("Cannot create remark serializer: ") + toString(std::move(E)); |
| 1984 | + report_fatal_error(Twine(Error)); |
| 1985 | + } |
| 1986 | + RemarkStreamer = std::make_unique<llvm::remarks::RemarkStreamer>(std::move(*RemarkSerializer)); |
| 1987 | + LlvmRemarkStreamer = std::make_unique<LLVMRemarkStreamer>(*RemarkStreamer); |
| 1988 | + } |
1920 | 1989 |
|
1921 | 1990 | unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
|
1922 |
| - DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes)); |
| 1991 | + DiagnosticHandlerCallback, |
| 1992 | + DiagnosticHandlerContext, |
| 1993 | + RemarkAllPasses, |
| 1994 | + Passes, |
| 1995 | + std::move(RemarkFile), |
| 1996 | + std::move(RemarkStreamer), |
| 1997 | + std::move(LlvmRemarkStreamer) |
| 1998 | + )); |
1923 | 1999 | }
|
1924 | 2000 |
|
1925 | 2001 | extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) {
|
|
0 commit comments