Auto merge of #129181 - beetrees:asm-spans, r=pnkfelix,compiler-errors
Pass end position of span through inline ASM cookie Before this PR, only the start position of the span was passed though the inline ASM cookie to diagnostics. LLVM 19 has full support for 64-bit inline ASM cookies; this PR uses that to pass the end position of the span in the upper 32 bits, meaning inline ASM diagnostics now point at the entire line the error occurred on, not just the first character of it.
This commit is contained in:
commit
903d2976fd
24 changed files with 1565 additions and 200 deletions
|
@ -512,14 +512,13 @@ pub(crate) fn inline_asm_call<'ll>(
|
|||
let key = "srcloc";
|
||||
let kind = llvm::LLVMGetMDKindIDInContext(
|
||||
bx.llcx,
|
||||
key.as_ptr() as *const c_char,
|
||||
key.as_ptr().cast::<c_char>(),
|
||||
key.len() as c_uint,
|
||||
);
|
||||
|
||||
// srcloc contains one integer for each line of assembly code.
|
||||
// Unfortunately this isn't enough to encode a full span so instead
|
||||
// we just encode the start position of each line.
|
||||
// FIXME: Figure out a way to pass the entire line spans.
|
||||
// `srcloc` contains one 64-bit integer for each line of assembly code,
|
||||
// where the lower 32 bits hold the lo byte position and the upper 32 bits
|
||||
// hold the hi byte position.
|
||||
let mut srcloc = vec![];
|
||||
if dia == llvm::AsmDialect::Intel && line_spans.len() > 1 {
|
||||
// LLVM inserts an extra line to add the ".intel_syntax", so add
|
||||
|
@ -529,13 +528,13 @@ pub(crate) fn inline_asm_call<'ll>(
|
|||
// due to the asm template string coming from a macro. LLVM will
|
||||
// default to the first srcloc for lines that don't have an
|
||||
// associated srcloc.
|
||||
srcloc.push(llvm::LLVMValueAsMetadata(bx.const_i32(0)));
|
||||
srcloc.push(llvm::LLVMValueAsMetadata(bx.const_u64(0)));
|
||||
}
|
||||
srcloc.extend(
|
||||
line_spans
|
||||
.iter()
|
||||
.map(|span| llvm::LLVMValueAsMetadata(bx.const_i32(span.lo().to_u32() as i32))),
|
||||
);
|
||||
srcloc.extend(line_spans.iter().map(|span| {
|
||||
llvm::LLVMValueAsMetadata(bx.const_u64(
|
||||
u64::from(span.lo().to_u32()) | (u64::from(span.hi().to_u32()) << 32),
|
||||
))
|
||||
}));
|
||||
let md = llvm::LLVMMDNodeInContext2(bx.llcx, srcloc.as_ptr(), srcloc.len());
|
||||
let md = llvm::LLVMMetadataAsValue(&bx.llcx, md);
|
||||
llvm::LLVMSetMetadata(call, kind, md);
|
||||
|
|
|
@ -25,8 +25,8 @@ use rustc_session::Session;
|
|||
use rustc_session::config::{
|
||||
self, Lto, OutputType, Passes, RemapPathScopeComponents, SplitDwarfKind, SwitchWithOptPath,
|
||||
};
|
||||
use rustc_span::InnerSpan;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{BytePos, InnerSpan, Pos, SpanData, SyntaxContext};
|
||||
use rustc_target::spec::{CodeModel, RelocModel, SanitizerSet, SplitDebuginfo, TlsModel};
|
||||
use tracing::debug;
|
||||
|
||||
|
@ -415,21 +415,32 @@ fn report_inline_asm(
|
|||
cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||
msg: String,
|
||||
level: llvm::DiagnosticLevel,
|
||||
mut cookie: u64,
|
||||
cookie: u64,
|
||||
source: Option<(String, Vec<InnerSpan>)>,
|
||||
) {
|
||||
// In LTO build we may get srcloc values from other crates which are invalid
|
||||
// since they use a different source map. To be safe we just suppress these
|
||||
// in LTO builds.
|
||||
if matches!(cgcx.lto, Lto::Fat | Lto::Thin) {
|
||||
cookie = 0;
|
||||
}
|
||||
let span = if cookie == 0 || matches!(cgcx.lto, Lto::Fat | Lto::Thin) {
|
||||
SpanData::default()
|
||||
} else {
|
||||
let lo = BytePos::from_u32(cookie as u32);
|
||||
let hi = BytePos::from_u32((cookie >> 32) as u32);
|
||||
SpanData {
|
||||
lo,
|
||||
// LLVM version < 19 silently truncates the cookie to 32 bits in some situations.
|
||||
hi: if hi.to_u32() != 0 { hi } else { lo },
|
||||
ctxt: SyntaxContext::root(),
|
||||
parent: None,
|
||||
}
|
||||
};
|
||||
let level = match level {
|
||||
llvm::DiagnosticLevel::Error => Level::Error,
|
||||
llvm::DiagnosticLevel::Warning => Level::Warning,
|
||||
llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note,
|
||||
};
|
||||
cgcx.diag_emitter.inline_asm_error(cookie.try_into().unwrap(), msg, level, source);
|
||||
let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string();
|
||||
cgcx.diag_emitter.inline_asm_error(span, msg, level, source);
|
||||
}
|
||||
|
||||
unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) {
|
||||
|
|
|
@ -151,7 +151,7 @@ impl InlineAsmDiagnostic {
|
|||
unsafe { SrcMgrDiagnostic::unpack(super::LLVMRustGetSMDiagnostic(di, &mut cookie)) };
|
||||
InlineAsmDiagnostic {
|
||||
level: smdiag.level,
|
||||
cookie: cookie.into(),
|
||||
cookie,
|
||||
message: smdiag.message,
|
||||
source: smdiag.source,
|
||||
}
|
||||
|
|
|
@ -2317,7 +2317,7 @@ unsafe extern "C" {
|
|||
|
||||
pub fn LLVMRustGetSMDiagnostic<'a>(
|
||||
DI: &'a DiagnosticInfo,
|
||||
cookie_out: &mut c_uint,
|
||||
cookie_out: &mut u64,
|
||||
) -> &'a SMDiagnostic;
|
||||
|
||||
pub fn LLVMRustUnpackSMDiagnostic(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue