[clang] [CodeGen][CIR] Split out Backend Diags to utils, impl CIR error-attr (PR #225966)
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 29 13:57:43 PDT 2026
================
@@ -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
More information about the cfe-commits
mailing list