From 5541f689e9cfc6c1ccdb2277a308bc2e8541ab5e Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 9 Jun 2020 14:37:59 +0100 Subject: [PATCH] Handle assembler warnings properly --- src/librustc_codegen_llvm/back/write.rs | 22 +++++++-- src/librustc_codegen_llvm/llvm/diagnostic.rs | 12 ++++- src/librustc_codegen_llvm/llvm/ffi.rs | 13 ++++++ src/librustc_codegen_ssa/back/write.rs | 20 ++++++--- src/librustc_errors/lib.rs | 5 +++ src/librustc_session/session.rs | 3 ++ src/rustllvm/RustWrapper.cpp | 47 +++++++++++++++++++- src/test/ui/asm/srcloc.rs | 3 ++ src/test/ui/asm/srcloc.stderr | 14 +++++- 9 files changed, 124 insertions(+), 15 deletions(-) diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 02a9294930d2b..26f5334668b8f 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -16,7 +16,7 @@ use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, Mo use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen}; use rustc_data_structures::small_c_str::SmallCStr; -use rustc_errors::{FatalError, Handler}; +use rustc_errors::{FatalError, Handler, Level}; use rustc_fs_util::{link_or_copy, path_to_c_string}; use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::bug; @@ -242,6 +242,7 @@ impl<'a> Drop for DiagnosticHandlers<'a> { fn report_inline_asm( cgcx: &CodegenContext, msg: String, + level: llvm::DiagnosticLevel, mut cookie: c_uint, source: Option<(String, Vec)>, ) { @@ -251,7 +252,12 @@ fn report_inline_asm( if matches!(cgcx.lto, Lto::Fat | Lto::Thin) { cookie = 0; } - cgcx.diag_emitter.inline_asm_error(cookie as u32, msg, source); + 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 as u32, msg, level, source); } unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void, cookie: c_uint) { @@ -264,6 +270,7 @@ unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void // diagnostics. let mut have_source = false; let mut buffer = String::new(); + let mut level = llvm::DiagnosticLevel::Error; let mut loc = 0; let mut ranges = [0; 8]; let mut num_ranges = ranges.len() / 2; @@ -273,6 +280,7 @@ unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void diag, msg, buffer, + &mut level, &mut loc, ranges.as_mut_ptr(), &mut num_ranges, @@ -290,7 +298,7 @@ unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void (buffer, spans) }); - report_inline_asm(cgcx, msg, cookie, source); + report_inline_asm(cgcx, msg, level, cookie, source); } unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) { @@ -301,7 +309,13 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void match llvm::diagnostic::Diagnostic::unpack(info) { llvm::diagnostic::InlineAsm(inline) => { - report_inline_asm(cgcx, llvm::twine_to_string(inline.message), inline.cookie, None); + report_inline_asm( + cgcx, + llvm::twine_to_string(inline.message), + inline.level, + inline.cookie, + None, + ); } llvm::diagnostic::Optimization(opt) => { diff --git a/src/librustc_codegen_llvm/llvm/diagnostic.rs b/src/librustc_codegen_llvm/llvm/diagnostic.rs index 4347cd06532da..47f5c94e70c53 100644 --- a/src/librustc_codegen_llvm/llvm/diagnostic.rs +++ b/src/librustc_codegen_llvm/llvm/diagnostic.rs @@ -88,6 +88,7 @@ impl OptimizationDiagnostic<'ll> { #[derive(Copy, Clone)] pub struct InlineAsmDiagnostic<'ll> { + pub level: super::DiagnosticLevel, pub cookie: c_uint, pub message: &'ll Twine, pub instruction: Option<&'ll Value>, @@ -98,10 +99,17 @@ impl InlineAsmDiagnostic<'ll> { let mut cookie = 0; let mut message = None; let mut instruction = None; + let mut level = super::DiagnosticLevel::Error; - super::LLVMRustUnpackInlineAsmDiagnostic(di, &mut cookie, &mut message, &mut instruction); + super::LLVMRustUnpackInlineAsmDiagnostic( + di, + &mut level, + &mut cookie, + &mut message, + &mut instruction, + ); - InlineAsmDiagnostic { cookie, message: message.unwrap(), instruction } + InlineAsmDiagnostic { level, cookie, message: message.unwrap(), instruction } } } diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 759c2bf1b85f4..3c981af73ab0d 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -489,6 +489,17 @@ pub enum DiagnosticKind { Linker, } +/// LLVMRustDiagnosticLevel +#[derive(Copy, Clone)] +#[repr(C)] +#[allow(dead_code)] // Variants constructed by C++. +pub enum DiagnosticLevel { + Error, + Warning, + Note, + Remark, +} + /// LLVMRustArchiveKind #[derive(Copy, Clone)] #[repr(C)] @@ -2054,6 +2065,7 @@ extern "C" { pub fn LLVMRustUnpackInlineAsmDiagnostic( DI: &'a DiagnosticInfo, + level_out: &mut DiagnosticLevel, cookie_out: &mut c_uint, message_out: &mut Option<&'a Twine>, instruction_out: &mut Option<&'a Value>, @@ -2074,6 +2086,7 @@ extern "C" { d: &SMDiagnostic, message_out: &RustString, buffer_out: &RustString, + level_out: &mut DiagnosticLevel, loc_out: &mut c_uint, ranges_out: *mut c_uint, num_ranges: &mut usize, diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index cb5c95c11fad8..c118e5ebdb72d 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -1551,7 +1551,7 @@ fn spawn_work(cgcx: CodegenContext, work: WorkItem enum SharedEmitterMessage { Diagnostic(Diagnostic), - InlineAsmError(u32, String, Option<(String, Vec)>), + InlineAsmError(u32, String, Level, Option<(String, Vec)>), AbortIfErrors, Fatal(String), } @@ -1576,9 +1576,10 @@ impl SharedEmitter { &self, cookie: u32, msg: String, + level: Level, source: Option<(String, Vec)>, ) { - drop(self.sender.send(SharedEmitterMessage::InlineAsmError(cookie, msg, source))); + drop(self.sender.send(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source))); } pub fn fatal(&self, msg: &str) { @@ -1631,16 +1632,21 @@ impl SharedEmitterMain { } handler.emit_diagnostic(&d); } - Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, source)) => { + Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => { let msg = msg.strip_prefix("error: ").unwrap_or(&msg); + let mut err = match level { + Level::Error => sess.struct_err(&msg), + Level::Warning => sess.struct_warn(&msg), + Level::Note => sess.struct_note_without_error(&msg), + _ => bug!("Invalid inline asm diagnostic level"), + }; + // If the cookie is 0 then we don't have span information. - let mut err = if cookie == 0 { - sess.struct_err(&msg) - } else { + if cookie != 0 { let pos = BytePos::from_u32(cookie); let span = Span::with_root_ctxt(pos, pos); - sess.struct_span_err(span, &msg) + err.set_span(span); }; // Point to the generated assembly if it is available. diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index e4a560e434aaa..7261c638ce013 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -581,6 +581,11 @@ impl Handler { DiagnosticBuilder::new(self, Level::Help, msg) } + /// Construct a builder at the `Note` level with the `msg`. + pub fn struct_note_without_error(&self, msg: &str) -> DiagnosticBuilder<'_> { + DiagnosticBuilder::new(self, Level::Note, msg) + } + pub fn span_fatal(&self, span: impl Into, msg: &str) -> FatalError { self.emit_diag_at_span(Diagnostic::new(Fatal, msg), span); FatalError diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index 048033846a138..06d7d4f14d8f4 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -441,6 +441,9 @@ impl Session { pub fn span_note_without_error>(&self, sp: S, msg: &str) { self.diagnostic().span_note_without_error(sp, msg) } + pub fn struct_note_without_error(&self, msg: &str) -> DiagnosticBuilder<'_> { + self.diagnostic().struct_note_without_error(msg) + } pub fn diagnostic(&self) -> &rustc_errors::Handler { &self.parse_sess.span_diagnostic diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 6fac2662506a1..4704622922af0 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -1094,8 +1094,17 @@ extern "C" void LLVMRustUnpackOptimizationDiagnostic( MessageOS << Opt->getMsg(); } +enum class LLVMRustDiagnosticLevel { + Error, + Warning, + Note, + Remark, +}; + extern "C" void -LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI, unsigned *CookieOut, +LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI, + LLVMRustDiagnosticLevel *LevelOut, + unsigned *CookieOut, LLVMTwineRef *MessageOut, LLVMValueRef *InstructionOut) { // Undefined to call this not on an inline assembly diagnostic! @@ -1105,6 +1114,23 @@ LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI, unsigned *CookieOut, *CookieOut = IA->getLocCookie(); *MessageOut = wrap(&IA->getMsgStr()); *InstructionOut = wrap(IA->getInstruction()); + + switch (IA->getSeverity()) { + case DS_Error: + *LevelOut = LLVMRustDiagnosticLevel::Error; + break; + case DS_Warning: + *LevelOut = LLVMRustDiagnosticLevel::Warning; + break; + case DS_Note: + *LevelOut = LLVMRustDiagnosticLevel::Note; + break; + case DS_Remark: + *LevelOut = LLVMRustDiagnosticLevel::Remark; + break; + default: + report_fatal_error("Invalid LLVMRustDiagnosticLevel value!"); + } } extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI, @@ -1166,6 +1192,7 @@ extern "C" LLVMRustDiagnosticKind LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) { return toRust((DiagnosticKind)unwrap(DI)->getKind()); } + // This is kept distinct from LLVMGetTypeKind, because when // a new type kind is added, the Rust-side enum must be // updated or UB will result. @@ -1219,6 +1246,7 @@ extern "C" void LLVMRustSetInlineAsmDiagnosticHandler( extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, RustStringRef MessageOut, RustStringRef BufferOut, + LLVMRustDiagnosticLevel* LevelOut, unsigned* LocOut, unsigned* RangesOut, size_t* NumRanges) { @@ -1226,6 +1254,23 @@ extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, RawRustStringOstream MessageOS(MessageOut); MessageOS << D.getMessage(); + switch (D.getKind()) { + case SourceMgr::DK_Error: + *LevelOut = LLVMRustDiagnosticLevel::Error; + break; + case SourceMgr::DK_Warning: + *LevelOut = LLVMRustDiagnosticLevel::Warning; + break; + case SourceMgr::DK_Note: + *LevelOut = LLVMRustDiagnosticLevel::Note; + break; + case SourceMgr::DK_Remark: + *LevelOut = LLVMRustDiagnosticLevel::Remark; + break; + default: + report_fatal_error("Invalid LLVMRustDiagnosticLevel value!"); + } + if (D.getLoc() == SMLoc()) return false; diff --git a/src/test/ui/asm/srcloc.rs b/src/test/ui/asm/srcloc.rs index 7af6f620a9858..402adc50d5b44 100644 --- a/src/test/ui/asm/srcloc.rs +++ b/src/test/ui/asm/srcloc.rs @@ -37,5 +37,8 @@ fn main() { asm!(concat!("invalid", "_", "instruction")); //~^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + asm!("movaps %xmm3, (%esi, 2)", options(att_syntax)); + //~^ WARN: scale factor without index register is ignored } } diff --git a/src/test/ui/asm/srcloc.stderr b/src/test/ui/asm/srcloc.stderr index 57a4fbb974228..d5d12b004816f 100644 --- a/src/test/ui/asm/srcloc.stderr +++ b/src/test/ui/asm/srcloc.stderr @@ -70,5 +70,17 @@ note: instantiated into assembly here LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +warning: scale factor without index register is ignored + --> $DIR/srcloc.rs:41:15 + | +LL | asm!("movaps %xmm3, (%esi, 2)", options(att_syntax)); + | ^ + | +note: instantiated into assembly here + --> :1:23 + | +LL | movaps %xmm3, (%esi, 2) + | ^ + +error: aborting due to 6 previous errors; 1 warning emitted