Skip to content

Commit 78bcfc3

Browse files
committed
Pass end position of span through inline ASM cookie
1 parent 569d7e3 commit 78bcfc3

File tree

18 files changed

+887
-116
lines changed

18 files changed

+887
-116
lines changed

Diff for: compiler/rustc_codegen_llvm/src/asm.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -487,14 +487,11 @@ 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.
498495
let mut srcloc = vec![];
499496
if dia == llvm::AsmDialect::Intel && line_spans.len() > 1 {
500497
// LLVM inserts an extra line to add the ".intel_syntax", so add
@@ -504,9 +501,11 @@ pub(crate) fn inline_asm_call<'ll>(
504501
// due to the asm template string coming from a macro. LLVM will
505502
// default to the first srcloc for lines that don't have an
506503
// associated srcloc.
507-
srcloc.push(bx.const_i32(0));
504+
srcloc.push(bx.const_u64(0));
508505
}
509-
srcloc.extend(line_spans.iter().map(|span| bx.const_i32(span.lo().to_u32() as i32)));
506+
srcloc.extend(line_spans.iter().map(|span| {
507+
bx.const_u64(u64::from(span.lo().to_u32()) | (u64::from(span.hi().to_u32()) << 32))
508+
}));
510509
let md = llvm::LLVMMDNodeInContext(bx.llcx, srcloc.as_ptr(), srcloc.len() as u32);
511510
llvm::LLVMSetMetadata(call, kind, md);
512511

Diff for: compiler/rustc_codegen_llvm/src/back/write.rs

+17-6
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use rustc_session::config::{
2525
};
2626
use rustc_session::Session;
2727
use rustc_span::symbol::sym;
28-
use rustc_span::InnerSpan;
28+
use rustc_span::{BytePos, InnerSpan, Pos, SpanData, SyntaxContext};
2929
use rustc_target::spec::{CodeModel, RelocModel, SanitizerSet, SplitDebuginfo, TlsModel};
3030
use tracing::debug;
3131

@@ -406,21 +406,32 @@ fn report_inline_asm(
406406
cgcx: &CodegenContext<LlvmCodegenBackend>,
407407
msg: String,
408408
level: llvm::DiagnosticLevel,
409-
mut cookie: u64,
409+
cookie: u64,
410410
source: Option<(String, Vec<InnerSpan>)>,
411411
) {
412412
// In LTO build we may get srcloc values from other crates which are invalid
413413
// since they use a different source map. To be safe we just suppress these
414414
// in LTO builds.
415-
if matches!(cgcx.lto, Lto::Fat | Lto::Thin) {
416-
cookie = 0;
417-
}
415+
let span = if cookie == 0 || matches!(cgcx.lto, Lto::Fat | Lto::Thin) {
416+
SpanData::default()
417+
} else {
418+
let lo = BytePos::from_u32(cookie as u32);
419+
let hi = BytePos::from_u32((cookie >> 32) as u32);
420+
// LLVM version < 19 silently truncates the cookie to 32 bits in some situations.
421+
SpanData {
422+
lo,
423+
hi: if hi.to_u32() != 0 { hi } else { lo },
424+
ctxt: SyntaxContext::root(),
425+
parent: None,
426+
}
427+
};
418428
let level = match level {
419429
llvm::DiagnosticLevel::Error => Level::Error,
420430
llvm::DiagnosticLevel::Warning => Level::Warning,
421431
llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note,
422432
};
423-
cgcx.diag_emitter.inline_asm_error(cookie.try_into().unwrap(), msg, level, source);
433+
let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string();
434+
cgcx.diag_emitter.inline_asm_error(span, msg, level, source);
424435
}
425436

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

Diff for: 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
}

Diff for: compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2293,7 +2293,7 @@ extern "C" {
22932293

22942294
pub fn LLVMRustGetSMDiagnostic<'a>(
22952295
DI: &'a DiagnosticInfo,
2296-
cookie_out: &mut c_uint,
2296+
cookie_out: &mut u64,
22972297
) -> &'a SMDiagnostic;
22982298

22992299
#[allow(improper_ctypes)]

Diff for: compiler/rustc_codegen_ssa/src/back/write.rs

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

@@ -1851,7 +1851,7 @@ fn spawn_work<'a, B: ExtraBackendMethods>(
18511851

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

@@ -1873,12 +1873,12 @@ impl SharedEmitter {
18731873

18741874
pub fn inline_asm_error(
18751875
&self,
1876-
cookie: u32,
1876+
span: SpanData,
18771877
msg: String,
18781878
level: Level,
18791879
source: Option<(String, Vec<InnerSpan>)>,
18801880
) {
1881-
drop(self.sender.send(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)));
1881+
drop(self.sender.send(SharedEmitterMessage::InlineAsmError(span, msg, level, source)));
18821882
}
18831883

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

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

Diff for: compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

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

14551455
extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(LLVMDiagnosticInfoRef DI,
1456-
unsigned *Cookie) {
1456+
uint64_t *Cookie) {
14571457
llvm::DiagnosticInfoSrcMgr *SM =
14581458
static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
14591459
*Cookie = SM->getLocCookie();

Diff for: compiler/rustc_span/src/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,12 @@ impl SpanData {
519519
}
520520
}
521521

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

0 commit comments

Comments
 (0)