Skip to content

Commit

Permalink
rustc: Handle linker diagnostic from LLVM
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
alexcrichton committed Jul 31, 2018
1 parent f898179 commit f0bceba
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 8 deletions.
12 changes: 10 additions & 2 deletions src/librustc_codegen_llvm/back/lto.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -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
Expand Down
13 changes: 7 additions & 6 deletions src/librustc_codegen_llvm/back/write.rs
Expand Up @@ -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 _);
Expand Down Expand Up @@ -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(..) => {},
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_codegen_llvm/llvm/diagnostic.rs
Expand Up @@ -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),
Expand Down Expand Up @@ -168,6 +169,9 @@ impl Diagnostic<'ll> {
Dk::PGOProfile => {
PGO(di)
}
Dk::Linker => {
Linker(di)
}

_ => UnknownDiagnostic(di),
}
Expand Down
1 change: 1 addition & 0 deletions src/librustc_codegen_llvm/llvm/ffi.rs
Expand Up @@ -332,6 +332,7 @@ pub enum DiagnosticKind {
OptimizationRemarkOther,
OptimizationFailure,
PGOProfile,
Linker,
}

/// LLVMRustArchiveKind
Expand Down
3 changes: 3 additions & 0 deletions src/rustllvm/RustWrapper.cpp
Expand Up @@ -984,6 +984,7 @@ enum class LLVMRustDiagnosticKind {
OptimizationRemarkOther,
OptimizationFailure,
PGOProfile,
Linker,
};

static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
Expand All @@ -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
Expand Down
16 changes: 16 additions & 0 deletions 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 <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() {}
16 changes: 16 additions & 0 deletions 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 <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() {}
20 changes: 20 additions & 0 deletions 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 <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() {}

0 comments on commit f0bceba

Please sign in to comment.