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