diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index daa2fb05280..b644422e795 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -11,7 +11,7 @@ use back::bytecode::{DecodedBytecode, RLIB_BYTECODE_EXTENSION}; use back::symbol_export; use back::write::{ModuleConfig, with_llvm_pmb, CodegenContext}; -use back::write; +use back::write::{self, DiagnosticHandlers}; use errors::{FatalError, Handler}; use llvm::archive_ro::ArchiveRO; use llvm::{True, False}; @@ -234,9 +234,17 @@ fn fat_lto(cgcx: &CodegenContext, let module = modules.remove(costliest_module); let mut serialized_bitcode = Vec::new(); { - let llmod = module.llvm().expect("can't lto pre-codegened modules").llmod(); + let (llcx, llmod) = { + let llvm = module.llvm().expect("can't lto pre-codegened modules"); + (&llvm.llcx, llvm.llmod()) + }; info!("using {:?} as a base module", module.llmod_id); + // The linking steps below may produce errors and diagnostics within LLVM + // which we'd like to handle and print, so set up our diagnostic handlers + // (which get unregistered when they go out of scope below). + let _handler = DiagnosticHandlers::new(cgcx, diag_handler, llcx); + // For all other modules we codegened we'll need to link them into our own // bitcode. All modules were codegened in their own LLVM context, however, // and we want to move everything to the same LLVM context. Currently the diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index db044878fe7..209c3a23c5c 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -397,15 +397,15 @@ impl CodegenContext { } } -struct DiagnosticHandlers<'a> { +pub struct DiagnosticHandlers<'a> { data: *mut (&'a CodegenContext, &'a Handler), llcx: &'a llvm::Context, } impl<'a> DiagnosticHandlers<'a> { - fn new(cgcx: &'a CodegenContext, - handler: &'a Handler, - llcx: &'a llvm::Context) -> Self { + pub fn new(cgcx: &'a CodegenContext, + handler: &'a Handler, + llcx: &'a llvm::Context) -> Self { let data = Box::into_raw(Box::new((cgcx, handler))); unsafe { llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, data as *mut _); @@ -475,10 +475,11 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void opt.message)); } } - llvm::diagnostic::PGO(diagnostic_ref) => { + llvm::diagnostic::PGO(diagnostic_ref) | + llvm::diagnostic::Linker(diagnostic_ref) => { let msg = llvm::build_string(|s| { llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s) - }).expect("non-UTF8 PGO diagnostic"); + }).expect("non-UTF8 diagnostic"); diag_handler.warn(&msg); } llvm::diagnostic::UnknownDiagnostic(..) => {}, diff --git a/src/librustc_codegen_llvm/llvm/diagnostic.rs b/src/librustc_codegen_llvm/llvm/diagnostic.rs index 7f2a9d6984a..c41a5f74ae3 100644 --- a/src/librustc_codegen_llvm/llvm/diagnostic.rs +++ b/src/librustc_codegen_llvm/llvm/diagnostic.rs @@ -126,6 +126,7 @@ pub enum Diagnostic<'ll> { Optimization(OptimizationDiagnostic<'ll>), InlineAsm(InlineAsmDiagnostic<'ll>), PGO(&'ll DiagnosticInfo), + Linker(&'ll DiagnosticInfo), /// LLVM has other types that we do not wrap here. UnknownDiagnostic(&'ll DiagnosticInfo), @@ -168,6 +169,9 @@ impl Diagnostic<'ll> { Dk::PGOProfile => { PGO(di) } + Dk::Linker => { + Linker(di) + } _ => UnknownDiagnostic(di), } diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 898d3d67353..989498ea92b 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -332,6 +332,7 @@ pub enum DiagnosticKind { OptimizationRemarkOther, OptimizationFailure, PGOProfile, + Linker, } /// LLVMRustArchiveKind diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index f2b5297285c..4bcb4fd7ad3 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -984,6 +984,7 @@ enum class LLVMRustDiagnosticKind { OptimizationRemarkOther, OptimizationFailure, PGOProfile, + Linker, }; static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) { @@ -1008,6 +1009,8 @@ static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) { return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing; case DK_PGOProfile: return LLVMRustDiagnosticKind::PGOProfile; + case DK_Linker: + return LLVMRustDiagnosticKind::Linker; default: return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark) ? LLVMRustDiagnosticKind::OptimizationRemarkOther diff --git a/src/test/compile-fail/auxiliary/lto-duplicate-symbols1.rs b/src/test/compile-fail/auxiliary/lto-duplicate-symbols1.rs new file mode 100644 index 00000000000..ea09327bd19 --- /dev/null +++ b/src/test/compile-fail/auxiliary/lto-duplicate-symbols1.rs @@ -0,0 +1,16 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// no-prefer-dynamic + +#![crate_type = "rlib"] + +#[no_mangle] +pub extern fn foo() {} diff --git a/src/test/compile-fail/auxiliary/lto-duplicate-symbols2.rs b/src/test/compile-fail/auxiliary/lto-duplicate-symbols2.rs new file mode 100644 index 00000000000..ea09327bd19 --- /dev/null +++ b/src/test/compile-fail/auxiliary/lto-duplicate-symbols2.rs @@ -0,0 +1,16 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// no-prefer-dynamic + +#![crate_type = "rlib"] + +#[no_mangle] +pub extern fn foo() {} diff --git a/src/test/compile-fail/lto-duplicate-symbols.rs b/src/test/compile-fail/lto-duplicate-symbols.rs new file mode 100644 index 00000000000..9c1dbfc2af9 --- /dev/null +++ b/src/test/compile-fail/lto-duplicate-symbols.rs @@ -0,0 +1,20 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:lto-duplicate-symbols1.rs +// aux-build:lto-duplicate-symbols2.rs +// error-pattern:Linking globals named 'foo': symbol multiply defined! +// compile-flags: -C lto +// no-prefer-dynamic + +extern crate lto_duplicate_symbols1; +extern crate lto_duplicate_symbols2; + +fn main() {}