Handle SrcMgr diagnostics
This is how InlineAsm diagnostics with source information are reported now. Previously a separate InlineAsm diagnostic handler was used.
This commit is contained in:
parent
2967036f57
commit
621f5146c3
6 changed files with 108 additions and 66 deletions
|
@ -296,39 +296,8 @@ unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void
|
||||||
}
|
}
|
||||||
let (cgcx, _) = *(user as *const (&CodegenContext<LlvmCodegenBackend>, &Handler));
|
let (cgcx, _) = *(user as *const (&CodegenContext<LlvmCodegenBackend>, &Handler));
|
||||||
|
|
||||||
// Recover the post-substitution assembly code from LLVM for better
|
let smdiag = llvm::diagnostic::SrcMgrDiagnostic::unpack(diag);
|
||||||
// diagnostics.
|
report_inline_asm(cgcx, smdiag.message, smdiag.level, cookie, smdiag.source);
|
||||||
let mut have_source = false;
|
|
||||||
let mut buffer = String::new();
|
|
||||||
let mut level = llvm::DiagnosticLevel::Error;
|
|
||||||
let mut loc = 0;
|
|
||||||
let mut ranges = [0; 8];
|
|
||||||
let mut num_ranges = ranges.len() / 2;
|
|
||||||
let msg = llvm::build_string(|msg| {
|
|
||||||
buffer = llvm::build_string(|buffer| {
|
|
||||||
have_source = llvm::LLVMRustUnpackSMDiagnostic(
|
|
||||||
diag,
|
|
||||||
msg,
|
|
||||||
buffer,
|
|
||||||
&mut level,
|
|
||||||
&mut loc,
|
|
||||||
ranges.as_mut_ptr(),
|
|
||||||
&mut num_ranges,
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.expect("non-UTF8 inline asm");
|
|
||||||
})
|
|
||||||
.expect("non-UTF8 SMDiagnostic");
|
|
||||||
|
|
||||||
let source = have_source.then(|| {
|
|
||||||
let mut spans = vec![InnerSpan::new(loc as usize, loc as usize)];
|
|
||||||
for i in 0..num_ranges {
|
|
||||||
spans.push(InnerSpan::new(ranges[i * 2] as usize, ranges[i * 2 + 1] as usize));
|
|
||||||
}
|
|
||||||
(buffer, spans)
|
|
||||||
});
|
|
||||||
|
|
||||||
report_inline_asm(cgcx, msg, level, cookie, source);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) {
|
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
|
||||||
|
|
||||||
match llvm::diagnostic::Diagnostic::unpack(info) {
|
match llvm::diagnostic::Diagnostic::unpack(info) {
|
||||||
llvm::diagnostic::InlineAsm(inline) => {
|
llvm::diagnostic::InlineAsm(inline) => {
|
||||||
report_inline_asm(
|
report_inline_asm(cgcx, inline.message, inline.level, inline.cookie, inline.source);
|
||||||
cgcx,
|
|
||||||
llvm::twine_to_string(inline.message),
|
|
||||||
inline.level,
|
|
||||||
inline.cookie,
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::diagnostic::Optimization(opt) => {
|
llvm::diagnostic::Optimization(opt) => {
|
||||||
|
|
|
@ -6,7 +6,8 @@ pub use self::OptimizationDiagnosticKind::*;
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use libc::c_uint;
|
use libc::c_uint;
|
||||||
|
|
||||||
use super::{DiagnosticInfo, Twine};
|
use super::{DiagnosticInfo, SMDiagnostic};
|
||||||
|
use rustc_span::InnerSpan;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum OptimizationDiagnosticKind {
|
pub enum OptimizationDiagnosticKind {
|
||||||
|
@ -86,36 +87,91 @@ impl OptimizationDiagnostic<'ll> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
pub struct SrcMgrDiagnostic {
|
||||||
pub struct InlineAsmDiagnostic<'ll> {
|
|
||||||
pub level: super::DiagnosticLevel,
|
pub level: super::DiagnosticLevel,
|
||||||
pub cookie: c_uint,
|
pub message: String,
|
||||||
pub message: &'ll Twine,
|
pub source: Option<(String, Vec<InnerSpan>)>,
|
||||||
pub instruction: Option<&'ll Value>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InlineAsmDiagnostic<'ll> {
|
impl SrcMgrDiagnostic {
|
||||||
unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self {
|
pub unsafe fn unpack(diag: &SMDiagnostic) -> SrcMgrDiagnostic {
|
||||||
|
// Recover the post-substitution assembly code from LLVM for better
|
||||||
|
// diagnostics.
|
||||||
|
let mut have_source = false;
|
||||||
|
let mut buffer = String::new();
|
||||||
|
let mut level = super::DiagnosticLevel::Error;
|
||||||
|
let mut loc = 0;
|
||||||
|
let mut ranges = [0; 8];
|
||||||
|
let mut num_ranges = ranges.len() / 2;
|
||||||
|
let message = super::build_string(|message| {
|
||||||
|
buffer = super::build_string(|buffer| {
|
||||||
|
have_source = super::LLVMRustUnpackSMDiagnostic(
|
||||||
|
diag,
|
||||||
|
message,
|
||||||
|
buffer,
|
||||||
|
&mut level,
|
||||||
|
&mut loc,
|
||||||
|
ranges.as_mut_ptr(),
|
||||||
|
&mut num_ranges,
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.expect("non-UTF8 inline asm");
|
||||||
|
})
|
||||||
|
.expect("non-UTF8 SMDiagnostic");
|
||||||
|
|
||||||
|
SrcMgrDiagnostic {
|
||||||
|
message,
|
||||||
|
level,
|
||||||
|
source: have_source.then(|| {
|
||||||
|
let mut spans = vec![InnerSpan::new(loc as usize, loc as usize)];
|
||||||
|
for i in 0..num_ranges {
|
||||||
|
spans.push(InnerSpan::new(ranges[i * 2] as usize, ranges[i * 2 + 1] as usize));
|
||||||
|
}
|
||||||
|
(buffer, spans)
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct InlineAsmDiagnostic {
|
||||||
|
pub level: super::DiagnosticLevel,
|
||||||
|
pub cookie: c_uint,
|
||||||
|
pub message: String,
|
||||||
|
pub source: Option<(String, Vec<InnerSpan>)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InlineAsmDiagnostic {
|
||||||
|
unsafe fn unpackInlineAsm(di: &'ll DiagnosticInfo) -> Self {
|
||||||
let mut cookie = 0;
|
let mut cookie = 0;
|
||||||
let mut message = None;
|
let mut message = None;
|
||||||
let mut instruction = None;
|
|
||||||
let mut level = super::DiagnosticLevel::Error;
|
let mut level = super::DiagnosticLevel::Error;
|
||||||
|
|
||||||
super::LLVMRustUnpackInlineAsmDiagnostic(
|
super::LLVMRustUnpackInlineAsmDiagnostic(di, &mut level, &mut cookie, &mut message);
|
||||||
di,
|
|
||||||
&mut level,
|
|
||||||
&mut cookie,
|
|
||||||
&mut message,
|
|
||||||
&mut instruction,
|
|
||||||
);
|
|
||||||
|
|
||||||
InlineAsmDiagnostic { level, cookie, message: message.unwrap(), instruction }
|
InlineAsmDiagnostic {
|
||||||
|
level,
|
||||||
|
cookie,
|
||||||
|
message: super::twine_to_string(message.unwrap()),
|
||||||
|
source: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn unpackSrcMgr(di: &'ll DiagnosticInfo) -> Self {
|
||||||
|
let mut cookie = 0;
|
||||||
|
let smdiag = SrcMgrDiagnostic::unpack(super::LLVMRustGetSMDiagnostic(di, &mut cookie));
|
||||||
|
InlineAsmDiagnostic {
|
||||||
|
level: smdiag.level,
|
||||||
|
cookie,
|
||||||
|
message: smdiag.message,
|
||||||
|
source: smdiag.source,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Diagnostic<'ll> {
|
pub enum Diagnostic<'ll> {
|
||||||
Optimization(OptimizationDiagnostic<'ll>),
|
Optimization(OptimizationDiagnostic<'ll>),
|
||||||
InlineAsm(InlineAsmDiagnostic<'ll>),
|
InlineAsm(InlineAsmDiagnostic),
|
||||||
PGO(&'ll DiagnosticInfo),
|
PGO(&'ll DiagnosticInfo),
|
||||||
Linker(&'ll DiagnosticInfo),
|
Linker(&'ll DiagnosticInfo),
|
||||||
Unsupported(&'ll DiagnosticInfo),
|
Unsupported(&'ll DiagnosticInfo),
|
||||||
|
@ -130,7 +186,7 @@ impl Diagnostic<'ll> {
|
||||||
let kind = super::LLVMRustGetDiagInfoKind(di);
|
let kind = super::LLVMRustGetDiagInfoKind(di);
|
||||||
|
|
||||||
match kind {
|
match kind {
|
||||||
Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpack(di)),
|
Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpackInlineAsm(di)),
|
||||||
|
|
||||||
Dk::OptimizationRemark => {
|
Dk::OptimizationRemark => {
|
||||||
Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di))
|
Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di))
|
||||||
|
@ -162,6 +218,8 @@ impl Diagnostic<'ll> {
|
||||||
Dk::Linker => Linker(di),
|
Dk::Linker => Linker(di),
|
||||||
Dk::Unsupported => Unsupported(di),
|
Dk::Unsupported => Unsupported(di),
|
||||||
|
|
||||||
|
Dk::SrcMgr => InlineAsm(InlineAsmDiagnostic::unpackSrcMgr(di)),
|
||||||
|
|
||||||
_ => UnknownDiagnostic(di),
|
_ => UnknownDiagnostic(di),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -490,6 +490,7 @@ pub enum DiagnosticKind {
|
||||||
PGOProfile,
|
PGOProfile,
|
||||||
Linker,
|
Linker,
|
||||||
Unsupported,
|
Unsupported,
|
||||||
|
SrcMgr,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// LLVMRustDiagnosticLevel
|
/// LLVMRustDiagnosticLevel
|
||||||
|
@ -2264,13 +2265,17 @@ extern "C" {
|
||||||
level_out: &mut DiagnosticLevel,
|
level_out: &mut DiagnosticLevel,
|
||||||
cookie_out: &mut c_uint,
|
cookie_out: &mut c_uint,
|
||||||
message_out: &mut Option<&'a Twine>,
|
message_out: &mut Option<&'a Twine>,
|
||||||
instruction_out: &mut Option<&'a Value>,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
#[allow(improper_ctypes)]
|
#[allow(improper_ctypes)]
|
||||||
pub fn LLVMRustWriteDiagnosticInfoToString(DI: &DiagnosticInfo, s: &RustString);
|
pub fn LLVMRustWriteDiagnosticInfoToString(DI: &DiagnosticInfo, s: &RustString);
|
||||||
pub fn LLVMRustGetDiagInfoKind(DI: &DiagnosticInfo) -> DiagnosticKind;
|
pub fn LLVMRustGetDiagInfoKind(DI: &DiagnosticInfo) -> DiagnosticKind;
|
||||||
|
|
||||||
|
pub fn LLVMRustGetSMDiagnostic(
|
||||||
|
DI: &'a DiagnosticInfo,
|
||||||
|
cookie_out: &mut c_uint,
|
||||||
|
) -> &'a SMDiagnostic;
|
||||||
|
|
||||||
pub fn LLVMRustSetInlineAsmDiagnosticHandler(
|
pub fn LLVMRustSetInlineAsmDiagnosticHandler(
|
||||||
C: &Context,
|
C: &Context,
|
||||||
H: InlineAsmDiagHandler,
|
H: InlineAsmDiagHandler,
|
||||||
|
|
|
@ -1114,15 +1114,13 @@ extern "C" void
|
||||||
LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
|
LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
|
||||||
LLVMRustDiagnosticLevel *LevelOut,
|
LLVMRustDiagnosticLevel *LevelOut,
|
||||||
unsigned *CookieOut,
|
unsigned *CookieOut,
|
||||||
LLVMTwineRef *MessageOut,
|
LLVMTwineRef *MessageOut) {
|
||||||
LLVMValueRef *InstructionOut) {
|
|
||||||
// Undefined to call this not on an inline assembly diagnostic!
|
// Undefined to call this not on an inline assembly diagnostic!
|
||||||
llvm::DiagnosticInfoInlineAsm *IA =
|
llvm::DiagnosticInfoInlineAsm *IA =
|
||||||
static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
|
static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
|
||||||
|
|
||||||
*CookieOut = IA->getLocCookie();
|
*CookieOut = IA->getLocCookie();
|
||||||
*MessageOut = wrap(&IA->getMsgStr());
|
*MessageOut = wrap(&IA->getMsgStr());
|
||||||
*InstructionOut = wrap(IA->getInstruction());
|
|
||||||
|
|
||||||
switch (IA->getSeverity()) {
|
switch (IA->getSeverity()) {
|
||||||
case DS_Error:
|
case DS_Error:
|
||||||
|
@ -1165,6 +1163,7 @@ enum class LLVMRustDiagnosticKind {
|
||||||
PGOProfile,
|
PGOProfile,
|
||||||
Linker,
|
Linker,
|
||||||
Unsupported,
|
Unsupported,
|
||||||
|
SrcMgr,
|
||||||
};
|
};
|
||||||
|
|
||||||
static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
|
static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
|
||||||
|
@ -1193,6 +1192,10 @@ static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
|
||||||
return LLVMRustDiagnosticKind::Linker;
|
return LLVMRustDiagnosticKind::Linker;
|
||||||
case DK_Unsupported:
|
case DK_Unsupported:
|
||||||
return LLVMRustDiagnosticKind::Unsupported;
|
return LLVMRustDiagnosticKind::Unsupported;
|
||||||
|
#if LLVM_VERSION_GE(13, 0)
|
||||||
|
case DK_SrcMgr:
|
||||||
|
return LLVMRustDiagnosticKind::SrcMgr;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
|
return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
|
||||||
? LLVMRustDiagnosticKind::OptimizationRemarkOther
|
? LLVMRustDiagnosticKind::OptimizationRemarkOther
|
||||||
|
@ -1280,6 +1283,17 @@ extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(
|
||||||
|
LLVMDiagnosticInfoRef DI, unsigned *Cookie) {
|
||||||
|
#if LLVM_VERSION_GE(13, 0)
|
||||||
|
llvm::DiagnosticInfoSrcMgr *SM = static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
|
||||||
|
*Cookie = SM->getLocCookie();
|
||||||
|
return wrap(&SM->getSMDiag());
|
||||||
|
#else
|
||||||
|
report_fatal_error("Shouldn't get called on older versions");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
|
extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
|
||||||
RustStringRef MessageOut,
|
RustStringRef MessageOut,
|
||||||
RustStringRef BufferOut,
|
RustStringRef BufferOut,
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// build-fail
|
// build-fail
|
||||||
// ignore-emscripten no asm! support
|
// ignore-emscripten no asm! support
|
||||||
|
// The error message differs slightly between LLVM versions
|
||||||
|
// min-llvm-version: 13.0
|
||||||
// Regression test for #69092
|
// Regression test for #69092
|
||||||
|
|
||||||
#![feature(llvm_asm)]
|
#![feature(llvm_asm)]
|
||||||
|
@ -7,5 +9,5 @@
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe { llvm_asm!(".ascii \"Xen\0\""); }
|
unsafe { llvm_asm!(".ascii \"Xen\0\""); }
|
||||||
//~^ ERROR: expected string in '.ascii' directive
|
//~^ ERROR: expected string
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: expected string in '.ascii' directive
|
error: expected string
|
||||||
--> $DIR/issue-69092.rs:9:14
|
--> $DIR/issue-69092.rs:11:14
|
||||||
|
|
|
|
||||||
LL | unsafe { llvm_asm!(".ascii \"Xen\0\""); }
|
LL | unsafe { llvm_asm!(".ascii \"Xen\0\""); }
|
||||||
| ^
|
| ^
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue