rustc_codegen_llvm/llvm/
diagnostic.rs
1use libc::c_uint;
4use rustc_span::InnerSpan;
5
6pub(crate) use self::Diagnostic::*;
7use self::OptimizationDiagnosticKind::*;
8use super::{DiagnosticInfo, SMDiagnostic};
9use crate::value::Value;
10
11#[derive(Copy, Clone, Debug)]
12pub(crate) enum OptimizationDiagnosticKind {
13 OptimizationRemark,
14 OptimizationMissed,
15 OptimizationAnalysis,
16 OptimizationAnalysisFPCommute,
17 OptimizationAnalysisAliasing,
18 OptimizationFailure,
19 OptimizationRemarkOther,
20}
21
22pub(crate) struct OptimizationDiagnostic<'ll> {
23 pub kind: OptimizationDiagnosticKind,
24 pub pass_name: String,
25 #[expect(dead_code)]
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
33impl<'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| unsafe {
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
77pub(crate) struct SrcMgrDiagnostic {
78 pub level: super::DiagnosticLevel,
79 pub message: String,
80 pub source: Option<(String, Vec<InnerSpan>)>,
81}
82
83impl SrcMgrDiagnostic {
84 pub(crate) unsafe fn unpack(diag: &SMDiagnostic) -> SrcMgrDiagnostic {
85 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| unsafe {
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)]
124pub(crate) struct InlineAsmDiagnostic {
125 pub level: super::DiagnosticLevel,
126 pub cookie: u64,
127 pub message: String,
128 pub source: Option<(String, Vec<InnerSpan>)>,
129}
130
131impl 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 unsafe {
138 super::LLVMRustUnpackInlineAsmDiagnostic(di, &mut level, &mut cookie, &mut message);
139 }
140
141 InlineAsmDiagnostic {
142 level,
143 cookie,
144 message: super::twine_to_string(message.unwrap()),
145 source: None,
146 }
147 }
148
149 unsafe fn unpackSrcMgr(di: &DiagnosticInfo) -> Self {
150 let mut cookie = 0;
151 let smdiag =
152 unsafe { SrcMgrDiagnostic::unpack(super::LLVMRustGetSMDiagnostic(di, &mut cookie)) };
153 InlineAsmDiagnostic {
154 level: smdiag.level,
155 cookie,
156 message: smdiag.message,
157 source: smdiag.source,
158 }
159 }
160}
161
162pub(crate) enum Diagnostic<'ll> {
163 Optimization(OptimizationDiagnostic<'ll>),
164 InlineAsm(InlineAsmDiagnostic),
165 PGO(&'ll DiagnosticInfo),
166 Linker(&'ll DiagnosticInfo),
167 Unsupported(&'ll DiagnosticInfo),
168
169 #[expect(dead_code)]
171 UnknownDiagnostic(&'ll DiagnosticInfo),
172}
173
174impl<'ll> Diagnostic<'ll> {
175 pub(crate) unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self {
176 use super::DiagnosticKind as Dk;
177
178 unsafe {
179 let kind = super::LLVMRustGetDiagInfoKind(di);
180 match kind {
181 Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpackInlineAsm(di)),
182
183 Dk::OptimizationRemark => {
184 Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di))
185 }
186 Dk::OptimizationRemarkOther => {
187 Optimization(OptimizationDiagnostic::unpack(OptimizationRemarkOther, di))
188 }
189 Dk::OptimizationRemarkMissed => {
190 Optimization(OptimizationDiagnostic::unpack(OptimizationMissed, di))
191 }
192
193 Dk::OptimizationRemarkAnalysis => {
194 Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysis, di))
195 }
196
197 Dk::OptimizationRemarkAnalysisFPCommute => {
198 Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisFPCommute, di))
199 }
200
201 Dk::OptimizationRemarkAnalysisAliasing => {
202 Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisAliasing, di))
203 }
204
205 Dk::OptimizationFailure => {
206 Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di))
207 }
208
209 Dk::PGOProfile => PGO(di),
210 Dk::Linker => Linker(di),
211 Dk::Unsupported => Unsupported(di),
212
213 Dk::SrcMgr => InlineAsm(InlineAsmDiagnostic::unpackSrcMgr(di)),
214
215 _ => UnknownDiagnostic(di),
216 }
217 }
218 }
219}