diff --git a/src/librustc_llvm/diagnostic.rs b/src/librustc_llvm/diagnostic.rs index db2a569cdef..5d0ae9d1f92 100644 --- a/src/librustc_llvm/diagnostic.rs +++ b/src/librustc_llvm/diagnostic.rs @@ -13,7 +13,7 @@ pub use self::OptimizationDiagnosticKind::*; pub use self::Diagnostic::*; -use libc::c_char; +use libc::{c_char, c_uint}; use std::ptr; use {ValueRef, TwineRef, DebugLocRef, DiagnosticInfoRef}; @@ -69,9 +69,37 @@ impl OptimizationDiagnostic { } } +pub struct InlineAsmDiagnostic { + pub cookie: c_uint, + pub message: TwineRef, + pub instruction: ValueRef, +} + +impl Copy for InlineAsmDiagnostic {} + +impl InlineAsmDiagnostic { + unsafe fn unpack(di: DiagnosticInfoRef) + -> InlineAsmDiagnostic { + + let mut opt = InlineAsmDiagnostic { + cookie: 0, + message: ptr::null_mut(), + instruction: ptr::null_mut(), + }; + + super::LLVMUnpackInlineAsmDiagnostic(di, + &mut opt.cookie, + &mut opt.message, + &mut opt.instruction); + + opt + } +} + #[derive(Copy)] pub enum Diagnostic { Optimization(OptimizationDiagnostic), + InlineAsm(InlineAsmDiagnostic), /// LLVM has other types that we do not wrap here. UnknownDiagnostic(DiagnosticInfoRef), @@ -82,6 +110,9 @@ impl Diagnostic { let kind = super::LLVMGetDiagInfoKind(di); match kind { + super::DK_InlineAsm + => InlineAsm(InlineAsmDiagnostic::unpack(di)), + super::DK_OptimizationRemark => Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di)), diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index eded88bb62e..8c651cf839b 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -2049,6 +2049,10 @@ extern { function_out: *mut ValueRef, debugloc_out: *mut DebugLocRef, message_out: *mut TwineRef); + pub fn LLVMUnpackInlineAsmDiagnostic(DI: DiagnosticInfoRef, + cookie_out: *mut c_uint, + message_out: *mut TwineRef, + instruction_out: *mut ValueRef); pub fn LLVMWriteDiagnosticInfoToString(DI: DiagnosticInfoRef, s: RustStringRef); pub fn LLVMGetDiagInfoSeverity(DI: DiagnosticInfoRef) -> DiagnosticSeverity; diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index b07c2060e69..5e48ce384be 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -336,30 +336,36 @@ struct HandlerFreeVars<'a> { cgcx: &'a CodegenContext<'a>, } +unsafe extern "C" fn report_inline_asm<'a, 'b>(cgcx: &'a CodegenContext<'a>, + msg: &'b str, + cookie: c_uint) { + use syntax::codemap::ExpnId; + + match cgcx.lto_ctxt { + Some((sess, _)) => { + sess.codemap().with_expn_info(ExpnId::from_llvm_cookie(cookie), |info| match info { + Some(ei) => sess.span_err(ei.call_site, msg), + None => sess.err(msg), + }); + } + + None => { + cgcx.handler.err(msg); + cgcx.handler.note("build without -C codegen-units for more exact errors"); + } + } +} + unsafe extern "C" fn inline_asm_handler(diag: SMDiagnosticRef, user: *const c_void, cookie: c_uint) { - use syntax::codemap::ExpnId; - let HandlerFreeVars { cgcx, .. } = *mem::transmute::<_, *const HandlerFreeVars>(user); let msg = llvm::build_string(|s| llvm::LLVMWriteSMDiagnosticToString(diag, s)) .expect("non-UTF8 SMDiagnostic"); - match cgcx.lto_ctxt { - Some((sess, _)) => { - sess.codemap().with_expn_info(ExpnId::from_llvm_cookie(cookie), |info| match info { - Some(ei) => sess.span_err(ei.call_site, &msg[]), - None => sess.err(&msg[]), - }); - } - - None => { - cgcx.handler.err(&msg[]); - cgcx.handler.note("build without -C codegen-units for more exact errors"); - } - } + report_inline_asm(cgcx, &msg[], cookie); } unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_void) { @@ -367,6 +373,12 @@ unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_vo = *mem::transmute::<_, *const HandlerFreeVars>(user); match llvm::diagnostic::Diagnostic::unpack(info) { + llvm::diagnostic::InlineAsm(inline) => { + report_inline_asm(cgcx, + llvm::twine_to_string(inline.message).as_slice(), + inline.cookie); + } + llvm::diagnostic::Optimization(opt) => { let pass_name = str::from_utf8(ffi::c_str_to_bytes(&opt.pass_name)) .ok() @@ -407,10 +419,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, let fv = &fv as *const HandlerFreeVars as *mut c_void; llvm::LLVMSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, fv); - - if !cgcx.remark.is_empty() { - llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, fv); - } + llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, fv); if config.emit_no_opt_bc { let ext = format!("{}.no-opt.bc", name_extra); diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index bce73a27699..728ff1461fc 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -894,6 +894,22 @@ LLVMUnpackOptimizationDiagnostic( *message_out = wrap(&opt->getMsg()); } +extern "C" void +LLVMUnpackInlineAsmDiagnostic( + LLVMDiagnosticInfoRef di, + unsigned *cookie_out, + LLVMTwineRef *message_out, + LLVMValueRef *instruction_out) +{ + // Undefined to call this not on an inline assembly diagnostic! + llvm::DiagnosticInfoInlineAsm *ia + = static_cast(unwrap(di)); + + *cookie_out = ia->getLocCookie(); + *message_out = wrap(&ia->getMsgStr()); + *instruction_out = wrap(ia->getInstruction()); +} + extern "C" void LLVMWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef di, RustStringRef str) { raw_rust_string_ostream os(str); DiagnosticPrinterRawOStream dp(os);