| //! LLVM diagnostic reports. |
| |
| pub use self::Diagnostic::*; |
| pub use self::OptimizationDiagnosticKind::*; |
| |
| use crate::value::Value; |
| use libc::c_uint; |
| |
| use super::{DiagnosticInfo, SMDiagnostic}; |
| use rustc_span::InnerSpan; |
| |
| #[derive(Copy, Clone)] |
| pub enum OptimizationDiagnosticKind { |
| OptimizationRemark, |
| OptimizationMissed, |
| OptimizationAnalysis, |
| OptimizationAnalysisFPCommute, |
| OptimizationAnalysisAliasing, |
| OptimizationFailure, |
| OptimizationRemarkOther, |
| } |
| |
| pub struct OptimizationDiagnostic<'ll> { |
| pub kind: OptimizationDiagnosticKind, |
| pub pass_name: String, |
| 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| { |
| 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 struct SrcMgrDiagnostic { |
| pub level: super::DiagnosticLevel, |
| pub message: String, |
| pub source: Option<(String, Vec<InnerSpan>)>, |
| } |
| |
| impl SrcMgrDiagnostic { |
| pub 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| { |
| 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 struct InlineAsmDiagnostic { |
| pub level: super::DiagnosticLevel, |
| pub cookie: c_uint, |
| 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; |
| |
| 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 = SrcMgrDiagnostic::unpack(super::LLVMRustGetSMDiagnostic(di, &mut cookie)); |
| InlineAsmDiagnostic { |
| level: smdiag.level, |
| cookie, |
| message: smdiag.message, |
| source: smdiag.source, |
| } |
| } |
| } |
| |
| pub 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. |
| UnknownDiagnostic(&'ll DiagnosticInfo), |
| } |
| |
| impl<'ll> Diagnostic<'ll> { |
| pub unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self { |
| use super::DiagnosticKind as Dk; |
| 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), |
| } |
| } |
| } |