Pass end position of span through inline ASM cookie

This commit is contained in:
beetrees 2024-08-17 05:32:09 +01:00
parent f2abf827c1
commit 68227a3777
No known key found for this signature in database
GPG key ID: 8791BD754191EBD6
24 changed files with 1565 additions and 200 deletions

View file

@ -504,14 +504,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
@ -521,13 +520,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);

View file

@ -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;
@ -413,21 +413,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) {

View file

@ -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,
}

View file

@ -2316,7 +2316,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(