Skip to content
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

Rollup of 5 pull requests #72065

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