Skip to content

Commit 621f514

Browse files
committed
Handle SrcMgr diagnostics
This is how InlineAsm diagnostics with source information are reported now. Previously a separate InlineAsm diagnostic handler was used.
1 parent 2967036 commit 621f514

File tree

6 files changed

+107
-65
lines changed

6 files changed

+107
-65
lines changed

compiler/rustc_codegen_llvm/src/back/write.rs

Lines changed: 3 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -296,39 +296,8 @@ unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void
296296
}
297297
let (cgcx, _) = *(user as *const (&CodegenContext<LlvmCodegenBackend>, &Handler));
298298

299-
// Recover the post-substitution assembly code from LLVM for better
300-
// diagnostics.
301-
let mut have_source = false;
302-
let mut buffer = String::new();
303-
let mut level = llvm::DiagnosticLevel::Error;
304-
let mut loc = 0;
305-
let mut ranges = [0; 8];
306-
let mut num_ranges = ranges.len() / 2;
307-
let msg = llvm::build_string(|msg| {
308-
buffer = llvm::build_string(|buffer| {
309-
have_source = llvm::LLVMRustUnpackSMDiagnostic(
310-
diag,
311-
msg,
312-
buffer,
313-
&mut level,
314-
&mut loc,
315-
ranges.as_mut_ptr(),
316-
&mut num_ranges,
317-
);
318-
})
319-
.expect("non-UTF8 inline asm");
320-
})
321-
.expect("non-UTF8 SMDiagnostic");
322-
323-
let source = have_source.then(|| {
324-
let mut spans = vec![InnerSpan::new(loc as usize, loc as usize)];
325-
for i in 0..num_ranges {
326-
spans.push(InnerSpan::new(ranges[i * 2] as usize, ranges[i * 2 + 1] as usize));
327-
}
328-
(buffer, spans)
329-
});
330-
331-
report_inline_asm(cgcx, msg, level, cookie, source);
299+
let smdiag = llvm::diagnostic::SrcMgrDiagnostic::unpack(diag);
300+
report_inline_asm(cgcx, smdiag.message, smdiag.level, cookie, smdiag.source);
332301
}
333302

334303
unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) {
@@ -339,13 +308,7 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void
339308

340309
match llvm::diagnostic::Diagnostic::unpack(info) {
341310
llvm::diagnostic::InlineAsm(inline) => {
342-
report_inline_asm(
343-
cgcx,
344-
llvm::twine_to_string(inline.message),
345-
inline.level,
346-
inline.cookie,
347-
None,
348-
);
311+
report_inline_asm(cgcx, inline.message, inline.level, inline.cookie, inline.source);
349312
}
350313

351314
llvm::diagnostic::Optimization(opt) => {

compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs

Lines changed: 76 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ pub use self::OptimizationDiagnosticKind::*;
66
use crate::value::Value;
77
use libc::c_uint;
88

9-
use super::{DiagnosticInfo, Twine};
9+
use super::{DiagnosticInfo, SMDiagnostic};
10+
use rustc_span::InnerSpan;
1011

1112
#[derive(Copy, Clone)]
1213
pub enum OptimizationDiagnosticKind {
@@ -86,36 +87,91 @@ impl OptimizationDiagnostic<'ll> {
8687
}
8788
}
8889

89-
#[derive(Copy, Clone)]
90-
pub struct InlineAsmDiagnostic<'ll> {
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 {
91138
pub level: super::DiagnosticLevel,
92139
pub cookie: c_uint,
93-
pub message: &'ll Twine,
94-
pub instruction: Option<&'ll Value>,
140+
pub message: String,
141+
pub source: Option<(String, Vec<InnerSpan>)>,
95142
}
96143

97-
impl InlineAsmDiagnostic<'ll> {
98-
unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self {
144+
impl InlineAsmDiagnostic {
145+
unsafe fn unpackInlineAsm(di: &'ll DiagnosticInfo) -> Self {
99146
let mut cookie = 0;
100147
let mut message = None;
101-
let mut instruction = None;
102148
let mut level = super::DiagnosticLevel::Error;
103149

104-
super::LLVMRustUnpackInlineAsmDiagnostic(
105-
di,
106-
&mut level,
107-
&mut cookie,
108-
&mut message,
109-
&mut instruction,
110-
);
150+
super::LLVMRustUnpackInlineAsmDiagnostic(di, &mut level, &mut cookie, &mut message);
111151

112-
InlineAsmDiagnostic { level, cookie, message: message.unwrap(), instruction }
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: &'ll 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+
}
113169
}
114170
}
115171

116172
pub enum Diagnostic<'ll> {
117173
Optimization(OptimizationDiagnostic<'ll>),
118-
InlineAsm(InlineAsmDiagnostic<'ll>),
174+
InlineAsm(InlineAsmDiagnostic),
119175
PGO(&'ll DiagnosticInfo),
120176
Linker(&'ll DiagnosticInfo),
121177
Unsupported(&'ll DiagnosticInfo),
@@ -130,7 +186,7 @@ impl Diagnostic<'ll> {
130186
let kind = super::LLVMRustGetDiagInfoKind(di);
131187

132188
match kind {
133-
Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpack(di)),
189+
Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpackInlineAsm(di)),
134190

135191
Dk::OptimizationRemark => {
136192
Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di))
@@ -162,6 +218,8 @@ impl Diagnostic<'ll> {
162218
Dk::Linker => Linker(di),
163219
Dk::Unsupported => Unsupported(di),
164220

221+
Dk::SrcMgr => InlineAsm(InlineAsmDiagnostic::unpackSrcMgr(di)),
222+
165223
_ => UnknownDiagnostic(di),
166224
}
167225
}

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,7 @@ pub enum DiagnosticKind {
490490
PGOProfile,
491491
Linker,
492492
Unsupported,
493+
SrcMgr,
493494
}
494495

495496
/// LLVMRustDiagnosticLevel
@@ -2264,13 +2265,17 @@ extern "C" {
22642265
level_out: &mut DiagnosticLevel,
22652266
cookie_out: &mut c_uint,
22662267
message_out: &mut Option<&'a Twine>,
2267-
instruction_out: &mut Option<&'a Value>,
22682268
);
22692269

22702270
#[allow(improper_ctypes)]
22712271
pub fn LLVMRustWriteDiagnosticInfoToString(DI: &DiagnosticInfo, s: &RustString);
22722272
pub fn LLVMRustGetDiagInfoKind(DI: &DiagnosticInfo) -> DiagnosticKind;
22732273

2274+
pub fn LLVMRustGetSMDiagnostic(
2275+
DI: &'a DiagnosticInfo,
2276+
cookie_out: &mut c_uint,
2277+
) -> &'a SMDiagnostic;
2278+
22742279
pub fn LLVMRustSetInlineAsmDiagnosticHandler(
22752280
C: &Context,
22762281
H: InlineAsmDiagHandler,

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,15 +1114,13 @@ extern "C" void
11141114
LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
11151115
LLVMRustDiagnosticLevel *LevelOut,
11161116
unsigned *CookieOut,
1117-
LLVMTwineRef *MessageOut,
1118-
LLVMValueRef *InstructionOut) {
1117+
LLVMTwineRef *MessageOut) {
11191118
// Undefined to call this not on an inline assembly diagnostic!
11201119
llvm::DiagnosticInfoInlineAsm *IA =
11211120
static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
11221121

11231122
*CookieOut = IA->getLocCookie();
11241123
*MessageOut = wrap(&IA->getMsgStr());
1125-
*InstructionOut = wrap(IA->getInstruction());
11261124

11271125
switch (IA->getSeverity()) {
11281126
case DS_Error:
@@ -1165,6 +1163,7 @@ enum class LLVMRustDiagnosticKind {
11651163
PGOProfile,
11661164
Linker,
11671165
Unsupported,
1166+
SrcMgr,
11681167
};
11691168

11701169
static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
@@ -1193,6 +1192,10 @@ static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
11931192
return LLVMRustDiagnosticKind::Linker;
11941193
case DK_Unsupported:
11951194
return LLVMRustDiagnosticKind::Unsupported;
1195+
#if LLVM_VERSION_GE(13, 0)
1196+
case DK_SrcMgr:
1197+
return LLVMRustDiagnosticKind::SrcMgr;
1198+
#endif
11961199
default:
11971200
return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
11981201
? LLVMRustDiagnosticKind::OptimizationRemarkOther
@@ -1280,6 +1283,17 @@ extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
12801283
#endif
12811284
}
12821285

1286+
extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(
1287+
LLVMDiagnosticInfoRef DI, unsigned *Cookie) {
1288+
#if LLVM_VERSION_GE(13, 0)
1289+
llvm::DiagnosticInfoSrcMgr *SM = static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
1290+
*Cookie = SM->getLocCookie();
1291+
return wrap(&SM->getSMDiag());
1292+
#else
1293+
report_fatal_error("Shouldn't get called on older versions");
1294+
#endif
1295+
}
1296+
12831297
extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
12841298
RustStringRef MessageOut,
12851299
RustStringRef BufferOut,

src/test/ui/llvm-asm/issue-69092.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
// build-fail
22
// ignore-emscripten no asm! support
3+
// The error message differs slightly between LLVM versions
4+
// min-llvm-version: 13.0
35
// Regression test for #69092
46

57
#![feature(llvm_asm)]
68
#![allow(deprecated)] // llvm_asm!
79

810
fn main() {
911
unsafe { llvm_asm!(".ascii \"Xen\0\""); }
10-
//~^ ERROR: expected string in '.ascii' directive
12+
//~^ ERROR: expected string
1113
}

src/test/ui/llvm-asm/issue-69092.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
error: expected string in '.ascii' directive
2-
--> $DIR/issue-69092.rs:9:14
1+
error: expected string
2+
--> $DIR/issue-69092.rs:11:14
33
|
44
LL | unsafe { llvm_asm!(".ascii \"Xen\0\""); }
55
| ^

0 commit comments

Comments
 (0)