Skip to content

Commit 903d297

Browse files
committed
Auto merge of rust-lang#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.
2 parents 1daec06 + 68227a3 commit 903d297

24 files changed

+1565
-200
lines changed

compiler/rustc_codegen_llvm/src/asm.rs

+10-11
Original file line numberDiff line numberDiff line change
@@ -512,14 +512,13 @@ pub(crate) fn inline_asm_call<'ll>(
512512
let key = "srcloc";
513513
let kind = llvm::LLVMGetMDKindIDInContext(
514514
bx.llcx,
515-
key.as_ptr() as *const c_char,
515+
key.as_ptr().cast::<c_char>(),
516516
key.len() as c_uint,
517517
);
518518

519-
// srcloc contains one integer for each line of assembly code.
520-
// Unfortunately this isn't enough to encode a full span so instead
521-
// we just encode the start position of each line.
522-
// FIXME: Figure out a way to pass the entire line spans.
519+
// `srcloc` contains one 64-bit integer for each line of assembly code,
520+
// where the lower 32 bits hold the lo byte position and the upper 32 bits
521+
// hold the hi byte position.
523522
let mut srcloc = vec![];
524523
if dia == llvm::AsmDialect::Intel && line_spans.len() > 1 {
525524
// LLVM inserts an extra line to add the ".intel_syntax", so add
@@ -529,13 +528,13 @@ pub(crate) fn inline_asm_call<'ll>(
529528
// due to the asm template string coming from a macro. LLVM will
530529
// default to the first srcloc for lines that don't have an
531530
// associated srcloc.
532-
srcloc.push(llvm::LLVMValueAsMetadata(bx.const_i32(0)));
531+
srcloc.push(llvm::LLVMValueAsMetadata(bx.const_u64(0)));
533532
}
534-
srcloc.extend(
535-
line_spans
536-
.iter()
537-
.map(|span| llvm::LLVMValueAsMetadata(bx.const_i32(span.lo().to_u32() as i32))),
538-
);
533+
srcloc.extend(line_spans.iter().map(|span| {
534+
llvm::LLVMValueAsMetadata(bx.const_u64(
535+
u64::from(span.lo().to_u32()) | (u64::from(span.hi().to_u32()) << 32),
536+
))
537+
}));
539538
let md = llvm::LLVMMDNodeInContext2(bx.llcx, srcloc.as_ptr(), srcloc.len());
540539
let md = llvm::LLVMMetadataAsValue(&bx.llcx, md);
541540
llvm::LLVMSetMetadata(call, kind, md);

compiler/rustc_codegen_llvm/src/back/write.rs

+17-6
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ use rustc_session::Session;
2525
use rustc_session::config::{
2626
self, Lto, OutputType, Passes, RemapPathScopeComponents, SplitDwarfKind, SwitchWithOptPath,
2727
};
28-
use rustc_span::InnerSpan;
2928
use rustc_span::symbol::sym;
29+
use rustc_span::{BytePos, InnerSpan, Pos, SpanData, SyntaxContext};
3030
use rustc_target::spec::{CodeModel, RelocModel, SanitizerSet, SplitDebuginfo, TlsModel};
3131
use tracing::debug;
3232

@@ -415,21 +415,32 @@ fn report_inline_asm(
415415
cgcx: &CodegenContext<LlvmCodegenBackend>,
416416
msg: String,
417417
level: llvm::DiagnosticLevel,
418-
mut cookie: u64,
418+
cookie: u64,
419419
source: Option<(String, Vec<InnerSpan>)>,
420420
) {
421421
// In LTO build we may get srcloc values from other crates which are invalid
422422
// since they use a different source map. To be safe we just suppress these
423423
// in LTO builds.
424-
if matches!(cgcx.lto, Lto::Fat | Lto::Thin) {
425-
cookie = 0;
426-
}
424+
let span = if cookie == 0 || matches!(cgcx.lto, Lto::Fat | Lto::Thin) {
425+
SpanData::default()
426+
} else {
427+
let lo = BytePos::from_u32(cookie as u32);
428+
let hi = BytePos::from_u32((cookie >> 32) as u32);
429+
SpanData {
430+
lo,
431+
// LLVM version < 19 silently truncates the cookie to 32 bits in some situations.
432+
hi: if hi.to_u32() != 0 { hi } else { lo },
433+
ctxt: SyntaxContext::root(),
434+
parent: None,
435+
}
436+
};
427437
let level = match level {
428438
llvm::DiagnosticLevel::Error => Level::Error,
429439
llvm::DiagnosticLevel::Warning => Level::Warning,
430440
llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note,
431441
};
432-
cgcx.diag_emitter.inline_asm_error(cookie.try_into().unwrap(), msg, level, source);
442+
let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string();
443+
cgcx.diag_emitter.inline_asm_error(span, msg, level, source);
433444
}
434445

435446
unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) {

compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ impl InlineAsmDiagnostic {
151151
unsafe { SrcMgrDiagnostic::unpack(super::LLVMRustGetSMDiagnostic(di, &mut cookie)) };
152152
InlineAsmDiagnostic {
153153
level: smdiag.level,
154-
cookie: cookie.into(),
154+
cookie,
155155
message: smdiag.message,
156156
source: smdiag.source,
157157
}

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2317,7 +2317,7 @@ unsafe extern "C" {
23172317

23182318
pub fn LLVMRustGetSMDiagnostic<'a>(
23192319
DI: &'a DiagnosticInfo,
2320-
cookie_out: &mut c_uint,
2320+
cookie_out: &mut u64,
23212321
) -> &'a SMDiagnostic;
23222322

23232323
pub fn LLVMRustUnpackSMDiagnostic(

compiler/rustc_codegen_ssa/src/back/write.rs

+8-13
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use rustc_session::config::{
3434
};
3535
use rustc_span::source_map::SourceMap;
3636
use rustc_span::symbol::sym;
37-
use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span};
37+
use rustc_span::{FileName, InnerSpan, Span, SpanData};
3838
use rustc_target::spec::{MergeFunctions, SanitizerSet};
3939
use tracing::debug;
4040

@@ -1837,7 +1837,7 @@ fn spawn_work<'a, B: ExtraBackendMethods>(
18371837

18381838
enum SharedEmitterMessage {
18391839
Diagnostic(Diagnostic),
1840-
InlineAsmError(u32, String, Level, Option<(String, Vec<InnerSpan>)>),
1840+
InlineAsmError(SpanData, String, Level, Option<(String, Vec<InnerSpan>)>),
18411841
Fatal(String),
18421842
}
18431843

@@ -1859,12 +1859,12 @@ impl SharedEmitter {
18591859

18601860
pub fn inline_asm_error(
18611861
&self,
1862-
cookie: u32,
1862+
span: SpanData,
18631863
msg: String,
18641864
level: Level,
18651865
source: Option<(String, Vec<InnerSpan>)>,
18661866
) {
1867-
drop(self.sender.send(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)));
1867+
drop(self.sender.send(SharedEmitterMessage::InlineAsmError(span, msg, level, source)));
18681868
}
18691869

18701870
fn fatal(&self, msg: &str) {
@@ -1953,17 +1953,12 @@ impl SharedEmitterMain {
19531953
dcx.emit_diagnostic(d);
19541954
sess.dcx().abort_if_errors();
19551955
}
1956-
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
1956+
Ok(SharedEmitterMessage::InlineAsmError(span, msg, level, source)) => {
19571957
assert_matches!(level, Level::Error | Level::Warning | Level::Note);
1958-
let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string();
19591958
let mut err = Diag::<()>::new(sess.dcx(), level, msg);
1960-
1961-
// If the cookie is 0 then we don't have span information.
1962-
if cookie != 0 {
1963-
let pos = BytePos::from_u32(cookie);
1964-
let span = Span::with_root_ctxt(pos, pos);
1965-
err.span(span);
1966-
};
1959+
if !span.is_dummy() {
1960+
err.span(span.span());
1961+
}
19671962

19681963
// Point to the generated assembly if it is available.
19691964
if let Some((buffer, spans)) = source {

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1535,7 +1535,7 @@ extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
15351535
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
15361536

15371537
extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(LLVMDiagnosticInfoRef DI,
1538-
unsigned *Cookie) {
1538+
uint64_t *Cookie) {
15391539
llvm::DiagnosticInfoSrcMgr *SM =
15401540
static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
15411541
*Cookie = SM->getLocCookie();

compiler/rustc_span/src/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,12 @@ impl SpanData {
523523
}
524524
}
525525

526+
impl Default for SpanData {
527+
fn default() -> Self {
528+
Self { lo: BytePos(0), hi: BytePos(0), ctxt: SyntaxContext::root(), parent: None }
529+
}
530+
}
531+
526532
impl PartialOrd for Span {
527533
fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
528534
PartialOrd::partial_cmp(&self.data(), &rhs.data())

0 commit comments

Comments
 (0)