]> git.lizzy.rs Git - rust.git/commitdiff
rustc: Handle linker diagnostic from LLVM
authorAlex Crichton <alex@alexcrichton.com>
Tue, 17 Jul 2018 23:20:51 +0000 (16:20 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Tue, 31 Jul 2018 17:47:27 +0000 (10:47 -0700)
Previously linker diagnostic were being hidden when two modules were linked
together but failed to link. This commit fixes the situation by ensuring that we
have a diagnostic handler installed and also adds support for handling linker
diagnostics.

src/librustc_codegen_llvm/back/lto.rs
src/librustc_codegen_llvm/back/write.rs
src/librustc_codegen_llvm/llvm/diagnostic.rs
src/librustc_codegen_llvm/llvm/ffi.rs
src/rustllvm/RustWrapper.cpp
src/test/compile-fail/auxiliary/lto-duplicate-symbols1.rs [new file with mode: 0644]
src/test/compile-fail/auxiliary/lto-duplicate-symbols2.rs [new file with mode: 0644]
src/test/compile-fail/lto-duplicate-symbols.rs [new file with mode: 0644]

index daa2fb05280649793a50ac3831c7352cd8b1f5df..b644422e79532a4aba355813fff735f5d2f88a90 100644 (file)
@@ -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
index db044878fe745e194b12d215cc0adc1453337e53..209c3a23c5cc35e1f6a97350825b3d61b4e5bae1 100644 (file)
@@ -397,15 +397,15 @@ pub(crate) fn save_temp_bitcode(&self, module: &ModuleCodegen, name: &str) {
     }
 }
 
-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 @@ fn drop(&mut self) {
                                                 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(..) => {},
index 7f2a9d6984a1577fbca34234f932f2b250e253d7..c41a5f74ae30282a598717aaa843f95fb9c348c9 100644 (file)
@@ -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 @@ pub unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self {
             Dk::PGOProfile => {
                 PGO(di)
             }
+            Dk::Linker => {
+                Linker(di)
+            }
 
             _ => UnknownDiagnostic(di),
         }
index 898d3d67353634b1ece65bfd1e2dd74fea44f9c8..989498ea92bcefd770af80cee557ac8f6741648b 100644 (file)
@@ -332,6 +332,7 @@ pub enum DiagnosticKind {
     OptimizationRemarkOther,
     OptimizationFailure,
     PGOProfile,
+    Linker,
 }
 
 /// LLVMRustArchiveKind
index f2b5297285ca79623d4ccad6e3b13d69625dda09..4bcb4fd7ad385a4ec1c0db8593a65cb578d248e6 100644 (file)
@@ -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 (file)
index 0000000..ea09327
--- /dev/null
@@ -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 <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.
+
+// 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 (file)
index 0000000..ea09327
--- /dev/null
@@ -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 <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.
+
+// 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 (file)
index 0000000..9c1dbfc
--- /dev/null
@@ -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 <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.
+
+// 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() {}