diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/back/write.rs | 43 | ||||
| -rw-r--r-- | src/librustc/driver/driver.rs | 2 | ||||
| -rw-r--r-- | src/librustc/middle/trans/asm.rs | 14 | ||||
| -rw-r--r-- | src/librustc_llvm/lib.rs | 9 | ||||
| -rw-r--r-- | src/libsyntax/ast.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/codemap.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ext/asm.rs | 13 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 6 | ||||
| -rw-r--r-- | src/rustllvm/RustWrapper.cpp | 15 | ||||
| -rw-r--r-- | src/rustllvm/rustllvm.h | 1 | ||||
| -rw-r--r-- | src/test/compile-fail/asm-src-loc-codegen-units.rs | 20 | ||||
| -rw-r--r-- | src/test/compile-fail/asm-src-loc.rs | 17 |
12 files changed, 133 insertions, 12 deletions
diff --git a/src/librustc/back/write.rs b/src/librustc/back/write.rs index 7242c12ae0c..8e703d954f3 100644 --- a/src/librustc/back/write.rs +++ b/src/librustc/back/write.rs @@ -16,6 +16,7 @@ use driver::session::Session; use driver::config; use llvm; use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef, ContextRef}; +use llvm::SMDiagnosticRef; use util::common::time; use syntax::abi; use syntax::codemap; @@ -326,14 +327,40 @@ impl<'a> CodegenContext<'a> { } } -struct DiagHandlerFreeVars<'a> { +struct HandlerFreeVars<'a> { llcx: ContextRef, cgcx: &'a CodegenContext<'a>, } +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(cookie as u32), |info| match info { + Some(ei) => sess.span_err(ei.call_site, msg.as_slice()), + None => sess.err(msg.as_slice()), + }); + } + + None => { + cgcx.handler.err(msg.as_slice()); + cgcx.handler.note("build without -C codegen-units for more exact errors"); + } + } +} + unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_void) { - let DiagHandlerFreeVars { llcx, cgcx } - = *mem::transmute::<_, *const DiagHandlerFreeVars>(user); + let HandlerFreeVars { llcx, cgcx } + = *mem::transmute::<_, *const HandlerFreeVars>(user); match llvm::diagnostic::Diagnostic::unpack(info) { llvm::diagnostic::Optimization(opt) => { @@ -368,14 +395,16 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, let tm = config.tm; // llcx doesn't outlive this function, so we can put this on the stack. - let fv = DiagHandlerFreeVars { + let fv = HandlerFreeVars { llcx: llcx, cgcx: cgcx, }; + 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 as *const DiagHandlerFreeVars - as *mut c_void); + llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, fv); } if config.emit_no_opt_bc { diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 33e6579fb87..b0b445b590c 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -556,6 +556,8 @@ pub fn phase_5_run_llvm_passes(sess: &Session, sess.opts.output_types.as_slice(), outputs)); } + + sess.abort_if_errors(); } /// Run the linker on any artifacts that resulted from the LLVM run. diff --git a/src/librustc/middle/trans/asm.rs b/src/librustc/middle/trans/asm.rs index a5e6d606d7b..b4c10c78db8 100644 --- a/src/librustc/middle/trans/asm.rs +++ b/src/librustc/middle/trans/asm.rs @@ -25,6 +25,7 @@ use middle::trans::type_::Type; use std::c_str::ToCStr; use std::string::String; use syntax::ast; +use libc::{c_uint, c_char}; // Take an inline assembly expression and splat it out via LLVM pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm) @@ -141,6 +142,19 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm) } } + // Store expn_id in a metadata node so we can map LLVM errors + // back to source locations. See #17552. + unsafe { + let key = "srcloc"; + let kind = llvm::LLVMGetMDKindIDInContext(bcx.ccx().llcx(), + key.as_ptr() as *const c_char, key.len() as c_uint); + + let val: llvm::ValueRef = C_i32(bcx.ccx(), ia.expn_id as i32); + + llvm::LLVMSetMetadata(r, kind, + llvm::LLVMMDNodeInContext(bcx.ccx().llcx(), &val, 1)); + } + return bcx; } diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index c25ef2ca63a..401933d7058 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -424,8 +424,11 @@ pub enum DiagnosticInfo_opaque {} pub type DiagnosticInfoRef = *mut DiagnosticInfo_opaque; pub enum DebugLoc_opaque {} pub type DebugLocRef = *mut DebugLoc_opaque; +pub enum SMDiagnostic_opaque {} +pub type SMDiagnosticRef = *mut SMDiagnostic_opaque; pub type DiagnosticHandler = unsafe extern "C" fn(DiagnosticInfoRef, *mut c_void); +pub type InlineAsmDiagHandler = unsafe extern "C" fn(SMDiagnosticRef, *const c_void, c_uint); pub mod debuginfo { use super::{ValueRef}; @@ -1967,6 +1970,12 @@ extern { pub fn LLVMGetDiagInfoKind(DI: DiagnosticInfoRef) -> DiagnosticKind; pub fn LLVMWriteDebugLocToString(C: ContextRef, DL: DebugLocRef, s: RustStringRef); + + pub fn LLVMSetInlineAsmDiagnosticHandler(C: ContextRef, + H: InlineAsmDiagHandler, + CX: *mut c_void); + + pub fn LLVMWriteSMDiagnosticToString(d: SMDiagnosticRef, s: RustStringRef); } pub fn SetInstructionCallConv(instr: ValueRef, cc: CallConv) { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 38d8136c1a1..43d6b9b9e90 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -983,7 +983,8 @@ pub struct InlineAsm { pub clobbers: InternedString, pub volatile: bool, pub alignstack: bool, - pub dialect: AsmDialect + pub dialect: AsmDialect, + pub expn_id: u32, } /// represents an argument in a function header diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 9072889463c..d44de7862a3 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -224,7 +224,7 @@ pub struct ExpnInfo { } #[deriving(PartialEq, Eq, Clone, Show, Hash)] -pub struct ExpnId(u32); +pub struct ExpnId(pub u32); pub static NO_EXPANSION: ExpnId = ExpnId(-1); diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs index 4b8c3376cad..f82fe4b13a2 100644 --- a/src/libsyntax/ext/asm.rs +++ b/src/libsyntax/ext/asm.rs @@ -13,6 +13,7 @@ */ use ast; +use codemap; use codemap::Span; use ext::base; use ext::base::*; @@ -198,6 +199,15 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) } } + let codemap::ExpnId(expn_id) = cx.codemap().record_expansion(codemap::ExpnInfo { + call_site: sp, + callee: codemap::NameAndSpan { + name: "asm".to_string(), + format: codemap::MacroBang, + span: None, + }, + }); + MacExpr::new(P(ast::Expr { id: ast::DUMMY_NODE_ID, node: ast::ExprInlineAsm(ast::InlineAsm { @@ -208,7 +218,8 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) clobbers: token::intern_and_get_ident(cons.as_slice()), volatile: volatile, alignstack: alignstack, - dialect: dialect + dialect: dialect, + expn_id: expn_id, }), span: sp })) diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 91a339a73f7..53be7f2c20c 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1279,7 +1279,8 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) -> clobbers, volatile, alignstack, - dialect + dialect, + expn_id, }) => ExprInlineAsm(InlineAsm { inputs: inputs.move_map(|(c, input)| { (c, folder.fold_expr(input)) @@ -1292,7 +1293,8 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) -> clobbers: clobbers, volatile: volatile, alignstack: alignstack, - dialect: dialect + dialect: dialect, + expn_id: expn_id, }), ExprMac(mac) => ExprMac(folder.fold_mac(mac)), ExprStruct(path, fields, maybe_expr) => { diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 7896ce2ba76..1fdaa548ebe 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -871,3 +871,18 @@ extern "C" void LLVMWriteDebugLocToString( raw_rust_string_ostream os(str); unwrap(dl)->print(*unwrap(C), os); } + +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef) + +extern "C" void LLVMSetInlineAsmDiagnosticHandler( + LLVMContextRef C, + LLVMContext::InlineAsmDiagHandlerTy H, + void *CX) +{ + unwrap(C)->setInlineAsmDiagnosticHandler(H, CX); +} + +extern "C" void LLVMWriteSMDiagnosticToString(LLVMSMDiagnosticRef d, RustStringRef str) { + raw_rust_string_ostream os(str); + unwrap(d)->print("", os); +} diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h index 54b0c2506c7..5469531c541 100644 --- a/src/rustllvm/rustllvm.h +++ b/src/rustllvm/rustllvm.h @@ -73,6 +73,7 @@ void LLVMRustSetLastError(const char*); typedef struct OpaqueRustString *RustStringRef; typedef struct LLVMOpaqueTwine *LLVMTwineRef; typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef; +typedef struct LLVMOpaqueSMDiagnostic *LLVMSMDiagnosticRef; extern "C" void rust_llvm_string_write_impl(RustStringRef str, const char *ptr, size_t size); diff --git a/src/test/compile-fail/asm-src-loc-codegen-units.rs b/src/test/compile-fail/asm-src-loc-codegen-units.rs new file mode 100644 index 00000000000..1b8fb32a808 --- /dev/null +++ b/src/test/compile-fail/asm-src-loc-codegen-units.rs @@ -0,0 +1,20 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// compile-flags: -C codegen-units=2 +// error-pattern: build without -C codegen-units for more exact errors + +#![feature(asm)] + +fn main() { + unsafe { + asm!("nowayisthisavalidinstruction"); + } +} diff --git a/src/test/compile-fail/asm-src-loc.rs b/src/test/compile-fail/asm-src-loc.rs new file mode 100644 index 00000000000..8da6cca77cc --- /dev/null +++ b/src/test/compile-fail/asm-src-loc.rs @@ -0,0 +1,17 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(asm)] + +fn main() { + unsafe { + asm!("nowayisthisavalidinstruction"); //~ ERROR invalid instruction mnemonic + } +} |
