Skip to content

Rollup of 5 pull requests #72065

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
wants to merge 11 commits into from
Closed
69 changes: 39 additions & 30 deletions src/librustc_codegen_ssa/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -709,38 +709,34 @@ fn execute_work_item<B: ExtraBackendMethods>(
}

// Actual LTO type we end up choosing based on multiple factors.
enum ComputedLtoType {
pub enum ComputedLtoType {
No,
Thin,
Fat,
}

fn execute_optimize_work_item<B: ExtraBackendMethods>(
cgcx: &CodegenContext<B>,
module: ModuleCodegen<B::Module>,
module_config: &ModuleConfig,
) -> Result<WorkItemResult<B>, FatalError> {
let diag_handler = cgcx.create_diag_handler();

unsafe {
B::optimize(cgcx, &diag_handler, &module, module_config)?;
pub fn compute_per_cgu_lto_type(
sess_lto: &Lto,
opts: &config::Options,
sess_crate_types: &[CrateType],
module_kind: ModuleKind,
) -> ComputedLtoType {
// Metadata modules never participate in LTO regardless of the lto
// settings.
if module_kind == ModuleKind::Metadata {
return ComputedLtoType::No;
}

// 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
// has to wait for all the initial modules to be optimized).

// 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.
let linker_does_lto = cgcx.opts.cg.linker_plugin_lto.enabled();
let linker_does_lto = opts.cg.linker_plugin_lto.enabled();

// When we're automatically doing ThinLTO for multi-codegen-unit
// builds we don't actually want to LTO the allocator modules if
// it shows up. This is due to various linker shenanigans that
// we'll encounter later.
let is_allocator = module.kind == ModuleKind::Allocator;
let is_allocator = module_kind == ModuleKind::Allocator;

// We ignore a request for full crate grath LTO if the cate type
// is only an rlib, as there is no full crate graph to process,
Expand All @@ -750,20 +746,33 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
// require LTO so the request for LTO is always unconditionally
// passed down to the backend, but we don't actually want to do
// anything about it yet until we've got a final product.
let is_rlib = cgcx.crate_types.len() == 1 && cgcx.crate_types[0] == CrateType::Rlib;
let is_rlib = sess_crate_types.len() == 1 && sess_crate_types[0] == CrateType::Rlib;

// Metadata modules never participate in LTO regardless of the lto
// settings.
let lto_type = if module.kind == ModuleKind::Metadata {
ComputedLtoType::No
} else {
match cgcx.lto {
Lto::ThinLocal if !linker_does_lto && !is_allocator => ComputedLtoType::Thin,
Lto::Thin if !linker_does_lto && !is_rlib => ComputedLtoType::Thin,
Lto::Fat if !is_rlib => ComputedLtoType::Fat,
_ => ComputedLtoType::No,
}
};
match sess_lto {
Lto::ThinLocal if !linker_does_lto && !is_allocator => ComputedLtoType::Thin,
Lto::Thin if !linker_does_lto && !is_rlib => ComputedLtoType::Thin,
Lto::Fat if !is_rlib => ComputedLtoType::Fat,
_ => ComputedLtoType::No,
}
}

fn execute_optimize_work_item<B: ExtraBackendMethods>(
cgcx: &CodegenContext<B>,
module: ModuleCodegen<B::Module>,
module_config: &ModuleConfig,
) -> Result<WorkItemResult<B>, FatalError> {
let diag_handler = cgcx.create_diag_handler();

unsafe {
B::optimize(cgcx, &diag_handler, &module, module_config)?;
}

// 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
// has to wait for all the initial modules to be optimized).

let lto_type = compute_per_cgu_lto_type(&cgcx.lto, &cgcx.opts, &cgcx.crate_types, module.kind);

// If we're doing some form of incremental LTO then we need to be sure to
// save our module to disk first.
Expand Down
20 changes: 15 additions & 5 deletions src/librustc_codegen_ssa/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
//! int)` and `rec(x=int, y=int, z=int)` will have the same `llvm::Type`.

use crate::back::write::{
start_async_codegen, submit_codegened_module_to_llvm, submit_post_lto_module_to_llvm,
submit_pre_lto_module_to_llvm, OngoingCodegen,
compute_per_cgu_lto_type, start_async_codegen, submit_codegened_module_to_llvm,
submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm, ComputedLtoType, OngoingCodegen,
};
use crate::common::{IntPredicate, RealPredicate, TypeKind};
use crate::meth;
Expand Down Expand Up @@ -43,7 +43,7 @@ use rustc_middle::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_session::cgu_reuse_tracker::CguReuse;
use rustc_session::config::{self, EntryFnType, Lto};
use rustc_session::config::{self, EntryFnType};
use rustc_session::Session;
use rustc_span::Span;
use rustc_symbol_mangling::test as symbol_names_test;
Expand Down Expand Up @@ -941,8 +941,18 @@ fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> CguR
);

if tcx.dep_graph.try_mark_green(tcx, &dep_node).is_some() {
// We can re-use either the pre- or the post-thinlto state
if tcx.sess.lto() != Lto::No { CguReuse::PreLto } else { CguReuse::PostLto }
// We can re-use either the pre- or the post-thinlto state. If no LTO is
// being performed then we can use post-LTO artifacts, otherwise we must
// reuse pre-LTO artifacts
match compute_per_cgu_lto_type(
&tcx.sess.lto(),
&tcx.sess.opts,
&tcx.sess.crate_types.borrow(),
ModuleKind::Regular,
) {
ComputedLtoType::No => CguReuse::PostLto,
_ => CguReuse::PreLto,
}
} else {
CguReuse::No
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_error_codes/error_codes/E0569.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
If an impl has a generic parameter with the `#[may_dangle]` attribute, then
that impl must be declared as an `unsafe impl.
that impl must be declared as an `unsafe impl`.

Erroneous code example:

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_interface/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub fn add_configuration(

cfg.extend(codegen_backend.target_features(sess).into_iter().map(|feat| (tf, Some(feat))));

if sess.crt_static_feature(None) {
if sess.crt_static(None) {
cfg.insert((tf, Some(Symbol::intern("crt-static"))));
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir_build/build/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}));

debug!("ast_block_stmts: pattern={:?}", pattern);
this.visit_bindings(
this.visit_primary_bindings(
&pattern,
UserTypeProjections::none(),
&mut |this, _, _, _, node, span, _, _| {
Expand Down
59 changes: 43 additions & 16 deletions src/librustc_mir_build/build/matches/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
opt_match_place: Option<(Option<&Place<'tcx>>, Span)>,
) -> Option<SourceScope> {
debug!("declare_bindings: pattern={:?}", pattern);
self.visit_bindings(
self.visit_primary_bindings(
&pattern,
UserTypeProjections::none(),
&mut |this, mutability, name, mode, var, span, ty, user_ty| {
Expand Down Expand Up @@ -563,7 +563,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.schedule_drop(span, region_scope, local_id, DropKind::Value);
}

pub(super) fn visit_bindings(
/// Visit all of the primary bindings in a patterns, that is, visit the
/// leftmost occurrence of each variable bound in a pattern. A variable
/// will occur more than once in an or-pattern.
pub(super) fn visit_primary_bindings(
&mut self,
pattern: &Pat<'tcx>,
pattern_user_ty: UserTypeProjections,
Expand All @@ -578,12 +581,26 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
UserTypeProjections,
),
) {
debug!("visit_bindings: pattern={:?} pattern_user_ty={:?}", pattern, pattern_user_ty);
debug!(
"visit_primary_bindings: pattern={:?} pattern_user_ty={:?}",
pattern, pattern_user_ty
);
match *pattern.kind {
PatKind::Binding { mutability, name, mode, var, ty, ref subpattern, .. } => {
f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty.clone());
PatKind::Binding {
mutability,
name,
mode,
var,
ty,
ref subpattern,
is_primary,
..
} => {
if is_primary {
f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty.clone());
}
if let Some(subpattern) = subpattern.as_ref() {
self.visit_bindings(subpattern, pattern_user_ty, f);
self.visit_primary_bindings(subpattern, pattern_user_ty, f);
}
}

Expand All @@ -592,20 +609,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let from = u32::try_from(prefix.len()).unwrap();
let to = u32::try_from(suffix.len()).unwrap();
for subpattern in prefix {
self.visit_bindings(subpattern, pattern_user_ty.clone().index(), f);
self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f);
}
for subpattern in slice {
self.visit_bindings(subpattern, pattern_user_ty.clone().subslice(from, to), f);
self.visit_primary_bindings(
subpattern,
pattern_user_ty.clone().subslice(from, to),
f,
);
}
for subpattern in suffix {
self.visit_bindings(subpattern, pattern_user_ty.clone().index(), f);
self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f);
}
}

PatKind::Constant { .. } | PatKind::Range { .. } | PatKind::Wild => {}

PatKind::Deref { ref subpattern } => {
self.visit_bindings(subpattern, pattern_user_ty.deref(), f);
self.visit_primary_bindings(subpattern, pattern_user_ty.deref(), f);
}

PatKind::AscribeUserType {
Expand All @@ -630,26 +651,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
projs: Vec::new(),
};
let subpattern_user_ty = pattern_user_ty.push_projection(&projection, user_ty_span);
self.visit_bindings(subpattern, subpattern_user_ty, f)
self.visit_primary_bindings(subpattern, subpattern_user_ty, f)
}

PatKind::Leaf { ref subpatterns } => {
for subpattern in subpatterns {
let subpattern_user_ty = pattern_user_ty.clone().leaf(subpattern.field);
debug!("visit_bindings: subpattern_user_ty={:?}", subpattern_user_ty);
self.visit_bindings(&subpattern.pattern, subpattern_user_ty, f);
debug!("visit_primary_bindings: subpattern_user_ty={:?}", subpattern_user_ty);
self.visit_primary_bindings(&subpattern.pattern, subpattern_user_ty, f);
}
}

PatKind::Variant { adt_def, substs: _, variant_index, ref subpatterns } => {
for subpattern in subpatterns {
let subpattern_user_ty =
pattern_user_ty.clone().variant(adt_def, variant_index, subpattern.field);
self.visit_bindings(&subpattern.pattern, subpattern_user_ty, f);
self.visit_primary_bindings(&subpattern.pattern, subpattern_user_ty, f);
}
}
PatKind::Or { ref pats } => {
self.visit_bindings(&pats[0], pattern_user_ty, f);
// In cases where we recover from errors the primary bindings
// may not all be in the leftmost subpattern. For example in
// `let (x | y) = ...`, the primary binding of `y` occurs in
// the right subpattern
for subpattern in pats {
self.visit_primary_bindings(subpattern, pattern_user_ty.clone(), f);
}
}
}
}
Expand Down Expand Up @@ -1955,7 +1982,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
is_block_tail: None,
local_info: Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
binding_mode,
// hypothetically, `visit_bindings` could try to unzip
// hypothetically, `visit_primary_bindings` could try to unzip
// an outermost hir::Ty as we descend, matching up
// idents in pat; but complex w/ unclear UI payoff.
// Instead, just abandon providing diagnostic info.
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir_build/build/matches/simplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Ok(())
}

PatKind::Binding { name, mutability, mode, var, ty, ref subpattern } => {
PatKind::Binding { name, mutability, mode, var, ty, ref subpattern, is_primary: _ } => {
candidate.bindings.push(Binding {
name,
mutability,
Expand Down
7 changes: 6 additions & 1 deletion src/librustc_mir_build/hair/pattern/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ crate enum PatKind<'tcx> {
var: hir::HirId,
ty: Ty<'tcx>,
subpattern: Option<Pat<'tcx>>,
/// Is this the leftmost occurance of the binding, i.e., is `var` the
/// `HirId` of this pattern?
is_primary: bool,
},

/// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with
Expand Down Expand Up @@ -601,6 +604,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
var: id,
ty: var_ty,
subpattern: self.lower_opt_pattern(sub),
is_primary: id == pat.hir_id,
}
}

Expand Down Expand Up @@ -977,14 +981,15 @@ impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> {
user_ty_span,
},
},
PatKind::Binding { mutability, name, mode, var, ty, ref subpattern } => {
PatKind::Binding { mutability, name, mode, var, ty, ref subpattern, is_primary } => {
PatKind::Binding {
mutability: mutability.fold_with(folder),
name: name.fold_with(folder),
mode: mode.fold_with(folder),
var: var.fold_with(folder),
ty: ty.fold_with(folder),
subpattern: subpattern.fold_with(folder),
is_primary,
}
}
PatKind::Variant { adt_def, substs, variant_index, ref subpatterns } => {
Expand Down
11 changes: 3 additions & 8 deletions src/librustc_session/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -598,16 +598,11 @@ impl Session {

/// Check whether this compile session and crate type use static crt.
pub fn crt_static(&self, crate_type: Option<CrateType>) -> bool {
// If the target does not opt in to crt-static support, use its default.
if self.target.target.options.crt_static_respected {
self.crt_static_feature(crate_type)
} else {
self.target.target.options.crt_static_default
if !self.target.target.options.crt_static_respected {
// If the target does not opt in to crt-static support, use its default.
return self.target.target.options.crt_static_default;
}
}

/// Check whether this compile session and crate type use `crt-static` feature.
pub fn crt_static_feature(&self, crate_type: Option<CrateType>) -> bool {
let requested_features = self.opts.cg.target_feature.split(',');
let found_negative = requested_features.clone().any(|r| r == "-crt-static");
let found_positive = requested_features.clone().any(|r| r == "+crt-static");
Expand Down
5 changes: 4 additions & 1 deletion src/librustdoc/html/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2281,7 +2281,10 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
);
message.push_str(&format!(": {}", html.to_string()));
}
stability.push(format!("<div class='stab deprecated'>{}</div>", message));
stability.push(format!(
"<div class='stab deprecated'><span class='emoji'>👎</span> {}</div>",
message,
));
}

if let Some(stab) = item.stability.as_ref().filter(|stab| stab.level == stability::Unstable) {
Expand Down
8 changes: 8 additions & 0 deletions src/test/incremental/lto-in-linker.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// revisions:cfail1 cfail2
// compile-flags: -Z query-dep-graph --crate-type rlib -C linker-plugin-lto -O
// build-pass

#![feature(rustc_attrs)]
#![rustc_partition_reused(module = "lto_in_linker", cfg = "cfail2")]

pub fn foo() {}
8 changes: 8 additions & 0 deletions src/test/incremental/rlib-lto.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// revisions:cfail1 cfail2
// compile-flags: -Z query-dep-graph --crate-type rlib -C lto
// build-pass

#![feature(rustc_attrs)]
#![rustc_partition_reused(module = "rlib_lto", cfg = "cfail2")]

pub fn foo() {}
Loading