-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Apply some fixes to cross-language LTO (especially when targeting MSVC) #53031
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d5f8edf
3a3b331
aa9eeff
54fba3a
386e000
3742f4d
f2969ed
b27a161
3a70050
49972e9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -552,7 +552,8 @@ unsafe fn optimize(cgcx: &CodegenContext, | |
llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod); | ||
llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod); | ||
let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None); | ||
let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal; | ||
let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal || | ||
(cgcx.lto != Lto::Fat && cgcx.opts.debugging_opts.cross_lang_lto.enabled()); | ||
have_name_anon_globals_pass = have_name_anon_globals_pass || prepare_for_thin_lto; | ||
if using_thin_buffers && !prepare_for_thin_lto { | ||
assert!(addpass("name-anon-globals")); | ||
|
@@ -1351,6 +1352,8 @@ fn execute_work_item(cgcx: &CodegenContext, | |
unsafe { | ||
optimize(cgcx, &diag_handler, &module, config, timeline)?; | ||
|
||
let linker_does_lto = cgcx.opts.debugging_opts.cross_lang_lto.enabled(); | ||
|
||
// After we've done the initial round of optimizations we need to | ||
// decide whether to synchronously codegen this module or ship it | ||
// back to the coordinator thread for further LTO processing (which | ||
|
@@ -1361,6 +1364,11 @@ fn execute_work_item(cgcx: &CodegenContext, | |
let needs_lto = match cgcx.lto { | ||
Lto::No => false, | ||
|
||
// If the linker does LTO, we don't have to do it. Note that we | ||
// keep doing full LTO, if it is requested, as not to break the | ||
// assumption that the output will be a single module. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To confirm, this is a rustc bug, right? This is fixable on our end where fat LTO plus cross-lang-lto shouldn't actually run the LTO passes in rustc? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it probably isn't too hard to do just the module merging but not the optimizations. Maybe in another PR, unless you think it's urgent. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh nah definitely fine to happen later, just wanted to make sure I understood! |
||
Lto::Thin | Lto::ThinLocal if linker_does_lto => false, | ||
|
||
// Here we've got a full crate graph LTO requested. We ignore | ||
// this, however, if the crate type is only an rlib as there's | ||
// no full crate graph to process, that'll happen later. | ||
|
@@ -1391,11 +1399,6 @@ fn execute_work_item(cgcx: &CodegenContext, | |
// settings. | ||
let needs_lto = needs_lto && module.kind != ModuleKind::Metadata; | ||
|
||
// Don't run LTO passes when cross-lang LTO is enabled. The linker | ||
// will do that for us in this case. | ||
let needs_lto = needs_lto && | ||
!cgcx.opts.debugging_opts.cross_lang_lto.enabled(); | ||
|
||
if needs_lto { | ||
Ok(WorkItemResult::NeedsLTO(module)) | ||
} else { | ||
|
@@ -2375,8 +2378,18 @@ pub(crate) fn submit_codegened_module_to_llvm(tcx: TyCtxt, | |
} | ||
|
||
fn msvc_imps_needed(tcx: TyCtxt) -> bool { | ||
// This should never be true (because it's not supported). If it is true, | ||
// something is wrong with commandline arg validation. | ||
assert!(!(tcx.sess.opts.debugging_opts.cross_lang_lto.enabled() && | ||
tcx.sess.target.target.options.is_like_msvc && | ||
tcx.sess.opts.cg.prefer_dynamic)); | ||
|
||
tcx.sess.target.target.options.is_like_msvc && | ||
tcx.sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateType::Rlib) | ||
tcx.sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateType::Rlib) && | ||
// ThinLTO can't handle this workaround in all cases, so we don't | ||
// emit the `__imp_` symbols. Instead we make them unnecessary by disallowing | ||
// dynamic linking when cross-language LTO is enabled. | ||
!tcx.sess.opts.debugging_opts.cross_lang_lto.enabled() | ||
} | ||
|
||
// Create a `__imp_<symbol> = &symbol` global for every public static `symbol`. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// 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. | ||
|
||
// This test makes sure that functions get annotated with the proper | ||
// "target-cpu" attribute in LLVM. | ||
|
||
// no-prefer-dynamic | ||
// only-msvc | ||
// compile-flags: -Z cross-lang-lto | ||
|
||
#![crate_type = "rlib"] | ||
|
||
// CHECK-NOT: @{{.*}}__imp_{{.*}}GLOBAL{{.*}} = global i8* | ||
|
||
pub static GLOBAL: u32 = 0; | ||
pub static mut GLOBAL2: u32 = 0; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// 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. | ||
|
||
// This test makes sure that functions get annotated with the proper | ||
// "target-cpu" attribute in LLVM. | ||
|
||
// no-prefer-dynamic | ||
// ignore-tidy-linelength | ||
// compile-flags: -C no-prepopulate-passes -C panic=abort -Z cross-lang-lto -Cpasses=name-anon-globals | ||
|
||
#![crate_type = "staticlib"] | ||
|
||
// CHECK-LABEL: define {{.*}} @exported() {{.*}} #0 | ||
#[no_mangle] | ||
pub extern fn exported() { | ||
not_exported(); | ||
} | ||
|
||
// CHECK-LABEL: define {{.*}} @_ZN23target_cpu_on_functions12not_exported{{.*}}() {{.*}} #0 | ||
fn not_exported() {} | ||
|
||
// CHECK: attributes #0 = {{.*}} "target-cpu"="{{.*}}" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
|
||
-include ../tools.mk | ||
|
||
# This test makes sure that we don't loose upstream object files when compiling | ||
# staticlibs with -Zcross-lang-lto | ||
|
||
all: staticlib.rs upstream.rs | ||
$(RUSTC) upstream.rs -Z cross-lang-lto -Ccodegen-units=1 | ||
|
||
# Check No LTO | ||
$(RUSTC) staticlib.rs -Z cross-lang-lto -Ccodegen-units=1 -L. -o $(TMPDIR)/staticlib.a | ||
(cd $(TMPDIR); llvm-ar x ./staticlib.a) | ||
# Make sure the upstream object file was included | ||
ls $(TMPDIR)/upstream.*.rcgu.o | ||
|
||
# Cleanup | ||
rm $(TMPDIR)/* | ||
|
||
# Check ThinLTO | ||
$(RUSTC) upstream.rs -Z cross-lang-lto -Ccodegen-units=1 -Clto=thin | ||
$(RUSTC) staticlib.rs -Z cross-lang-lto -Ccodegen-units=1 -Clto=thin -L. -o $(TMPDIR)/staticlib.a | ||
(cd $(TMPDIR); llvm-ar x ./staticlib.a) | ||
ls $(TMPDIR)/upstream.*.rcgu.o |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// 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. | ||
|
||
#![crate_type="staticlib"] | ||
|
||
extern crate upstream; | ||
|
||
#[no_mangle] | ||
pub extern fn bar() { | ||
upstream::foo(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// 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. | ||
|
||
#![crate_type = "rlib"] | ||
|
||
pub fn foo() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
# ignore-msvc | ||
|
||
-include ../tools.mk | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could a comment be added above this with a brief explanation as to why the error is being emitted? AFAIK it's all b/c of DLL weirdness, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍