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