Skip to content

Commit c9795bd

Browse files
authored
Rollup merge of #129181 - beetrees:asm-spans, r=pnkfelix
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 0037048 + 29ae617 commit c9795bd

File tree

17 files changed

+874
-103
lines changed

17 files changed

+874
-103
lines changed

compiler/rustc_codegen_llvm/src/asm.rs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -487,14 +487,13 @@ pub(crate) fn inline_asm_call<'ll>(
487487
let key = "srcloc";
488488
let kind = llvm::LLVMGetMDKindIDInContext(
489489
bx.llcx,
490-
key.as_ptr() as *const c_char,
490+
key.as_ptr().cast::<c_char>(),
491491
key.len() as c_uint,
492492
);
493493

494-
// srcloc contains one integer for each line of assembly code.
495-
// Unfortunately this isn't enough to encode a full span so instead
496-
// we just encode the start position of each line.
497-
// FIXME: Figure out a way to pass the entire line spans.
494+
// `srcloc` contains one 64-bit integer for each line of assembly code,
495+
// where the lower 32 bits hold the lo byte position and the upper 32 bits
496+
// hold the hi byte position.
498497
let mut srcloc = vec![];
499498
if dia == llvm::AsmDialect::Intel && line_spans.len() > 1 {
500499
// LLVM inserts an extra line to add the ".intel_syntax", so add
@@ -504,13 +503,13 @@ pub(crate) fn inline_asm_call<'ll>(
504503
// due to the asm template string coming from a macro. LLVM will
505504
// default to the first srcloc for lines that don't have an
506505
// associated srcloc.
507-
srcloc.push(llvm::LLVMValueAsMetadata(bx.const_i32(0)));
506+
srcloc.push(llvm::LLVMValueAsMetadata(bx.const_u64(0)));
508507
}
509-
srcloc.extend(
510-
line_spans
511-
.iter()
512-
.map(|span| llvm::LLVMValueAsMetadata(bx.const_i32(span.lo().to_u32() as i32))),
513-
);
508+
srcloc.extend(line_spans.iter().map(|span| {
509+
llvm::LLVMValueAsMetadata(bx.const_u64(
510+
u64::from(span.lo().to_u32()) | (u64::from(span.hi().to_u32()) << 32),
511+
))
512+
}));
514513
let md = llvm::LLVMMDNodeInContext2(bx.llcx, srcloc.as_ptr(), srcloc.len());
515514
let md = llvm::LLVMMetadataAsValue(&bx.llcx, md);
516515
llvm::LLVMSetMetadata(call, kind, md);

compiler/rustc_codegen_llvm/src/back/write.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ use rustc_session::Session;
2424
use rustc_session::config::{
2525
self, Lto, OutputType, Passes, RemapPathScopeComponents, SplitDwarfKind, SwitchWithOptPath,
2626
};
27-
use rustc_span::InnerSpan;
2827
use rustc_span::symbol::sym;
28+
use rustc_span::{BytePos, InnerSpan, Pos, SpanData, SyntaxContext};
2929
use rustc_target::spec::{CodeModel, RelocModel, SanitizerSet, SplitDebuginfo, TlsModel};
3030
use tracing::debug;
3131

@@ -411,21 +411,32 @@ fn report_inline_asm(
411411
cgcx: &CodegenContext<LlvmCodegenBackend>,
412412
msg: String,
413413
level: llvm::DiagnosticLevel,
414-
mut cookie: u64,
414+
cookie: u64,
415415
source: Option<(String, Vec<InnerSpan>)>,
416416
) {
417417
// In LTO build we may get srcloc values from other crates which are invalid
418418
// since they use a different source map. To be safe we just suppress these
419419
// in LTO builds.
420-
if matches!(cgcx.lto, Lto::Fat | Lto::Thin) {
421-
cookie = 0;
422-
}
420+
let span = if cookie == 0 || matches!(cgcx.lto, Lto::Fat | Lto::Thin) {
421+
SpanData::default()
422+
} else {
423+
let lo = BytePos::from_u32(cookie as u32);
424+
let hi = BytePos::from_u32((cookie >> 32) as u32);
425+
SpanData {
426+
lo,
427+
// LLVM version < 19 silently truncates the cookie to 32 bits in some situations.
428+
hi: if hi.to_u32() != 0 { hi } else { lo },
429+
ctxt: SyntaxContext::root(),
430+
parent: None,
431+
}
432+
};
423433
let level = match level {
424434
llvm::DiagnosticLevel::Error => Level::Error,
425435
llvm::DiagnosticLevel::Warning => Level::Warning,
426436
llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note,
427437
};
428-
cgcx.diag_emitter.inline_asm_error(cookie.try_into().unwrap(), msg, level, source);
438+
let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string();
439+
cgcx.diag_emitter.inline_asm_error(span, msg, level, source);
429440
}
430441

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

compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2271,7 +2271,7 @@ unsafe extern "C" {
22712271

22722272
pub fn LLVMRustGetSMDiagnostic<'a>(
22732273
DI: &'a DiagnosticInfo,
2274-
cookie_out: &mut c_uint,
2274+
cookie_out: &mut u64,
22752275
) -> &'a SMDiagnostic;
22762276

22772277
#[allow(improper_ctypes)]

compiler/rustc_codegen_ssa/src/back/write.rs

Lines changed: 8 additions & 13 deletions
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

@@ -1852,7 +1852,7 @@ fn spawn_work<'a, B: ExtraBackendMethods>(
18521852

18531853
enum SharedEmitterMessage {
18541854
Diagnostic(Diagnostic),
1855-
InlineAsmError(u32, String, Level, Option<(String, Vec<InnerSpan>)>),
1855+
InlineAsmError(SpanData, String, Level, Option<(String, Vec<InnerSpan>)>),
18561856
Fatal(String),
18571857
}
18581858

@@ -1874,12 +1874,12 @@ impl SharedEmitter {
18741874

18751875
pub fn inline_asm_error(
18761876
&self,
1877-
cookie: u32,
1877+
span: SpanData,
18781878
msg: String,
18791879
level: Level,
18801880
source: Option<(String, Vec<InnerSpan>)>,
18811881
) {
1882-
drop(self.sender.send(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)));
1882+
drop(self.sender.send(SharedEmitterMessage::InlineAsmError(span, msg, level, source)));
18831883
}
18841884

18851885
fn fatal(&self, msg: &str) {
@@ -1964,17 +1964,12 @@ impl SharedEmitterMain {
19641964
dcx.emit_diagnostic(d);
19651965
sess.dcx().abort_if_errors();
19661966
}
1967-
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
1967+
Ok(SharedEmitterMessage::InlineAsmError(span, msg, level, source)) => {
19681968
assert_matches!(level, Level::Error | Level::Warning | Level::Note);
1969-
let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string();
19701969
let mut err = Diag::<()>::new(sess.dcx(), level, msg);
1971-
1972-
// If the cookie is 0 then we don't have span information.
1973-
if cookie != 0 {
1974-
let pos = BytePos::from_u32(cookie);
1975-
let span = Span::with_root_ctxt(pos, pos);
1976-
err.span(span);
1977-
};
1970+
if !span.is_dummy() {
1971+
err.span(span.span());
1972+
}
19781973

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

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1445,7 +1445,7 @@ extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
14451445
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
14461446

14471447
extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(LLVMDiagnosticInfoRef DI,
1448-
unsigned *Cookie) {
1448+
uint64_t *Cookie) {
14491449
llvm::DiagnosticInfoSrcMgr *SM =
14501450
static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
14511451
*Cookie = SM->getLocCookie();

compiler/rustc_span/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,12 @@ impl SpanData {
521521
}
522522
}
523523

524+
impl Default for SpanData {
525+
fn default() -> Self {
526+
Self { lo: BytePos(0), hi: BytePos(0), ctxt: SyntaxContext::root(), parent: None }
527+
}
528+
}
529+
524530
// The interner is pointed to by a thread local value which is only set on the main thread
525531
// with parallelization is disabled. So we don't allow `Span` to transfer between threads
526532
// to avoid panics and other errors, even though it would be memory safe to do so.

0 commit comments

Comments
 (0)