1//===--- BackendDiagnosticHandler.cpp - Shared Backend Diagnostics ------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "clang/CodeGenUtils/BackendDiagnosticHandler.h"
10#include "clang/Basic/CodeGenOptions.h"
11#include "clang/Basic/Diagnostic.h"
12#include "clang/Basic/DiagnosticFrontend.h"
13#include "clang/Basic/FileManager.h"
14#include "clang/Basic/SourceManager.h"
15#include "llvm/ADT/Hashing.h"
16#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
17#include "llvm/Demangle/Demangle.h"
18#include "llvm/IR/DiagnosticInfo.h"
19#include "llvm/IR/DiagnosticPrinter.h"
20#include "llvm/IR/Function.h"
21#include "llvm/IR/Module.h"
22#include "llvm/Support/raw_ostream.h"
23
24using namespace clang;
25using namespace llvm;
26
27namespace {
28/// Forwards llvm::DiagnosticHandler callbacks into a BackendDiagnosticConsumer.
29class BackendDiagnosticHandlerImpl final : public DiagnosticHandler {
30public:
31 BackendDiagnosticHandlerImpl(const CodeGenOptions &CGOpts,
32 BackendDiagnosticConsumer *Consumer)
33 : CodeGenOpts(CGOpts), Consumer(Consumer) {}
34
35 bool handleDiagnostics(const DiagnosticInfo &DI) override {
36 Consumer->handleDiagnostics(DI);
37 return true;
38 }
39
40 bool isAnalysisRemarkEnabled(StringRef PassName) const override {
41 return CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(String: PassName);
42 }
43 bool isMissedOptRemarkEnabled(StringRef PassName) const override {
44 return CodeGenOpts.OptimizationRemarkMissed.patternMatches(String: PassName);
45 }
46 bool isPassedOptRemarkEnabled(StringRef PassName) const override {
47 return CodeGenOpts.OptimizationRemark.patternMatches(String: PassName);
48 }
49
50 bool isAnyRemarkEnabled() const override {
51 return CodeGenOpts.OptimizationRemarkAnalysis.hasValidPattern() ||
52 CodeGenOpts.OptimizationRemarkMissed.hasValidPattern() ||
53 CodeGenOpts.OptimizationRemark.hasValidPattern();
54 }
55
56private:
57 const CodeGenOptions &CodeGenOpts;
58 BackendDiagnosticConsumer *Consumer;
59};
60
61/// Convert a location in a temporary llvm::SourceMgr buffer to be a valid
62/// FullSourceLoc.
63FullSourceLoc ConvertBackendLocation(const llvm::SMDiagnostic &D,
64 SourceManager &CSM) {
65 // Get both the clang and llvm source managers. The location is relative to
66 // a memory buffer that the LLVM Source Manager is handling, we need to add
67 // a copy to the Clang source manager.
68 const llvm::SourceMgr &LSM = *D.getSourceMgr();
69
70 // We need to copy the underlying LLVM memory buffer because llvm::SourceMgr
71 // already owns its one and clang::SourceManager wants to own its one.
72 const MemoryBuffer *LBuf =
73 LSM.getMemoryBuffer(i: LSM.FindBufferContainingLoc(Loc: D.getLoc()));
74
75 // Create the copy and transfer ownership to clang::SourceManager.
76 // TODO: Avoid copying files into memory.
77 std::unique_ptr<llvm::MemoryBuffer> CBuf =
78 llvm::MemoryBuffer::getMemBufferCopy(InputData: LBuf->getBuffer(),
79 BufferName: LBuf->getBufferIdentifier());
80 // FIXME: Keep a file ID map instead of creating new IDs for each location.
81 FileID FID = CSM.createFileID(Buffer: std::move(CBuf));
82
83 // Translate the offset into the file.
84 unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart();
85 SourceLocation NewLoc =
86 CSM.getLocForStartOfFile(FID).getLocWithOffset(Offset);
87 return FullSourceLoc(NewLoc, CSM);
88}
89
90} // namespace
91
92#define ComputeDiagID(Severity, GroupName, DiagID) \
93 do { \
94 switch (Severity) { \
95 case llvm::DS_Error: \
96 DiagID = diag::err_fe_##GroupName; \
97 break; \
98 case llvm::DS_Warning: \
99 DiagID = diag::warn_fe_##GroupName; \
100 break; \
101 case llvm::DS_Remark: \
102 llvm_unreachable("'remark' severity not expected"); \
103 break; \
104 case llvm::DS_Note: \
105 DiagID = diag::note_fe_##GroupName; \
106 break; \
107 } \
108 } while (false)
109
110#define ComputeDiagRemarkID(Severity, GroupName, DiagID) \
111 do { \
112 switch (Severity) { \
113 case llvm::DS_Error: \
114 DiagID = diag::err_fe_##GroupName; \
115 break; \
116 case llvm::DS_Warning: \
117 DiagID = diag::warn_fe_##GroupName; \
118 break; \
119 case llvm::DS_Remark: \
120 DiagID = diag::remark_fe_##GroupName; \
121 break; \
122 case llvm::DS_Note: \
123 DiagID = diag::note_fe_##GroupName; \
124 break; \
125 } \
126 } while (false)
127
128std::unique_ptr<llvm::DiagnosticHandler>
129BackendDiagnosticConsumer::createDiagnosticHandler() {
130 return std::make_unique<BackendDiagnosticHandlerImpl>(args: CodeGenOpts, args: this);
131}
132
133void BackendDiagnosticConsumer::addFunctionSourceLocation(StringRef MangledName,
134 FullSourceLoc Loc) {
135 // TODO: use a fast content hash when available.
136 auto NameHash = llvm::hash_value(S: MangledName);
137 ManglingFullSourceLocs.push_back(x: std::make_pair(x&: NameHash, y&: Loc));
138}
139
140std::optional<FullSourceLoc>
141BackendDiagnosticConsumer::getFunctionSourceLocation(const Function &F) const {
142 auto Hash = llvm::hash_value(S: F.getName());
143 for (const auto &Pair : ManglingFullSourceLocs) {
144 if (Pair.first == Hash)
145 return Pair.second;
146 }
147 return std::nullopt;
148}
149
150const FullSourceLoc BackendDiagnosticConsumer::getBestLocationFromDebugLoc(
151 const llvm::DiagnosticInfoWithLocationBase &D, bool &BadDebugInfo,
152 StringRef &Filename, unsigned &Line, unsigned &Column) const {
153 SourceManager &SourceMgr = *SM;
154 FileManager &FileMgr = SourceMgr.getFileManager();
155 SourceLocation DILoc;
156
157 if (D.isLocationAvailable()) {
158 D.getLocation(RelativePath&: Filename, Line, Column);
159 if (Line > 0) {
160 auto FE = FileMgr.getOptionalFileRef(Filename);
161 if (!FE)
162 FE = FileMgr.getOptionalFileRef(Filename: D.getAbsolutePath());
163 if (FE) {
164 // If -gcolumn-info was not used, Column will be 0. This upsets the
165 // source manager, so pass 1 if Column is not set.
166 DILoc = SourceMgr.translateFileLineCol(SourceFile: *FE, Line, Col: Column ? Column : 1);
167 }
168 }
169 BadDebugInfo = DILoc.isInvalid();
170 }
171
172 // If a location isn't available, try to approximate it using the associated
173 // function definition. We use the definition's right brace to differentiate
174 // from diagnostics that genuinely relate to the function itself.
175 FullSourceLoc Loc(DILoc, SourceMgr);
176 if (Loc.isInvalid()) {
177 if (auto MaybeLoc = getFunctionSourceLocation(F: D.getFunction()))
178 Loc = *MaybeLoc;
179 }
180
181 if (DILoc.isInvalid() && D.isLocationAvailable())
182 // If we were not able to translate the file:line:col information
183 // back to a SourceLocation, at least emit a note stating that
184 // we could not translate this location. This can happen in the
185 // case of #line directives.
186 Diags.Report(Loc, DiagID: diag::note_fe_backend_invalid_loc)
187 << Filename << Line << Column;
188
189 return Loc;
190}
191
192void BackendDiagnosticConsumer::SrcMgrDiagHandler(
193 const llvm::DiagnosticInfoSrcMgr &DI) {
194 const llvm::SMDiagnostic &D = DI.getSMDiag();
195
196 unsigned DiagID;
197 if (DI.isInlineAsmDiag())
198 ComputeDiagID(DI.getSeverity(), inline_asm, DiagID);
199 else
200 ComputeDiagID(DI.getSeverity(), source_mgr, DiagID);
201
202 // This is for the empty consumer that uses the clang diagnostic
203 // handler for IR input files.
204 if (!SM) {
205 D.print(ProgName: nullptr, S&: llvm::errs());
206 Diags.Report(DiagID).AddString(V: "cannot compile inline asm");
207 return;
208 }
209
210 // There are a couple of different kinds of errors we could get here.
211 // First, we re-format the SMDiagnostic in terms of a clang diagnostic.
212
213 // Strip "error: " off the start of the message string.
214 StringRef Message = D.getMessage();
215 (void)Message.consume_front(Prefix: "error: ");
216
217 // If the SMDiagnostic has an inline asm source location, translate it.
218 FullSourceLoc Loc;
219 if (D.getLoc() != SMLoc())
220 Loc = ConvertBackendLocation(D, CSM&: *SM);
221
222 // If this problem has clang-level source location information, report the
223 // issue in the source with a note showing the instantiated
224 // code.
225 if (DI.isInlineAsmDiag()) {
226 SourceLocation LocCookie =
227 SourceLocation::getFromRawEncoding(Encoding: DI.getLocCookie());
228 if (LocCookie.isValid()) {
229 Diags.Report(Loc: LocCookie, DiagID).AddString(V: Message);
230
231 if (D.getLoc().isValid()) {
232 DiagnosticBuilder B = Diags.Report(Loc, DiagID: diag::note_fe_inline_asm_here);
233 // Convert the SMDiagnostic ranges into SourceRange and attach them
234 // to the diagnostic.
235 for (const std::pair<unsigned, unsigned> &Range : D.getRanges()) {
236 unsigned Column = D.getColumnNo();
237 B << SourceRange(Loc.getLocWithOffset(Offset: Range.first - Column),
238 Loc.getLocWithOffset(Offset: Range.second - Column));
239 }
240 }
241 return;
242 }
243 }
244
245 // Otherwise, report the backend issue as occurring in the generated .s file.
246 // If Loc is invalid, we still need to report the issue, it just gets no
247 // location info.
248 Diags.Report(Loc, DiagID).AddString(V: Message);
249}
250
251bool BackendDiagnosticConsumer::InlineAsmDiagHandler(
252 const llvm::DiagnosticInfoInlineAsm &D) {
253 unsigned DiagID;
254 ComputeDiagID(D.getSeverity(), inline_asm, DiagID);
255 std::string Message = D.getMsgStr().str();
256
257 // If this problem has clang-level source location information, report the
258 // issue as being a problem in the source with a note showing the instantiated
259 // code.
260 SourceLocation LocCookie =
261 SourceLocation::getFromRawEncoding(Encoding: D.getLocCookie());
262 if (LocCookie.isValid())
263 Diags.Report(Loc: LocCookie, DiagID).AddString(V: Message);
264 else {
265 // Otherwise, report the backend diagnostic as occurring in the generated
266 // .s file.
267 // If Loc is invalid, we still need to report the diagnostic, it just gets
268 // no location info.
269 FullSourceLoc Loc;
270 Diags.Report(Loc, DiagID).AddString(V: Message);
271 }
272 // We handled all the possible severities.
273 return true;
274}
275
276bool BackendDiagnosticConsumer::StackSizeDiagHandler(
277 const llvm::DiagnosticInfoStackSize &D) {
278 if (D.getSeverity() != llvm::DS_Warning)
279 // For now, the only support we have for StackSize diagnostic is warning.
280 // We do not know how to format other severities.
281 return false;
282
283 auto Loc = getFunctionSourceLocation(F: D.getFunction());
284 if (!Loc)
285 return false;
286
287 Diags.Report(Loc: *Loc, DiagID: diag::warn_fe_frame_larger_than)
288 << D.getStackSize() << D.getStackLimit()
289 << llvm::demangle(MangledName: D.getFunction().getName());
290 return true;
291}
292
293bool BackendDiagnosticConsumer::ResourceLimitDiagHandler(
294 const llvm::DiagnosticInfoResourceLimit &D) {
295 auto Loc = getFunctionSourceLocation(F: D.getFunction());
296 if (!Loc)
297 return false;
298 unsigned DiagID = diag::err_fe_backend_resource_limit;
299 ComputeDiagID(D.getSeverity(), backend_resource_limit, DiagID);
300
301 Diags.Report(Loc: *Loc, DiagID)
302 << D.getResourceName() << D.getResourceSize() << D.getResourceLimit()
303 << llvm::demangle(MangledName: D.getFunction().getName());
304 return true;
305}
306
307void BackendDiagnosticConsumer::UnsupportedDiagHandler(
308 const llvm::DiagnosticInfoUnsupported &D) {
309 // We only support warnings or errors.
310 assert(D.getSeverity() == llvm::DS_Error ||
311 D.getSeverity() == llvm::DS_Warning);
312
313 StringRef Filename;
314 unsigned Line, Column;
315 bool BadDebugInfo = false;
316 FullSourceLoc Loc;
317 std::string Msg;
318 raw_string_ostream MsgStream(Msg);
319
320 // SM will be null for IR input files, we will construct the diag
321 // message from llvm::DiagnosticInfoUnsupported.
322 if (SM != nullptr) {
323 Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column);
324 MsgStream << D.getMessage();
325 } else {
326 DiagnosticPrinterRawOStream DP(MsgStream);
327 D.print(DP);
328 }
329
330 auto DiagType = D.getSeverity() == llvm::DS_Error
331 ? diag::err_fe_backend_unsupported
332 : diag::warn_fe_backend_unsupported;
333 Diags.Report(Loc, DiagID: DiagType) << Msg;
334
335 if (BadDebugInfo)
336 // If we were not able to translate the file:line:col information
337 // back to a SourceLocation, at least emit a note stating that
338 // we could not translate this location. This can happen in the
339 // case of #line directives.
340 Diags.Report(Loc, DiagID: diag::note_fe_backend_invalid_loc)
341 << Filename << Line << Column;
342}
343
344void BackendDiagnosticConsumer::UnsupportedTargetIntrinsicDiagHandler(
345 const llvm::DiagnosticInfoUnsupportedTargetIntrinsic &D) {
346 assert(D.getSeverity() == llvm::DS_Error &&
347 "unsupported target intrinsic diagnostic should be an error");
348
349 StringRef Filename;
350 unsigned Line, Column;
351 bool BadDebugInfo = false;
352 FullSourceLoc Loc;
353 std::string Msg;
354 raw_string_ostream MsgStream(Msg);
355
356 // SM will be null for IR input files, so construct the diagnostic
357 // message from llvm::DiagnosticInfoUnsupportedTargetIntrinsic.
358 if (SM != nullptr) {
359 Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column);
360 MsgStream << D.getMessage();
361 } else {
362 DiagnosticPrinterRawOStream DP(MsgStream);
363 D.print(DP);
364 }
365
366 Diags.Report(Loc, DiagID: diag::err_fe_backend_unsupported) << Msg;
367
368 if (BadDebugInfo) {
369 // If we were not able to translate the file:line:col information
370 // back to a SourceLocation, at least emit a note stating that
371 // we could not translate this location. This can happen in the
372 // case of #line directives.
373 Diags.Report(Loc, DiagID: diag::note_fe_backend_invalid_loc)
374 << Filename << Line << Column;
375 }
376}
377
378void BackendDiagnosticConsumer::EmitOptimizationMessage(
379 const llvm::DiagnosticInfoOptimizationBase &D, unsigned DiagID) {
380 // We only support warnings and remarks.
381 assert(D.getSeverity() == llvm::DS_Remark ||
382 D.getSeverity() == llvm::DS_Warning);
383
384 StringRef Filename;
385 unsigned Line, Column;
386 bool BadDebugInfo = false;
387 FullSourceLoc Loc;
388 std::string Msg;
389 raw_string_ostream MsgStream(Msg);
390
391 // SM will be null for IR input files, we will construct the remark
392 // message from llvm::DiagnosticInfoOptimizationBase.
393 if (SM != nullptr) {
394 Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column);
395 MsgStream << D.getMsg();
396 } else {
397 DiagnosticPrinterRawOStream DP(MsgStream);
398 D.print(DP);
399 }
400
401 if (D.getHotness())
402 MsgStream << " (hotness: " << *D.getHotness() << ")";
403
404 Diags.Report(Loc, DiagID) << AddFlagValue(D.getPassName()) << Msg;
405
406 if (BadDebugInfo)
407 // If we were not able to translate the file:line:col information
408 // back to a SourceLocation, at least emit a note stating that
409 // we could not translate this location. This can happen in the
410 // case of #line directives.
411 Diags.Report(Loc, DiagID: diag::note_fe_backend_invalid_loc)
412 << Filename << Line << Column;
413}
414
415void BackendDiagnosticConsumer::OptimizationRemarkHandler(
416 const llvm::DiagnosticInfoOptimizationBase &D) {
417 // Without hotness information, don't show noisy remarks.
418 if (D.isVerbose() && !D.getHotness())
419 return;
420
421 if (D.isPassed()) {
422 // Optimization remarks are active only if the -Rpass flag has a regular
423 // expression that matches the name of the pass name in \p D.
424 if (CodeGenOpts.OptimizationRemark.patternMatches(String: D.getPassName()))
425 EmitOptimizationMessage(D, DiagID: diag::remark_fe_backend_optimization_remark);
426 } else if (D.isMissed()) {
427 // Missed optimization remarks are active only if the -Rpass-missed
428 // flag has a regular expression that matches the name of the pass
429 // name in \p D.
430 if (CodeGenOpts.OptimizationRemarkMissed.patternMatches(String: D.getPassName()))
431 EmitOptimizationMessage(
432 D, DiagID: diag::remark_fe_backend_optimization_remark_missed);
433 } else {
434 assert(D.isAnalysis() && "Unknown remark type");
435
436 bool ShouldAlwaysPrint = false;
437 if (auto *ORA = dyn_cast<llvm::OptimizationRemarkAnalysis>(Val: &D))
438 ShouldAlwaysPrint = ORA->shouldAlwaysPrint();
439
440 if (ShouldAlwaysPrint ||
441 CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(String: D.getPassName()))
442 EmitOptimizationMessage(
443 D, DiagID: diag::remark_fe_backend_optimization_remark_analysis);
444 }
445}
446
447void BackendDiagnosticConsumer::OptimizationRemarkHandler(
448 const llvm::OptimizationRemarkAnalysisFPCommute &D) {
449 // Optimization analysis remarks are active if the pass name is set to
450 // llvm::DiagnosticInfo::AlwaysPrint or if the -Rpass-analysis flag has a
451 // regular expression that matches the name of the pass name in \p D.
452
453 if (D.shouldAlwaysPrint() ||
454 CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(String: D.getPassName()))
455 EmitOptimizationMessage(
456 D, DiagID: diag::remark_fe_backend_optimization_remark_analysis_fpcommute);
457}
458
459void BackendDiagnosticConsumer::OptimizationRemarkHandler(
460 const llvm::OptimizationRemarkAnalysisAliasing &D) {
461 // Optimization analysis remarks are active if the pass name is set to
462 // llvm::DiagnosticInfo::AlwaysPrint or if the -Rpass-analysis flag has a
463 // regular expression that matches the name of the pass name in \p D.
464
465 if (D.shouldAlwaysPrint() ||
466 CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(String: D.getPassName()))
467 EmitOptimizationMessage(
468 D, DiagID: diag::remark_fe_backend_optimization_remark_analysis_aliasing);
469}
470
471void BackendDiagnosticConsumer::OptimizationFailureHandler(
472 const llvm::DiagnosticInfoOptimizationFailure &D) {
473 EmitOptimizationMessage(D, DiagID: diag::warn_fe_backend_optimization_failure);
474}
475
476void BackendDiagnosticConsumer::DontCallDiagHandler(
477 const DiagnosticInfoDontCall &D) {
478 SourceLocation LocCookie =
479 SourceLocation::getFromRawEncoding(Encoding: D.getLocCookie());
480
481 // FIXME: we can't yet diagnose indirect calls. When/if we can, we
482 // should instead assert that LocCookie.isValid().
483 if (!LocCookie.isValid())
484 return;
485
486 Diags.Report(Loc: LocCookie, DiagID: D.getSeverity() == DiagnosticSeverity::DS_Error
487 ? diag::err_fe_backend_error_attr
488 : diag::warn_fe_backend_warning_attr)
489 << llvm::demangle(MangledName: D.getFunctionName()) << D.getNote();
490
491 if (!CodeGenOpts.ShowInliningChain)
492 return;
493
494 auto EmitNote = [&](SourceLocation Loc, StringRef FuncName, bool IsFirst) {
495 if (!Loc.isValid())
496 Loc = LocCookie;
497 unsigned DiagID =
498 IsFirst ? diag::note_fe_backend_in : diag::note_fe_backend_inlined;
499 Diags.Report(Loc, DiagID) << llvm::demangle(MangledName: FuncName.str());
500 };
501
502 // Try debug info first for accurate source locations.
503 if (!D.getDebugInlineChain().empty()) {
504 SourceManager &SrcMgr = *SM;
505 FileManager &FM = SrcMgr.getFileManager();
506 for (const auto &[I, Info] : llvm::enumerate(First: D.getDebugInlineChain())) {
507 SourceLocation Loc;
508 if (Info.Line > 0)
509 if (auto FE = FM.getOptionalFileRef(Filename: Info.Filename))
510 Loc = SrcMgr.translateFileLineCol(SourceFile: *FE, Line: Info.Line,
511 Col: Info.Column ? Info.Column : 1);
512 EmitNote(Loc, Info.FuncName, I == 0);
513 }
514 return;
515 }
516
517 // Fall back to heuristic (srcloc metadata) when debug info is unavailable.
518 auto InliningDecisions = D.getInliningDecisions();
519 if (InliningDecisions.empty())
520 return;
521
522 for (const auto &[I, Entry] : llvm::enumerate(First&: InliningDecisions)) {
523 SourceLocation Loc =
524 I == 0 ? LocCookie : SourceLocation::getFromRawEncoding(Encoding: Entry.second);
525 EmitNote(Loc, Entry.first, I == 0);
526 }
527
528 // Suggest enabling debug info (at least -gline-directives-only) for more
529 // accurate locations.
530 Diags.Report(Loc: LocCookie, DiagID: diag::note_fe_backend_inlining_debug_info);
531}
532
533void BackendDiagnosticConsumer::MisExpectDiagHandler(
534 const llvm::DiagnosticInfoMisExpect &D) {
535 StringRef Filename;
536 unsigned Line, Column;
537 bool BadDebugInfo = false;
538 FullSourceLoc Loc =
539 getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column);
540
541 Diags.Report(Loc, DiagID: diag::warn_profile_data_misexpect) << D.getMsg().str();
542
543 if (BadDebugInfo)
544 // If we were not able to translate the file:line:col information
545 // back to a SourceLocation, at least emit a note stating that
546 // we could not translate this location. This can happen in the
547 // case of #line directives.
548 Diags.Report(Loc, DiagID: diag::note_fe_backend_invalid_loc)
549 << Filename << Line << Column;
550}
551
552void BackendDiagnosticConsumer::handleDiagnostics(const DiagnosticInfo &DI) {
553 unsigned DiagID = diag::err_fe_inline_asm;
554 llvm::DiagnosticSeverity Severity = DI.getSeverity();
555 // Get the diagnostic ID based.
556 switch (DI.getKind()) {
557 case llvm::DK_InlineAsm:
558 if (InlineAsmDiagHandler(D: cast<DiagnosticInfoInlineAsm>(Val: DI)))
559 return;
560 ComputeDiagID(Severity, inline_asm, DiagID);
561 break;
562 case llvm::DK_SrcMgr:
563 SrcMgrDiagHandler(DI: cast<DiagnosticInfoSrcMgr>(Val: DI));
564 return;
565 case llvm::DK_StackSize:
566 if (StackSizeDiagHandler(D: cast<DiagnosticInfoStackSize>(Val: DI)))
567 return;
568 ComputeDiagID(Severity, backend_frame_larger_than, DiagID);
569 break;
570 case llvm::DK_ResourceLimit:
571 if (ResourceLimitDiagHandler(D: cast<DiagnosticInfoResourceLimit>(Val: DI)))
572 return;
573 ComputeDiagID(Severity, backend_resource_limit, DiagID);
574 break;
575 case DK_Linker:
576 ComputeDiagID(Severity, linking_module, DiagID);
577 break;
578 case llvm::DK_OptimizationRemark:
579 // Optimization remarks are always handled completely by this
580 // handler. There is no generic way of emitting them.
581 OptimizationRemarkHandler(D: cast<OptimizationRemark>(Val: DI));
582 return;
583 case llvm::DK_OptimizationRemarkMissed:
584 // Optimization remarks are always handled completely by this
585 // handler. There is no generic way of emitting them.
586 OptimizationRemarkHandler(D: cast<OptimizationRemarkMissed>(Val: DI));
587 return;
588 case llvm::DK_OptimizationRemarkAnalysis:
589 // Optimization remarks are always handled completely by this
590 // handler. There is no generic way of emitting them.
591 OptimizationRemarkHandler(D: cast<OptimizationRemarkAnalysis>(Val: DI));
592 return;
593 case llvm::DK_OptimizationRemarkAnalysisFPCommute:
594 // Optimization remarks are always handled completely by this
595 // handler. There is no generic way of emitting them.
596 OptimizationRemarkHandler(D: cast<OptimizationRemarkAnalysisFPCommute>(Val: DI));
597 return;
598 case llvm::DK_OptimizationRemarkAnalysisAliasing:
599 // Optimization remarks are always handled completely by this
600 // handler. There is no generic way of emitting them.
601 OptimizationRemarkHandler(D: cast<OptimizationRemarkAnalysisAliasing>(Val: DI));
602 return;
603 case llvm::DK_MachineOptimizationRemark:
604 // Optimization remarks are always handled completely by this
605 // handler. There is no generic way of emitting them.
606 OptimizationRemarkHandler(D: cast<MachineOptimizationRemark>(Val: DI));
607 return;
608 case llvm::DK_MachineOptimizationRemarkMissed:
609 // Optimization remarks are always handled completely by this
610 // handler. There is no generic way of emitting them.
611 OptimizationRemarkHandler(D: cast<MachineOptimizationRemarkMissed>(Val: DI));
612 return;
613 case llvm::DK_MachineOptimizationRemarkAnalysis:
614 // Optimization remarks are always handled completely by this
615 // handler. There is no generic way of emitting them.
616 OptimizationRemarkHandler(D: cast<MachineOptimizationRemarkAnalysis>(Val: DI));
617 return;
618 case llvm::DK_OptimizationFailure:
619 // Optimization failures are always handled completely by this
620 // handler.
621 OptimizationFailureHandler(D: cast<DiagnosticInfoOptimizationFailure>(Val: DI));
622 return;
623 case llvm::DK_Unsupported:
624 UnsupportedDiagHandler(D: cast<DiagnosticInfoUnsupported>(Val: DI));
625 return;
626 case llvm::DK_UnsupportedTargetIntrinsic:
627 UnsupportedTargetIntrinsicDiagHandler(
628 D: cast<DiagnosticInfoUnsupportedTargetIntrinsic>(Val: DI));
629 return;
630 case llvm::DK_DontCall:
631 DontCallDiagHandler(D: cast<DiagnosticInfoDontCall>(Val: DI));
632 return;
633 case llvm::DK_MisExpect:
634 MisExpectDiagHandler(D: cast<DiagnosticInfoMisExpect>(Val: DI));
635 return;
636 default:
637 // Plugin IDs are not bound to any value as they are set dynamically.
638 ComputeDiagRemarkID(Severity, backend_plugin, DiagID);
639 break;
640 }
641 std::string MsgStorage;
642 {
643 raw_string_ostream Stream(MsgStorage);
644 DiagnosticPrinterRawOStream DP(Stream);
645 DI.print(DP);
646 }
647
648 if (DI.getKind() == DK_Linker) {
649 assert(CurLinkModule && "CurLinkModule must be set for linker diagnostics");
650 Diags.Report(DiagID) << CurLinkModule->getModuleIdentifier() << MsgStorage;
651 return;
652 }
653
654 // Report the backend message using the usual diagnostic mechanism.
655 FullSourceLoc Loc;
656 Diags.Report(Loc, DiagID).AddString(V: MsgStorage);
657}
658
659#undef ComputeDiagID
660#undef ComputeDiagRemarkID
661