Skip to content

Commit 68227a3

Browse files
committed
Pass end position of span through inline ASM cookie
1 parent f2abf82 commit 68227a3

24 files changed

+1565
-200
lines changed

compiler/rustc_codegen_llvm/src/asm.rs

+10-11
Original file line numberDiff line numberDiff line change
@@ -504,14 +504,13 @@ pub(crate) fn inline_asm_call<'ll>(
504504
let key = "srcloc";
505505
let kind = llvm::LLVMGetMDKindIDInContext(
506506
bx.llcx,
507-
key.as_ptr() as *const c_char,
507+
key.as_ptr().cast::<c_char>(),
508508
key.len() as c_uint,
509509
);
510510

511-
// srcloc contains one integer for each line of assembly code.
512-
// Unfortunately this isn't enough to encode a full span so instead
513-
// we just encode the start position of each line.
514-
// FIXME: Figure out a way to pass the entire line spans.
511+
// `srcloc` contains one 64-bit integer for each line of assembly code,
512+
// where the lower 32 bits hold the lo byte position and the upper 32 bits
513+
// hold the hi byte position.
515514
let mut srcloc = vec![];
516515
if dia == llvm::AsmDialect::Intel && line_spans.len() > 1 {
517516
// LLVM inserts an extra line to add the ".intel_syntax", so add
@@ -521,13 +520,13 @@ pub(crate) fn inline_asm_call<'ll>(
521520
// due to the asm template string coming from a macro. LLVM will
522521
// default to the first srcloc for lines that don't have an
523522
// associated srcloc.
524-
srcloc.push(llvm::LLVMValueAsMetadata(bx.const_i32(0)));
523+
srcloc.push(llvm::LLVMValueAsMetadata(bx.const_u64(0)));
525524
}
526-
srcloc.extend(
527-
line_spans
528-
.iter()
529-
.map(|span| llvm::LLVMValueAsMetadata(bx.const_i32(span.lo().to_u32() as i32))),
530-
);
525+
srcloc.extend(line_spans.iter().map(|span| {
526+
llvm::LLVMValueAsMetadata(bx.const_u64(
527+
u64::from(span.lo().to_u32()) | (u64::from(span.hi().to_u32()) << 32),
528+
))
529+
}));
531530
let md = llvm::LLVMMDNodeInContext2(bx.llcx, srcloc.as_ptr(), srcloc.len());
532531
let md = llvm::LLVMMetadataAsValue(&bx.llcx, md);
533532
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

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

433444
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
@@ -2316,7 +2316,7 @@ unsafe extern "C" {
23162316

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

23222322
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) {
@@ -1949,17 +1949,12 @@ impl SharedEmitterMain {
19491949
dcx.emit_diagnostic(d);
19501950
sess.dcx().abort_if_errors();
19511951
}
1952-
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
1952+
Ok(SharedEmitterMessage::InlineAsmError(span, msg, level, source)) => {
19531953
assert_matches!(level, Level::Error | Level::Warning | Level::Note);
1954-
let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string();
19551954
let mut err = Diag::<()>::new(sess.dcx(), level, msg);
1956-
1957-
// If the cookie is 0 then we don't have span information.
1958-
if cookie != 0 {
1959-
let pos = BytePos::from_u32(cookie);
1960-
let span = Span::with_root_ctxt(pos, pos);
1961-
err.span(span);
1962-
};
1955+
if !span.is_dummy() {
1956+
err.span(span.span());
1957+
}
19631958

19641959
// Point to the generated assembly if it is available.
19651960
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
@@ -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
impl PartialOrd for Span {
525531
fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
526532
PartialOrd::partial_cmp(&self.data(), &rhs.data())

0 commit comments

Comments
 (0)