]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
Rollup merge of #76851 - fusion-engineering-forks:fixme-nonzero, r=petrochenkov
[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, Twine};
10
11 #[derive(Copy, Clone)]
12 pub enum OptimizationDiagnosticKind {
13     OptimizationRemark,
14     OptimizationMissed,
15     OptimizationAnalysis,
16     OptimizationAnalysisFPCommute,
17     OptimizationAnalysisAliasing,
18     OptimizationFailure,
19     OptimizationRemarkOther,
20 }
21
22 impl OptimizationDiagnosticKind {
23     pub fn describe(self) -> &'static str {
24         match self {
25             OptimizationRemark | OptimizationRemarkOther => "remark",
26             OptimizationMissed => "missed",
27             OptimizationAnalysis => "analysis",
28             OptimizationAnalysisFPCommute => "floating-point",
29             OptimizationAnalysisAliasing => "aliasing",
30             OptimizationFailure => "failure",
31         }
32     }
33 }
34
35 pub struct OptimizationDiagnostic<'ll> {
36     pub kind: OptimizationDiagnosticKind,
37     pub pass_name: String,
38     pub function: &'ll Value,
39     pub line: c_uint,
40     pub column: c_uint,
41     pub filename: String,
42     pub message: String,
43 }
44
45 impl OptimizationDiagnostic<'ll> {
46     unsafe fn unpack(kind: OptimizationDiagnosticKind, di: &'ll DiagnosticInfo) -> Self {
47         let mut function = None;
48         let mut line = 0;
49         let mut column = 0;
50
51         let mut message = None;
52         let mut filename = None;
53         let pass_name = super::build_string(|pass_name| {
54             message = super::build_string(|message| {
55                 filename = super::build_string(|filename| {
56                     super::LLVMRustUnpackOptimizationDiagnostic(
57                         di,
58                         pass_name,
59                         &mut function,
60                         &mut line,
61                         &mut column,
62                         filename,
63                         message,
64                     )
65                 })
66                 .ok()
67             })
68             .ok()
69         })
70         .ok();
71
72         let mut filename = filename.unwrap_or_default();
73         if filename.is_empty() {
74             filename.push_str("<unknown file>");
75         }
76
77         OptimizationDiagnostic {
78             kind,
79             pass_name: pass_name.expect("got a non-UTF8 pass name from LLVM"),
80             function: function.unwrap(),
81             line,
82             column,
83             filename,
84             message: message.expect("got a non-UTF8 OptimizationDiagnostic message from LLVM"),
85         }
86     }
87 }
88
89 #[derive(Copy, Clone)]
90 pub struct InlineAsmDiagnostic<'ll> {
91     pub level: super::DiagnosticLevel,
92     pub cookie: c_uint,
93     pub message: &'ll Twine,
94     pub instruction: Option<&'ll Value>,
95 }
96
97 impl InlineAsmDiagnostic<'ll> {
98     unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self {
99         let mut cookie = 0;
100         let mut message = None;
101         let mut instruction = None;
102         let mut level = super::DiagnosticLevel::Error;
103
104         super::LLVMRustUnpackInlineAsmDiagnostic(
105             di,
106             &mut level,
107             &mut cookie,
108             &mut message,
109             &mut instruction,
110         );
111
112         InlineAsmDiagnostic { level, cookie, message: message.unwrap(), instruction }
113     }
114 }
115
116 pub enum Diagnostic<'ll> {
117     Optimization(OptimizationDiagnostic<'ll>),
118     InlineAsm(InlineAsmDiagnostic<'ll>),
119     PGO(&'ll DiagnosticInfo),
120     Linker(&'ll DiagnosticInfo),
121     Unsupported(&'ll DiagnosticInfo),
122
123     /// LLVM has other types that we do not wrap here.
124     UnknownDiagnostic(&'ll DiagnosticInfo),
125 }
126
127 impl Diagnostic<'ll> {
128     pub unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self {
129         use super::DiagnosticKind as Dk;
130         let kind = super::LLVMRustGetDiagInfoKind(di);
131
132         match kind {
133             Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpack(di)),
134
135             Dk::OptimizationRemark => {
136                 Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di))
137             }
138             Dk::OptimizationRemarkOther => {
139                 Optimization(OptimizationDiagnostic::unpack(OptimizationRemarkOther, di))
140             }
141             Dk::OptimizationRemarkMissed => {
142                 Optimization(OptimizationDiagnostic::unpack(OptimizationMissed, di))
143             }
144
145             Dk::OptimizationRemarkAnalysis => {
146                 Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysis, di))
147             }
148
149             Dk::OptimizationRemarkAnalysisFPCommute => {
150                 Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisFPCommute, di))
151             }
152
153             Dk::OptimizationRemarkAnalysisAliasing => {
154                 Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisAliasing, di))
155             }
156
157             Dk::OptimizationFailure => {
158                 Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di))
159             }
160
161             Dk::PGOProfile => PGO(di),
162             Dk::Linker => Linker(di),
163             Dk::Unsupported => Unsupported(di),
164
165             _ => UnknownDiagnostic(di),
166         }
167     }
168 }