================ @@ -0,0 +1,660 @@ +//===--- BackendDiagnosticHandler.cpp - Shared Backend Diagnostics ------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "clang/CodeGenUtils/BackendDiagnosticHandler.h" +#include "clang/Basic/CodeGenOptions.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticFrontend.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/ADT/Hashing.h" +#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" +#include "llvm/Demangle/Demangle.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/DiagnosticPrinter.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/raw_ostream.h" + +using namespace clang; +using namespace llvm; + +namespace { +/// Forwards llvm::DiagnosticHandler callbacks into a BackendDiagnosticConsumer. +class BackendDiagnosticHandlerImpl final : public DiagnosticHandler { +public: + BackendDiagnosticHandlerImpl(const CodeGenOptions &CGOpts, + BackendDiagnosticConsumer *Consumer) + : CodeGenOpts(CGOpts), Consumer(Consumer) {} + + bool handleDiagnostics(const DiagnosticInfo &DI) override { + Consumer->handleDiagnostics(DI); + return true; + } + + bool isAnalysisRemarkEnabled(StringRef PassName) const override { + return CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(PassName); + } + bool isMissedOptRemarkEnabled(StringRef PassName) const override { + return CodeGenOpts.OptimizationRemarkMissed.patternMatches(PassName); + } + bool isPassedOptRemarkEnabled(StringRef PassName) const override { + return CodeGenOpts.OptimizationRemark.patternMatches(PassName); + } + + bool isAnyRemarkEnabled() const override { + return CodeGenOpts.OptimizationRemarkAnalysis.hasValidPattern() || + CodeGenOpts.OptimizationRemarkMissed.hasValidPattern() || + CodeGenOpts.OptimizationRemark.hasValidPattern(); + } + +private: + const CodeGenOptions &CodeGenOpts; + BackendDiagnosticConsumer *Consumer; +}; + +/// Convert a location in a temporary llvm::SourceMgr buffer to be a valid +/// FullSourceLoc. +FullSourceLoc ConvertBackendLocation(const llvm::SMDiagnostic &D, + SourceManager &CSM) { + // Get both the clang and llvm source managers. The location is relative to + // a memory buffer that the LLVM Source Manager is handling, we need to add + // a copy to the Clang source manager. + const llvm::SourceMgr &LSM = *D.getSourceMgr(); + + // We need to copy the underlying LLVM memory buffer because llvm::SourceMgr + // already owns its one and clang::SourceManager wants to own its one. + const MemoryBuffer *LBuf = + LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); + + // Create the copy and transfer ownership to clang::SourceManager. + // TODO: Avoid copying files into memory. + std::unique_ptr<llvm::MemoryBuffer> CBuf = + llvm::MemoryBuffer::getMemBufferCopy(LBuf->getBuffer(), + LBuf->getBufferIdentifier()); + // FIXME: Keep a file ID map instead of creating new IDs for each location. + FileID FID = CSM.createFileID(std::move(CBuf)); + + // Translate the offset into the file. + unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart(); + SourceLocation NewLoc = + CSM.getLocForStartOfFile(FID).getLocWithOffset(Offset); + return FullSourceLoc(NewLoc, CSM); +} + +} // namespace + +#define ComputeDiagID(Severity, GroupName, DiagID) \ + do { \ + switch (Severity) { \ + case llvm::DS_Error: \ + DiagID = diag::err_fe_##GroupName; \ + break; \ + case llvm::DS_Warning: \ + DiagID = diag::warn_fe_##GroupName; \ + break; \ + case llvm::DS_Remark: \ + llvm_unreachable("'remark' severity not expected"); \ + break; \ + case llvm::DS_Note: \ + DiagID = diag::note_fe_##GroupName; \ + break; \ + } \ + } while (false) + +#define ComputeDiagRemarkID(Severity, GroupName, DiagID) \ + do { \ + switch (Severity) { \ + case llvm::DS_Error: \ + DiagID = diag::err_fe_##GroupName; \ + break; \ + case llvm::DS_Warning: \ + DiagID = diag::warn_fe_##GroupName; \ + break; \ + case llvm::DS_Remark: \ + DiagID = diag::remark_fe_##GroupName; \ + break; \ + case llvm::DS_Note: \ + DiagID = diag::note_fe_##GroupName; \ + break; \ + } \ + } while (false) + +std::unique_ptr<llvm::DiagnosticHandler> +BackendDiagnosticConsumer::createDiagnosticHandler() { + return std::make_unique<BackendDiagnosticHandlerImpl>(CodeGenOpts, this); +} + +void BackendDiagnosticConsumer::addFunctionSourceLocation(StringRef MangledName, + FullSourceLoc Loc) { + // TODO: use a fast content hash when available. + auto NameHash = llvm::hash_value(MangledName); + ManglingFullSourceLocs.push_back(std::make_pair(NameHash, Loc)); +} + +std::optional<FullSourceLoc> +BackendDiagnosticConsumer::getFunctionSourceLocation(const Function &F) const { + auto Hash = llvm::hash_value(F.getName()); + for (const auto &Pair : ManglingFullSourceLocs) { + if (Pair.first == Hash) + return Pair.second; + } + return std::nullopt; +} + +FullSourceLoc BackendDiagnosticConsumer::getBestLocationFromDebugLoc( ---------------- erichkeane wrote:
Typically non-ref returns don't get const because its a little silly (since it is just going to copy). BUT I'll put that in to match the previous version. https://github.com/llvm/llvm-project/pull/225966 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
