]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
Rollup merge of #99079 - compiler-errors:issue-99073, r=oli-obk
[rust.git] / compiler / rustc_codegen_llvm / src / llvm / diagnostic.rs
1 //! LLVM diagnostic reports.
2
3 pub use self::Diagnostic::*;
4 pub use self::OptimizationDiagnosticKind::*;
5
6 use crate::value::Value;
7 use libc::c_uint;
8
9 use super::{DiagnosticInfo, SMDiagnostic};
10 use rustc_span::InnerSpan;
11
12 #[derive(Copy, Clone)]
13 pub enum OptimizationDiagnosticKind {
14     OptimizationRemark,
15     OptimizationMissed,
16     OptimizationAnalysis,
17     OptimizationAnalysisFPCommute,
18     OptimizationAnalysisAliasing,
19     OptimizationFailure,
20     OptimizationRemarkOther,
21 }
22
23 pub struct OptimizationDiagnostic<'ll> {
24     pub kind: OptimizationDiagnosticKind,
25     pub pass_name: String,
26     pub function: &'ll Value,
27     pub line: c_uint,
28     pub column: c_uint,
29     pub filename: String,
30     pub message: String,
31 }
32
33 impl<'ll> OptimizationDiagnostic<'ll> {
34     unsafe fn unpack(kind: OptimizationDiagnosticKind, di: &'ll DiagnosticInfo) -> Self {
35         let mut function = None;
36         let mut line = 0;
37         let mut column = 0;
38
39         let mut message = None;
40         let mut filename = None;
41         let pass_name = super::build_string(|pass_name| {
42             message = super::build_string(|message| {
43                 filename = super::build_string(|filename| {
44                     super::LLVMRustUnpackOptimizationDiagnostic(
45                         di,
46                         pass_name,
47                         &mut function,
48                         &mut line,
49                         &mut column,
50                         filename,
51                         message,
52                     )
53                 })
54                 .ok()
55             })
56             .ok()
57         })
58         .ok();
59
60         let mut filename = filename.unwrap_or_default();
61         if filename.is_empty() {
62             filename.push_str("<unknown file>");
63         }
64
65         OptimizationDiagnostic {
66             kind,
67             pass_name: pass_name.expect("got a non-UTF8 pass name from LLVM"),
68             function: function.unwrap(),
69             line,
70             column,
71             filename,
72             message: message.expect("got a non-UTF8 OptimizationDiagnostic message from LLVM"),
73         }
74     }
75 }
76
77 pub struct SrcMgrDiagnostic {
78     pub level: super::DiagnosticLevel,
79     pub message: String,
80     pub source: Option<(String, Vec<InnerSpan>)>,
81 }
82
83 impl SrcMgrDiagnostic {
84     pub unsafe fn unpack(diag: &SMDiagnostic) -> SrcMgrDiagnostic {
85         // Recover the post-substitution assembly code from LLVM for better
86         // diagnostics.
87         let mut have_source = false;
88         let mut buffer = String::new();
89         let mut level = super::DiagnosticLevel::Error;
90         let mut loc = 0;
91         let mut ranges = [0; 8];
92         let mut num_ranges = ranges.len() / 2;
93         let message = super::build_string(|message| {
94             buffer = super::build_string(|buffer| {
95                 have_source = super::LLVMRustUnpackSMDiagnostic(
96                     diag,
97                     message,
98                     buffer,
99                     &mut level,
100                     &mut loc,
101                     ranges.as_mut_ptr(),
102                     &mut num_ranges,
103                 );
104             })
105             .expect("non-UTF8 inline asm");
106         })
107         .expect("non-UTF8 SMDiagnostic");
108
109         SrcMgrDiagnostic {
110             message,
111             level,
112             source: have_source.then(|| {
113                 let mut spans = vec![InnerSpan::new(loc as usize, loc as usize)];
114                 for i in 0..num_ranges {
115                     spans.push(InnerSpan::new(ranges[i * 2] as usize, ranges[i * 2 + 1] as usize));
116                 }
117                 (buffer, spans)
118             }),
119         }
120     }
121 }
122
123 #[derive(Clone)]
124 pub struct InlineAsmDiagnostic {
125     pub level: super::DiagnosticLevel,
126     pub cookie: c_uint,
127     pub message: String,
128     pub source: Option<(String, Vec<InnerSpan>)>,
129 }
130
131 impl InlineAsmDiagnostic {
132     unsafe fn unpackInlineAsm(di: &DiagnosticInfo) -> Self {
133         let mut cookie = 0;
134         let mut message = None;
135         let mut level = super::DiagnosticLevel::Error;
136
137         super::LLVMRustUnpackInlineAsmDiagnostic(di, &mut level, &mut cookie, &mut message);
138
139         InlineAsmDiagnostic {
140             level,
141             cookie,
142             message: super::twine_to_string(message.unwrap()),
143             source: None,
144         }
145     }
146
147     unsafe fn unpackSrcMgr(di: &DiagnosticInfo) -> Self {
148         let mut cookie = 0;
149         let smdiag = SrcMgrDiagnostic::unpack(super::LLVMRustGetSMDiagnostic(di, &mut cookie));
150         InlineAsmDiagnostic {
151             level: smdiag.level,
152             cookie,
153             message: smdiag.message,
154             source: smdiag.source,
155         }
156     }
157 }
158
159 pub enum Diagnostic<'ll> {
160     Optimization(OptimizationDiagnostic<'ll>),
161     InlineAsm(InlineAsmDiagnostic),
162     PGO(&'ll DiagnosticInfo),
163     Linker(&'ll DiagnosticInfo),
164     Unsupported(&'ll DiagnosticInfo),
165
166     /// LLVM has other types that we do not wrap here.
167     UnknownDiagnostic(&'ll DiagnosticInfo),
168 }
169
170 impl<'ll> Diagnostic<'ll> {
171     pub unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self {
172         use super::DiagnosticKind as Dk;
173         let kind = super::LLVMRustGetDiagInfoKind(di);
174
175         match kind {
176             Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpackInlineAsm(di)),
177
178             Dk::OptimizationRemark => {
179                 Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di))
180             }
181             Dk::OptimizationRemarkOther => {
182                 Optimization(OptimizationDiagnostic::unpack(OptimizationRemarkOther, di))
183             }
184             Dk::OptimizationRemarkMissed => {
185                 Optimization(OptimizationDiagnostic::unpack(OptimizationMissed, di))
186             }
187
188             Dk::OptimizationRemarkAnalysis => {
189                 Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysis, di))
190             }
191
192             Dk::OptimizationRemarkAnalysisFPCommute => {
193                 Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisFPCommute, di))
194             }
195
196             Dk::OptimizationRemarkAnalysisAliasing => {
197                 Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisAliasing, di))
198             }
199
200             Dk::OptimizationFailure => {
201                 Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di))
202             }
203
204             Dk::PGOProfile => PGO(di),
205             Dk::Linker => Linker(di),
206             Dk::Unsupported => Unsupported(di),
207
208             Dk::SrcMgr => InlineAsm(InlineAsmDiagnostic::unpackSrcMgr(di)),
209
210             _ => UnknownDiagnostic(di),
211         }
212     }
213 }