Auto merge of #21518 - Zoxc:asm-err, r=luqmana

Before:
```
error: invalid operand for inline asm constraint 'i' at line 11
```
Note that 11 is not the line the inline assembly appears in.

After:
```
src/arch/x64/multiboot/bootstrap.rs:203:5: 209:9 error: invalid operand for inline asm constraint 'i'
src/arch/x64/multiboot/bootstrap.rs:203     asm! {
src/arch/x64/multiboot/bootstrap.rs:204         [multiboot => %ecx, mod attsyntax]
src/arch/x64/multiboot/bootstrap.rs:205 
src/arch/x64/multiboot/bootstrap.rs:206         ljmp {size_of::<Descriptor>() => %i}, $bootstrap.64
src/arch/x64/multiboot/bootstrap.rs:207     }
src/arch/x64/multiboot/bootstrap.rs:208 
                                        ...
error: aborting due to previous error
```
This commit is contained in:
bors 2015-01-25 16:09:48 +00:00
commit d15192317a
4 changed files with 80 additions and 20 deletions

View File

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

View File

@ -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;

View File

@ -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);

View File

@ -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<llvm::DiagnosticInfoInlineAsm*>(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);