| //! LLVM diagnostic reports. | |
| use libc::c_uint; | |
| use rustc_span::InnerSpan; | |
| pub(crate) use self::Diagnostic::*; | |
| use self::OptimizationDiagnosticKind::*; | |
| use super::{DiagnosticInfo, SMDiagnostic}; | |
| use crate::llvm::Value; | |
| #[derive(Copy, Clone, Debug)] | |
| pub(crate) enum OptimizationDiagnosticKind { | |
| OptimizationRemark, | |
| OptimizationMissed, | |
| OptimizationAnalysis, | |
| OptimizationAnalysisFPCommute, | |
| OptimizationAnalysisAliasing, | |
| OptimizationFailure, | |
| OptimizationRemarkOther, | |
| } | |
| pub(crate) struct OptimizationDiagnostic<'ll> { | |
| pub kind: OptimizationDiagnosticKind, | |
| pub pass_name: String, | |
| #[expect(dead_code)] | |
| pub function: &'ll Value, | |
| pub line: c_uint, | |
| pub column: c_uint, | |
| pub filename: String, | |
| pub message: String, | |
| } | |
| impl<'ll> OptimizationDiagnostic<'ll> { | |
| unsafe fn unpack(kind: OptimizationDiagnosticKind, di: &'ll DiagnosticInfo) -> Self { | |
| let mut function = None; | |
| let mut line = 0; | |
| let mut column = 0; | |
| let mut message = None; | |
| let mut filename = None; | |
| let pass_name = super::build_string(|pass_name| { | |
| message = super::build_string(|message| { | |
| filename = super::build_string(|filename| unsafe { | |
| super::LLVMRustUnpackOptimizationDiagnostic( | |
| di, | |
| pass_name, | |
| &mut function, | |
| &mut line, | |
| &mut column, | |
| filename, | |
| message, | |
| ) | |
| }) | |
| .ok() | |
| }) | |
| .ok() | |
| }) | |
| .ok(); | |
| let mut filename = filename.unwrap_or_default(); | |
| if filename.is_empty() { | |
| filename.push_str("<unknown file>"); | |
| } | |
| OptimizationDiagnostic { | |
| kind, | |
| pass_name: pass_name.expect("got a non-UTF8 pass name from LLVM"), | |
| function: function.unwrap(), | |
| line, | |
| column, | |
| filename, | |
| message: message.expect("got a non-UTF8 OptimizationDiagnostic message from LLVM"), | |
| } | |
| } | |
| } | |
| pub(crate) struct SrcMgrDiagnostic { | |
| pub level: super::DiagnosticLevel, | |
| pub message: String, | |
| pub source: Option<(String, Vec<InnerSpan>)>, | |
| } | |
| impl SrcMgrDiagnostic { | |
| pub(crate) unsafe fn unpack(diag: &SMDiagnostic) -> SrcMgrDiagnostic { | |
| // Recover the post-substitution assembly code from LLVM for better | |
| // diagnostics. | |
| let mut have_source = false; | |
| let mut buffer = String::new(); | |
| let mut level = super::DiagnosticLevel::Error; | |
| let mut loc = 0; | |
| let mut ranges = [0; 8]; | |
| let mut num_ranges = ranges.len() / 2; | |
| let message = super::build_string(|message| { | |
| buffer = super::build_string(|buffer| unsafe { | |
| have_source = super::LLVMRustUnpackSMDiagnostic( | |
| diag, | |
| message, | |
| buffer, | |
| &mut level, | |
| &mut loc, | |
| ranges.as_mut_ptr(), | |
| &mut num_ranges, | |
| ); | |
| }) | |
| .expect("non-UTF8 inline asm"); | |
| }) | |
| .expect("non-UTF8 SMDiagnostic"); | |
| SrcMgrDiagnostic { | |
| message, | |
| level, | |
| source: have_source.then(|| { | |
| let mut spans = vec![InnerSpan::new(loc as usize, loc as usize)]; | |
| for i in 0..num_ranges { | |
| spans.push(InnerSpan::new(ranges[i * 2] as usize, ranges[i * 2 + 1] as usize)); | |
| } | |
| (buffer, spans) | |
| }), | |
| } | |
| } | |
| } | |
| #[derive(Clone)] | |
| pub(crate) struct InlineAsmDiagnostic { | |
| pub level: super::DiagnosticLevel, | |
| pub cookie: u64, | |
| pub message: String, | |
| pub source: Option<(String, Vec<InnerSpan>)>, | |
| } | |
| impl InlineAsmDiagnostic { | |
| unsafe fn unpackInlineAsm(di: &DiagnosticInfo) -> Self { | |
| let mut cookie = 0; | |
| let mut message = None; | |
| let mut level = super::DiagnosticLevel::Error; | |
| unsafe { | |
| super::LLVMRustUnpackInlineAsmDiagnostic(di, &mut level, &mut cookie, &mut message); | |
| } | |
| InlineAsmDiagnostic { | |
| level, | |
| cookie, | |
| message: super::twine_to_string(message.unwrap()), | |
| source: None, | |
| } | |
| } | |
| unsafe fn unpackSrcMgr(di: &DiagnosticInfo) -> Self { | |
| let mut cookie = 0; | |
| let smdiag = | |
| unsafe { SrcMgrDiagnostic::unpack(super::LLVMRustGetSMDiagnostic(di, &mut cookie)) }; | |
| InlineAsmDiagnostic { | |
| level: smdiag.level, | |
| cookie, | |
| message: smdiag.message, | |
| source: smdiag.source, | |
| } | |
| } | |
| } | |
| pub(crate) enum Diagnostic<'ll> { | |
| Optimization(OptimizationDiagnostic<'ll>), | |
| InlineAsm(InlineAsmDiagnostic), | |
| PGO(&'ll DiagnosticInfo), | |
| Linker(&'ll DiagnosticInfo), | |
| Unsupported(&'ll DiagnosticInfo), | |
| /// LLVM has other types that we do not wrap here. | |
| #[expect(dead_code)] | |
| UnknownDiagnostic(&'ll DiagnosticInfo), | |
| } | |
| impl<'ll> Diagnostic<'ll> { | |
| pub(crate) unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self { | |
| use super::DiagnosticKind as Dk; | |
| unsafe { | |
| let kind = super::LLVMRustGetDiagInfoKind(di); | |
| match kind { | |
| Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpackInlineAsm(di)), | |
| Dk::OptimizationRemark => { | |
| Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di)) | |
| } | |
| Dk::OptimizationRemarkOther => { | |
| Optimization(OptimizationDiagnostic::unpack(OptimizationRemarkOther, di)) | |
| } | |
| Dk::OptimizationRemarkMissed => { | |
| Optimization(OptimizationDiagnostic::unpack(OptimizationMissed, di)) | |
| } | |
| Dk::OptimizationRemarkAnalysis => { | |
| Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysis, di)) | |
| } | |
| Dk::OptimizationRemarkAnalysisFPCommute => { | |
| Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisFPCommute, di)) | |
| } | |
| Dk::OptimizationRemarkAnalysisAliasing => { | |
| Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisAliasing, di)) | |
| } | |
| Dk::OptimizationFailure => { | |
| Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di)) | |
| } | |
| Dk::PGOProfile => PGO(di), | |
| Dk::Linker => Linker(di), | |
| Dk::Unsupported => Unsupported(di), | |
| Dk::SrcMgr => InlineAsm(InlineAsmDiagnostic::unpackSrcMgr(di)), | |
| _ => UnknownDiagnostic(di), | |
| } | |
| } | |
| } | |
| } |