about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2021-07-28 21:31:47 +0200
committerNikita Popov <nikita.ppv@gmail.com>2021-08-16 18:28:17 +0200
commit621f5146c331ada06c6ff581edd0dbc23ffbb763 (patch)
treefa4e263cfa1d8ef483416f249e1fd3efa59f88a2 /compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
parent2967036f57675dbf3e00713d9d9d27956db068e4 (diff)
downloadrust-621f5146c331ada06c6ff581edd0dbc23ffbb763.tar.gz
rust-621f5146c331ada06c6ff581edd0dbc23ffbb763.zip
Handle SrcMgr diagnostics
This is how InlineAsm diagnostics with source information are
reported now. Previously a separate InlineAsm diagnostic handler
was used.
Diffstat (limited to 'compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs')
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs94
1 files changed, 76 insertions, 18 deletions
diff --git a/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
index ccd3e42e458..36aa022d746 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
@@ -6,7 +6,8 @@ pub use self::OptimizationDiagnosticKind::*;
 use crate::value::Value;
 use libc::c_uint;
 
-use super::{DiagnosticInfo, Twine};
+use super::{DiagnosticInfo, SMDiagnostic};
+use rustc_span::InnerSpan;
 
 #[derive(Copy, Clone)]
 pub enum OptimizationDiagnosticKind {
@@ -86,36 +87,91 @@ impl OptimizationDiagnostic<'ll> {
     }
 }
 
-#[derive(Copy, Clone)]
-pub struct InlineAsmDiagnostic<'ll> {
+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: &'ll Twine,
-    pub instruction: Option<&'ll Value>,
+    pub message: String,
+    pub source: Option<(String, Vec<InnerSpan>)>,
 }
 
-impl InlineAsmDiagnostic<'ll> {
-    unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self {
+impl InlineAsmDiagnostic {
+    unsafe fn unpackInlineAsm(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,
-        );
+        super::LLVMRustUnpackInlineAsmDiagnostic(di, &mut level, &mut cookie, &mut message);
 
-        InlineAsmDiagnostic { level, cookie, message: message.unwrap(), instruction }
+        InlineAsmDiagnostic {
+            level,
+            cookie,
+            message: super::twine_to_string(message.unwrap()),
+            source: None,
+        }
+    }
+
+    unsafe fn unpackSrcMgr(di: &'ll 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<'ll>),
+    InlineAsm(InlineAsmDiagnostic),
     PGO(&'ll DiagnosticInfo),
     Linker(&'ll DiagnosticInfo),
     Unsupported(&'ll DiagnosticInfo),
@@ -130,7 +186,7 @@ impl Diagnostic<'ll> {
         let kind = super::LLVMRustGetDiagInfoKind(di);
 
         match kind {
-            Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpack(di)),
+            Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpackInlineAsm(di)),
 
             Dk::OptimizationRemark => {
                 Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di))
@@ -162,6 +218,8 @@ impl Diagnostic<'ll> {
             Dk::Linker => Linker(di),
             Dk::Unsupported => Unsupported(di),
 
+            Dk::SrcMgr => InlineAsm(InlineAsmDiagnostic::unpackSrcMgr(di)),
+
             _ => UnknownDiagnostic(di),
         }
     }