about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-12-12 02:34:06 +0000
committerbors <bors@rust-lang.org>2024-12-12 02:34:06 +0000
commit903d2976fdb6ceeb65526b7555d8d1e6f8c02134 (patch)
treea2cae32f538b4205d39fd07fa877e3bd27f31d89 /compiler/rustc_codegen_llvm/src
parent1daec069fbf562f5ec22c2ab1c6aee3573348858 (diff)
parent68227a3777c7bf8ba6a69e2b8871d224504d1c31 (diff)
downloadrust-903d2976fdb6ceeb65526b7555d8d1e6f8c02134.tar.gz
rust-903d2976fdb6ceeb65526b7555d8d1e6f8c02134.zip
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.
Diffstat (limited to 'compiler/rustc_codegen_llvm/src')
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs21
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs23
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs2
4 files changed, 29 insertions, 19 deletions
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index f257abe2a71..3722d4350a2 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -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);
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index bde6668929c..66ca4e2b473 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -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) {
diff --git a/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
index a4cb5a25d1b..11043b664f5 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
@@ -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,
         }
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index b1ace0033ba..8b4523bd252 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -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(