about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs')
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs166
1 files changed, 166 insertions, 0 deletions
diff --git a/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
new file mode 100644
index 00000000000..47f5c94e70c
--- /dev/null
+++ b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
@@ -0,0 +1,166 @@
+//! LLVM diagnostic reports.
+
+pub use self::Diagnostic::*;
+pub use self::OptimizationDiagnosticKind::*;
+
+use crate::value::Value;
+use libc::c_uint;
+
+use super::{DiagnosticInfo, Twine};
+
+#[derive(Copy, Clone)]
+pub enum OptimizationDiagnosticKind {
+    OptimizationRemark,
+    OptimizationMissed,
+    OptimizationAnalysis,
+    OptimizationAnalysisFPCommute,
+    OptimizationAnalysisAliasing,
+    OptimizationFailure,
+    OptimizationRemarkOther,
+}
+
+impl OptimizationDiagnosticKind {
+    pub fn describe(self) -> &'static str {
+        match self {
+            OptimizationRemark | OptimizationRemarkOther => "remark",
+            OptimizationMissed => "missed",
+            OptimizationAnalysis => "analysis",
+            OptimizationAnalysisFPCommute => "floating-point",
+            OptimizationAnalysisAliasing => "aliasing",
+            OptimizationFailure => "failure",
+        }
+    }
+}
+
+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 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"),
+        }
+    }
+}
+
+#[derive(Copy, Clone)]
+pub struct InlineAsmDiagnostic<'ll> {
+    pub level: super::DiagnosticLevel,
+    pub cookie: c_uint,
+    pub message: &'ll Twine,
+    pub instruction: Option<&'ll Value>,
+}
+
+impl InlineAsmDiagnostic<'ll> {
+    unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self {
+        let mut cookie = 0;
+        let mut message = None;
+        let mut instruction = None;
+        let mut level = super::DiagnosticLevel::Error;
+
+        super::LLVMRustUnpackInlineAsmDiagnostic(
+            di,
+            &mut level,
+            &mut cookie,
+            &mut message,
+            &mut instruction,
+        );
+
+        InlineAsmDiagnostic { level, cookie, message: message.unwrap(), instruction }
+    }
+}
+
+pub enum Diagnostic<'ll> {
+    Optimization(OptimizationDiagnostic<'ll>),
+    InlineAsm(InlineAsmDiagnostic<'ll>),
+    PGO(&'ll DiagnosticInfo),
+    Linker(&'ll DiagnosticInfo),
+
+    /// LLVM has other types that we do not wrap here.
+    UnknownDiagnostic(&'ll DiagnosticInfo),
+}
+
+impl 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::unpack(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),
+
+            _ => UnknownDiagnostic(di),
+        }
+    }
+}