Merge pull request #20268 from lnicola/sync-from-rust

minor: Sync from downstream
This commit is contained in:
Laurențiu Nicola 2025-07-21 06:58:10 +00:00 committed by GitHub
commit 8f67bcf4b0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
1297 changed files with 18441 additions and 13139 deletions

View file

@ -216,7 +216,7 @@ dependencies = [
"memchr",
"serde",
"serde_derive",
"winnow 0.7.11",
"winnow 0.7.12",
]
[[package]]
@ -470,23 +470,12 @@ dependencies = [
[[package]]
name = "chrono-tz"
version = "0.10.3"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efdce149c370f133a071ca8ef6ea340b7b88748ab0810097a9e2976eaa34b4f3"
checksum = "a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3"
dependencies = [
"chrono",
"chrono-tz-build",
"phf",
]
[[package]]
name = "chrono-tz-build"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f10f8c9340e31fc120ff885fcdb54a0b48e474bbd77cab557f0c30a3e569402"
dependencies = [
"parse-zoneinfo",
"phf_codegen",
"phf 0.12.1",
]
[[package]]
@ -501,9 +490,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.40"
version = "4.5.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9"
dependencies = [
"clap_builder",
"clap_derive",
@ -521,9 +510,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.40"
version = "4.5.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d"
dependencies = [
"anstream",
"anstyle",
@ -533,9 +522,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.5.40"
version = "4.5.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce"
checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491"
dependencies = [
"heck 0.5.0",
"proc-macro2",
@ -798,9 +787,9 @@ dependencies = [
[[package]]
name = "crc32fast"
version = "1.4.2"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
dependencies = [
"cfg-if",
]
@ -989,9 +978,9 @@ dependencies = [
[[package]]
name = "derive_setters"
version = "0.1.7"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c848e86c87e5cc305313041c5677d4d95d60baa71cf95e5f6ea2554bb629ff"
checksum = "ae5c625eda104c228c06ecaf988d1c60e542176bd7a490e60eeda3493244c0c9"
dependencies = [
"darling",
"proc-macro2",
@ -2045,9 +2034,9 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
[[package]]
name = "libredox"
version = "0.1.4"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638"
checksum = "4488594b9328dee448adb906d8b126d9b7deb7cf5c22161ee591610bb1be83c0"
dependencies = [
"bitflags",
"libc",
@ -2157,7 +2146,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18"
dependencies = [
"log",
"phf",
"phf 0.11.3",
"phf_codegen",
"string_cache",
"string_cache_codegen",
@ -2196,9 +2185,9 @@ dependencies = [
[[package]]
name = "measureme"
version = "12.0.1"
version = "12.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "570a507d8948a66a97f42cbbaf8a6bb9516a51017d4ee949502ad7a10a864395"
checksum = "6ebd1ebda747ae161a4a377bf93f87e18d46faad2331cc0c7d25b84b1d445f49"
dependencies = [
"log",
"memmap2",
@ -2632,15 +2621,6 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "parse-zoneinfo"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24"
dependencies = [
"regex",
]
[[package]]
name = "pathdiff"
version = "0.2.3"
@ -2712,7 +2692,16 @@ version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
dependencies = [
"phf_shared",
"phf_shared 0.11.3",
]
[[package]]
name = "phf"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7"
dependencies = [
"phf_shared 0.12.1",
]
[[package]]
@ -2722,7 +2711,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a"
dependencies = [
"phf_generator",
"phf_shared",
"phf_shared 0.11.3",
]
[[package]]
@ -2731,7 +2720,7 @@ version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
dependencies = [
"phf_shared",
"phf_shared 0.11.3",
"rand 0.8.5",
]
@ -2744,6 +2733,15 @@ dependencies = [
"siphasher",
]
[[package]]
name = "phf_shared"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981"
dependencies = [
"siphasher",
]
[[package]]
name = "pin-project-lite"
version = "0.2.16"
@ -3136,9 +3134,9 @@ checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
[[package]]
name = "rustc-literal-escaper"
version = "0.0.4"
version = "0.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab03008eb631b703dd16978282ae36c73282e7922fe101a4bd072a40ecea7b8b"
checksum = "e4ee29da77c5a54f42697493cd4c9b9f31b74df666a6c04dfc4fde77abe0438b"
[[package]]
name = "rustc-main"
@ -4752,15 +4750,15 @@ dependencies = [
[[package]]
name = "rustix"
version = "1.0.7"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.59.0",
"windows-sys 0.60.2",
]
[[package]]
@ -4860,9 +4858,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.140"
version = "1.0.141"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3"
dependencies = [
"itoa",
"memchr",
@ -5027,7 +5025,7 @@ checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f"
dependencies = [
"new_debug_unreachable",
"parking_lot",
"phf_shared",
"phf_shared 0.11.3",
"precomputed-hash",
"serde",
]
@ -5039,7 +5037,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0"
dependencies = [
"phf_generator",
"phf_shared",
"phf_shared 0.11.3",
"proc-macro2",
"quote",
]
@ -5069,14 +5067,6 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "suggest-tests"
version = "0.1.0"
dependencies = [
"build_helper",
"glob",
]
[[package]]
name = "syn"
version = "1.0.109"
@ -5112,9 +5102,9 @@ dependencies = [
[[package]]
name = "sysinfo"
version = "0.36.0"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aab138f5c1bb35231de19049060a87977ad23e04f2303e953bc5c2947ac7dec4"
checksum = "252800745060e7b9ffb7b2badbd8b31cfa4aa2e61af879d0a3bf2a317c20217d"
dependencies = [
"libc",
"objc2-core-foundation",
@ -5419,7 +5409,7 @@ dependencies = [
"serde_spanned",
"toml_datetime",
"toml_write",
"winnow 0.7.11",
"winnow 0.7.12",
]
[[package]]
@ -5837,9 +5827,9 @@ dependencies = [
[[package]]
name = "wasi-preview1-component-adapter-provider"
version = "34.0.1"
version = "34.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aafa1e6af9a954a4bcf6ef420c33355d0ce84ddc6afbcba7bb6f05126f9120ae"
checksum = "33696c5f1ff1e083de9f36c3da471abd736362bc173e093f8b0b1ed5a387e39b"
[[package]]
name = "wasm-bindgen"
@ -6483,9 +6473,9 @@ dependencies = [
[[package]]
name = "winnow"
version = "0.7.11"
version = "0.7.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd"
checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95"
dependencies = [
"memchr",
]

View file

@ -39,7 +39,6 @@ members = [
"src/tools/rustdoc-gui-test",
"src/tools/rustdoc-themes",
"src/tools/rustfmt",
"src/tools/suggest-tests",
"src/tools/test-float-parse",
"src/tools/tidy",
"src/tools/tier-check",

View file

@ -43,7 +43,7 @@ use std::fmt;
#[cfg(feature = "nightly")]
use std::iter::Step;
use std::num::{NonZeroUsize, ParseIntError};
use std::ops::{Add, AddAssign, Deref, Mul, RangeInclusive, Sub};
use std::ops::{Add, AddAssign, Deref, Mul, RangeFull, RangeInclusive, Sub};
use std::str::FromStr;
use bitflags::bitflags;
@ -1391,12 +1391,45 @@ impl WrappingRange {
}
/// Returns `true` if `size` completely fills the range.
///
/// Note that this is *not* the same as `self == WrappingRange::full(size)`.
/// Niche calculations can produce full ranges which are not the canonical one;
/// for example `Option<NonZero<u16>>` gets `valid_range: (..=0) | (1..)`.
#[inline]
fn is_full_for(&self, size: Size) -> bool {
let max_value = size.unsigned_int_max();
debug_assert!(self.start <= max_value && self.end <= max_value);
self.start == (self.end.wrapping_add(1) & max_value)
}
/// Checks whether this range is considered non-wrapping when the values are
/// interpreted as *unsigned* numbers of width `size`.
///
/// Returns `Ok(true)` if there's no wrap-around, `Ok(false)` if there is,
/// and `Err(..)` if the range is full so it depends how you think about it.
#[inline]
pub fn no_unsigned_wraparound(&self, size: Size) -> Result<bool, RangeFull> {
if self.is_full_for(size) { Err(..) } else { Ok(self.start <= self.end) }
}
/// Checks whether this range is considered non-wrapping when the values are
/// interpreted as *signed* numbers of width `size`.
///
/// This is heavily dependent on the `size`, as `100..=200` does wrap when
/// interpreted as `i8`, but doesn't when interpreted as `i16`.
///
/// Returns `Ok(true)` if there's no wrap-around, `Ok(false)` if there is,
/// and `Err(..)` if the range is full so it depends how you think about it.
#[inline]
pub fn no_signed_wraparound(&self, size: Size) -> Result<bool, RangeFull> {
if self.is_full_for(size) {
Err(..)
} else {
let start: i128 = size.sign_extend(self.start);
let end: i128 = size.sign_extend(self.end);
Ok(start <= end)
}
}
}
impl fmt::Debug for WrappingRange {

View file

@ -7,7 +7,7 @@ edition = "2024"
# tidy-alphabetical-start
bitflags = "2.4.1"
memchr = "2.7.4"
rustc-literal-escaper = "0.0.4"
rustc-literal-escaper = "0.0.5"
rustc_ast_ir = { path = "../rustc_ast_ir" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_index = { path = "../rustc_index" }

View file

@ -18,7 +18,7 @@
//! - [`Attribute`]: Metadata associated with item.
//! - [`UnOp`], [`BinOp`], and [`BinOpKind`]: Unary and binary operators.
use std::borrow::Cow;
use std::borrow::{Borrow, Cow};
use std::{cmp, fmt};
pub use GenericArgs::*;
@ -155,6 +155,59 @@ impl Path {
}
}
/// Joins multiple symbols with "::" into a path, e.g. "a::b::c". If the first
/// segment is `kw::PathRoot` it will be printed as empty, e.g. "::b::c".
///
/// The generics on the `path` argument mean it can accept many forms, such as:
/// - `&[Symbol]`
/// - `Vec<Symbol>`
/// - `Vec<&Symbol>`
/// - `impl Iterator<Item = Symbol>`
/// - `impl Iterator<Item = &Symbol>`
///
/// Panics if `path` is empty or a segment after the first is `kw::PathRoot`.
pub fn join_path_syms(path: impl IntoIterator<Item = impl Borrow<Symbol>>) -> String {
// This is a guess at the needed capacity that works well in practice. It is slightly faster
// than (a) starting with an empty string, or (b) computing the exact capacity required.
// `8` works well because it's about the right size and jemalloc's size classes are all
// multiples of 8.
let mut iter = path.into_iter();
let len_hint = iter.size_hint().1.unwrap_or(1);
let mut s = String::with_capacity(len_hint * 8);
let first_sym = *iter.next().unwrap().borrow();
if first_sym != kw::PathRoot {
s.push_str(first_sym.as_str());
}
for sym in iter {
let sym = *sym.borrow();
debug_assert_ne!(sym, kw::PathRoot);
s.push_str("::");
s.push_str(sym.as_str());
}
s
}
/// Like `join_path_syms`, but for `Ident`s. This function is necessary because
/// `Ident::to_string` does more than just print the symbol in the `name` field.
pub fn join_path_idents(path: impl IntoIterator<Item = impl Borrow<Ident>>) -> String {
let mut iter = path.into_iter();
let len_hint = iter.size_hint().1.unwrap_or(1);
let mut s = String::with_capacity(len_hint * 8);
let first_ident = *iter.next().unwrap().borrow();
if first_ident.name != kw::PathRoot {
s.push_str(&first_ident.to_string());
}
for ident in iter {
let ident = *ident.borrow();
debug_assert_ne!(ident.name, kw::PathRoot);
s.push_str("::");
s.push_str(&ident.to_string());
}
s
}
/// A segment of a path: an identifier, an optional lifetime, and a set of types.
///
/// E.g., `std`, `String` or `Box<T>`.
@ -3637,6 +3690,7 @@ impl Default for FnHeader {
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Trait {
pub constness: Const,
pub safety: Safety,
pub is_auto: IsAuto,
pub ident: Ident,

View file

@ -126,11 +126,11 @@ impl LitKind {
token::CStr => {
let s = symbol.as_str();
let mut buf = Vec::with_capacity(s.len());
unescape_c_str(s, |_span, c| match c {
unescape_c_str(s, |_span, res| match res {
Ok(MixedUnit::Char(c)) => {
buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes())
buf.extend_from_slice(c.get().encode_utf8(&mut [0; 4]).as_bytes())
}
Ok(MixedUnit::HighByte(b)) => buf.push(b),
Ok(MixedUnit::HighByte(b)) => buf.push(b.get()),
Err(err) => {
assert!(!err.is_fatal(), "failed to unescape C string literal")
}

View file

@ -738,7 +738,8 @@ macro_rules! common_visitor_and_walkers {
try_visit!(vis.visit_ty(self_ty));
visit_assoc_items(vis, items, AssocCtxt::Impl { of_trait: of_trait.is_some() })
}
ItemKind::Trait(box Trait { safety, is_auto: _, ident, generics, bounds, items }) => {
ItemKind::Trait(box Trait { constness, safety, is_auto: _, ident, generics, bounds, items }) => {
try_visit!(visit_constness(vis, constness));
try_visit!(visit_safety(vis, safety));
try_visit!(vis.visit_ident(ident));
try_visit!(vis.visit_generics(generics));

View file

@ -127,9 +127,6 @@ ast_lowering_misplaced_impl_trait =
`impl Trait` is not allowed in {$position}
.note = `impl Trait` is only allowed in arguments and return types of functions and methods
ast_lowering_misplaced_relax_trait_bound =
`?Trait` bounds are only permitted at the point where a type parameter is declared
ast_lowering_never_pattern_with_body =
a never pattern is always unreachable
.label = this will never be executed

View file

@ -324,13 +324,6 @@ pub(crate) struct MisplacedDoubleDot {
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(ast_lowering_misplaced_relax_trait_bound)]
pub(crate) struct MisplacedRelaxTraitBound {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(ast_lowering_match_arm_with_no_body)]
pub(crate) struct MatchArmWithNoBody {

View file

@ -16,14 +16,11 @@ use smallvec::{SmallVec, smallvec};
use thin_vec::ThinVec;
use tracing::instrument;
use super::errors::{
InvalidAbi, InvalidAbiSuggestion, MisplacedRelaxTraitBound, TupleStructWithDefault,
UnionWithDefault,
};
use super::errors::{InvalidAbi, InvalidAbiSuggestion, TupleStructWithDefault, UnionWithDefault};
use super::stability::{enabled_names, gate_unstable_abi};
use super::{
AstOwner, FnDeclKind, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
ResolverAstLoweringExt,
RelaxedBoundForbiddenReason, RelaxedBoundPolicy, ResolverAstLoweringExt,
};
pub(super) struct ItemLowerer<'a, 'hir> {
@ -417,7 +414,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
items: new_impl_items,
}))
}
ItemKind::Trait(box Trait { is_auto, safety, ident, generics, bounds, items }) => {
ItemKind::Trait(box Trait {
constness,
is_auto,
safety,
ident,
generics,
bounds,
items,
}) => {
let constness = self.lower_constness(*constness);
let ident = self.lower_ident(*ident);
let (generics, (safety, items, bounds)) = self.lower_generics(
generics,
@ -426,6 +432,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|this| {
let bounds = this.lower_param_bounds(
bounds,
RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::SuperTrait),
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
);
let items = this.arena.alloc_from_iter(
@ -435,7 +442,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
(safety, items, bounds)
},
);
hir::ItemKind::Trait(*is_auto, safety, ident, generics, bounds, items)
hir::ItemKind::Trait(constness, *is_auto, safety, ident, generics, bounds, items)
}
ItemKind::TraitAlias(ident, generics, bounds) => {
let ident = self.lower_ident(*ident);
@ -446,6 +453,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|this| {
this.lower_param_bounds(
bounds,
RelaxedBoundPolicy::Allowed,
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
)
},
@ -931,6 +939,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::TraitItemKind::Type(
this.lower_param_bounds(
bounds,
RelaxedBoundPolicy::Allowed,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
),
ty,
@ -1668,61 +1677,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
assert!(self.impl_trait_defs.is_empty());
assert!(self.impl_trait_bounds.is_empty());
// Error if `?Trait` bounds in where clauses don't refer directly to type parameters.
// Note: we used to clone these bounds directly onto the type parameter (and avoid lowering
// these into hir when we lower thee where clauses), but this makes it quite difficult to
// keep track of the Span info. Now, `<dyn HirTyLowerer>::add_implicit_sized_bound`
// checks both param bounds and where clauses for `?Sized`.
for pred in &generics.where_clause.predicates {
let WherePredicateKind::BoundPredicate(bound_pred) = &pred.kind else {
continue;
};
let compute_is_param = || {
// Check if the where clause type is a plain type parameter.
match self
.resolver
.get_partial_res(bound_pred.bounded_ty.id)
.and_then(|r| r.full_res())
{
Some(Res::Def(DefKind::TyParam, def_id))
if bound_pred.bound_generic_params.is_empty() =>
{
generics
.params
.iter()
.any(|p| def_id == self.local_def_id(p.id).to_def_id())
}
// Either the `bounded_ty` is not a plain type parameter, or
// it's not found in the generic type parameters list.
_ => false,
}
};
// We only need to compute this once per `WherePredicate`, but don't
// need to compute this at all unless there is a Maybe bound.
let mut is_param: Option<bool> = None;
for bound in &bound_pred.bounds {
if !matches!(
*bound,
GenericBound::Trait(PolyTraitRef {
modifiers: TraitBoundModifiers { polarity: BoundPolarity::Maybe(_), .. },
..
})
) {
continue;
}
let is_param = *is_param.get_or_insert_with(compute_is_param);
if !is_param && !self.tcx.features().more_maybe_bounds() {
self.tcx
.sess
.create_feature_err(
MisplacedRelaxTraitBound { span: bound.span() },
sym::more_maybe_bounds,
)
.emit();
}
}
}
let mut predicates: SmallVec<[hir::WherePredicate<'hir>; 4]> = SmallVec::new();
predicates.extend(generics.params.iter().filter_map(|param| {
self.lower_generic_bound_predicate(
@ -1732,6 +1686,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&param.bounds,
param.colon_span,
generics.span,
RelaxedBoundPolicy::Allowed,
itctx,
PredicateOrigin::GenericParam,
)
@ -1741,7 +1696,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
.where_clause
.predicates
.iter()
.map(|predicate| self.lower_where_predicate(predicate)),
.map(|predicate| self.lower_where_predicate(predicate, &generics.params)),
);
let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> = self
@ -1818,6 +1773,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
bounds: &[GenericBound],
colon_span: Option<Span>,
parent_span: Span,
rbp: RelaxedBoundPolicy<'_>,
itctx: ImplTraitContext,
origin: PredicateOrigin,
) -> Option<hir::WherePredicate<'hir>> {
@ -1826,7 +1782,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
return None;
}
let bounds = self.lower_param_bounds(bounds, itctx);
let bounds = self.lower_param_bounds(bounds, rbp, itctx);
let param_span = ident.span;
@ -1878,7 +1834,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
Some(hir::WherePredicate { hir_id, span, kind })
}
fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate<'hir> {
fn lower_where_predicate(
&mut self,
pred: &WherePredicate,
params: &[ast::GenericParam],
) -> hir::WherePredicate<'hir> {
let hir_id = self.lower_node_id(pred.id);
let span = self.lower_span(pred.span);
self.lower_attrs(hir_id, &pred.attrs, span);
@ -1887,17 +1847,29 @@ impl<'hir> LoweringContext<'_, 'hir> {
bound_generic_params,
bounded_ty,
bounds,
}) => hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
bound_generic_params: self
.lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder),
bounded_ty: self
.lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
bounds: self.lower_param_bounds(
bounds,
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
),
origin: PredicateOrigin::WhereClause,
}),
}) => {
let rbp = if bound_generic_params.is_empty() {
RelaxedBoundPolicy::AllowedIfOnTyParam(bounded_ty.id, params)
} else {
RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::LateBoundVarsInScope)
};
hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
bound_generic_params: self.lower_generic_params(
bound_generic_params,
hir::GenericParamSource::Binder,
),
bounded_ty: self.lower_ty(
bounded_ty,
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
),
bounds: self.lower_param_bounds(
bounds,
rbp,
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
),
origin: PredicateOrigin::WhereClause,
})
}
WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => {
hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
lifetime: self.lower_lifetime(
@ -1907,6 +1879,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
),
bounds: self.lower_param_bounds(
bounds,
RelaxedBoundPolicy::Allowed,
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
),
in_where_clause: true,

View file

@ -53,8 +53,8 @@ use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
use rustc_hir::lints::DelayedLint;
use rustc_hir::{
self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem,
LifetimeSource, LifetimeSyntax, ParamName, TraitCandidate,
self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource,
LifetimeSyntax, ParamName, TraitCandidate,
};
use rustc_index::{Idx, IndexSlice, IndexVec};
use rustc_macros::extension;
@ -281,6 +281,24 @@ impl ResolverAstLowering {
}
}
/// How relaxed bounds `?Trait` should be treated.
///
/// Relaxed bounds should only be allowed in places where we later
/// (namely during HIR ty lowering) perform *sized elaboration*.
#[derive(Clone, Copy, Debug)]
enum RelaxedBoundPolicy<'a> {
Allowed,
AllowedIfOnTyParam(NodeId, &'a [ast::GenericParam]),
Forbidden(RelaxedBoundForbiddenReason),
}
#[derive(Clone, Copy, Debug)]
enum RelaxedBoundForbiddenReason {
TraitObjectTy,
SuperTrait,
LateBoundVarsInScope,
}
/// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
/// and if so, what meaning it has.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
@ -1084,10 +1102,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar)));
hir::AssocItemConstraintKind::Equality { term: err_ty.into() }
} else {
// Desugar `AssocTy: Bounds` into an assoc type binding where the
// later desugars into a trait predicate.
let bounds = self.lower_param_bounds(bounds, itctx);
// FIXME(#135229): These should be forbidden!
let bounds =
self.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx);
hir::AssocItemConstraintKind::Bound { bounds }
}
}
@ -1216,6 +1233,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span: t.span,
parens: ast::Parens::No,
},
RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::TraitObjectTy),
itctx,
);
let bounds = this.arena.alloc_from_iter([bound]);
@ -1271,7 +1289,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
parenthesized: hir::GenericArgsParentheses::No,
span_ext: span,
});
let path = self.make_lang_item_qpath(LangItem::Pin, span, Some(args));
let path = self.make_lang_item_qpath(hir::LangItem::Pin, span, Some(args));
hir::TyKind::Path(path)
}
TyKind::FnPtr(f) => {
@ -1332,7 +1350,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// takes care of rejecting invalid modifier combinations and
// const trait bounds in trait object types.
GenericBound::Trait(ty) => {
let trait_ref = this.lower_poly_trait_ref(ty, itctx);
let trait_ref = this.lower_poly_trait_ref(
ty,
RelaxedBoundPolicy::Forbidden(
RelaxedBoundForbiddenReason::TraitObjectTy,
),
itctx,
);
Some(trait_ref)
}
GenericBound::Outlives(lifetime) => {
@ -1387,9 +1411,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
path
}
ImplTraitContext::InBinding => {
hir::TyKind::TraitAscription(self.lower_param_bounds(bounds, itctx))
}
ImplTraitContext::InBinding => hir::TyKind::TraitAscription(
self.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx),
),
ImplTraitContext::FeatureGated(position, feature) => {
let guar = self
.tcx
@ -1505,7 +1529,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
self.lower_opaque_inner(opaque_ty_node_id, origin, opaque_ty_span, |this| {
this.lower_param_bounds(bounds, itctx)
this.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx)
})
}
@ -1799,10 +1823,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_param_bound(
&mut self,
tpb: &GenericBound,
rbp: RelaxedBoundPolicy<'_>,
itctx: ImplTraitContext,
) -> hir::GenericBound<'hir> {
match tpb {
GenericBound::Trait(p) => hir::GenericBound::Trait(self.lower_poly_trait_ref(p, itctx)),
GenericBound::Trait(p) => {
hir::GenericBound::Trait(self.lower_poly_trait_ref(p, rbp, itctx))
}
GenericBound::Outlives(lifetime) => hir::GenericBound::Outlives(self.lower_lifetime(
lifetime,
LifetimeSource::OutlivesBound,
@ -2017,21 +2044,93 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
#[instrument(level = "debug", skip(self))]
fn lower_poly_trait_ref(
&mut self,
p: &PolyTraitRef,
PolyTraitRef { bound_generic_params, modifiers, trait_ref, span, parens: _ }: &PolyTraitRef,
rbp: RelaxedBoundPolicy<'_>,
itctx: ImplTraitContext,
) -> hir::PolyTraitRef<'hir> {
let bound_generic_params =
self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
let trait_ref = self.lower_trait_ref(p.modifiers, &p.trait_ref, itctx);
let modifiers = self.lower_trait_bound_modifiers(p.modifiers);
self.lower_lifetime_binder(trait_ref.ref_id, bound_generic_params);
let trait_ref = self.lower_trait_ref(*modifiers, trait_ref, itctx);
let modifiers = self.lower_trait_bound_modifiers(*modifiers);
if let ast::BoundPolarity::Maybe(_) = modifiers.polarity {
self.validate_relaxed_bound(trait_ref, *span, rbp);
}
hir::PolyTraitRef {
bound_generic_params,
modifiers,
trait_ref,
span: self.lower_span(p.span),
span: self.lower_span(*span),
}
}
fn validate_relaxed_bound(
&self,
trait_ref: hir::TraitRef<'_>,
span: Span,
rbp: RelaxedBoundPolicy<'_>,
) {
// Even though feature `more_maybe_bounds` bypasses the given policy and (currently) enables
// relaxed bounds in every conceivable position[^1], we don't want to advertise it to the user
// (via a feature gate) since it's super internal. Besides this, it'd be quite distracting.
//
// [^1]: Strictly speaking, this is incorrect (at the very least for `Sized`) because it's
// no longer fully consistent with default trait elaboration in HIR ty lowering.
match rbp {
RelaxedBoundPolicy::Allowed => return,
RelaxedBoundPolicy::AllowedIfOnTyParam(id, params) => {
if let Some(res) = self.resolver.get_partial_res(id).and_then(|r| r.full_res())
&& let Res::Def(DefKind::TyParam, def_id) = res
&& params.iter().any(|p| def_id == self.local_def_id(p.id).to_def_id())
{
return;
}
if self.tcx.features().more_maybe_bounds() {
return;
}
}
RelaxedBoundPolicy::Forbidden(reason) => {
if self.tcx.features().more_maybe_bounds() {
return;
}
match reason {
RelaxedBoundForbiddenReason::TraitObjectTy => {
self.dcx().span_err(
span,
"relaxed bounds are not permitted in trait object types",
);
return;
}
RelaxedBoundForbiddenReason::SuperTrait => {
let mut diag = self.dcx().struct_span_err(
span,
"relaxed bounds are not permitted in supertrait bounds",
);
if let Some(def_id) = trait_ref.trait_def_id()
&& self.tcx.is_lang_item(def_id, hir::LangItem::Sized)
{
diag.note("traits are `?Sized` by default");
}
diag.emit();
return;
}
RelaxedBoundForbiddenReason::LateBoundVarsInScope => {}
};
}
}
self.dcx()
.struct_span_err(span, "this relaxed bound is not permitted here")
.with_note(
"in this context, relaxed bounds are only allowed on \
type parameters defined by the closest item",
)
.emit();
}
fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> {
hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), mutbl: mt.mutbl }
}
@ -2040,17 +2139,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_param_bounds(
&mut self,
bounds: &[GenericBound],
rbp: RelaxedBoundPolicy<'_>,
itctx: ImplTraitContext,
) -> hir::GenericBounds<'hir> {
self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx))
self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, rbp, itctx))
}
fn lower_param_bounds_mut(
&mut self,
bounds: &[GenericBound],
rbp: RelaxedBoundPolicy<'_>,
itctx: ImplTraitContext,
) -> impl Iterator<Item = hir::GenericBound<'hir>> {
bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx))
bounds.iter().map(move |bound| self.lower_param_bound(bound, rbp, itctx))
}
#[instrument(level = "debug", skip(self), ret)]
@ -2084,6 +2185,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
bounds,
/* colon_span */ None,
span,
RelaxedBoundPolicy::Allowed,
ImplTraitContext::Universal,
hir::PredicateOrigin::ImplTrait,
);

View file

@ -212,11 +212,6 @@ ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier
ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax
.help = use `auto trait Trait {"{}"}` instead
ast_passes_optional_trait_object = `?Trait` is not permitted in trait object types
ast_passes_optional_trait_supertrait = `?Trait` is not permitted in supertraits
.note = traits are `?{$path_str}` by default
ast_passes_out_of_order_params = {$param_ord} parameters must be declared prior to {$max_param} parameters
.suggestion = reorder the parameters: lifetimes, then consts and types
@ -240,10 +235,10 @@ ast_passes_static_without_body =
ast_passes_tilde_const_disallowed = `[const]` is not allowed here
.closure = closures cannot have `[const]` trait bounds
.function = this function is not `const`, so it cannot have `[const]` trait bounds
.trait = this trait is not a `#[const_trait]`, so it cannot have `[const]` trait bounds
.trait = this trait is not `const`, so it cannot have `[const]` trait bounds
.trait_impl = this impl is not `const`, so it cannot have `[const]` trait bounds
.impl = inherent impls cannot have `[const]` trait bounds
.trait_assoc_ty = associated types in non-`#[const_trait]` traits cannot have `[const]` trait bounds
.trait_assoc_ty = associated types in non-`const` traits cannot have `[const]` trait bounds
.trait_impl_assoc_ty = associated types in non-const impls cannot have `[const]` trait bounds
.inherent_assoc_ty = inherent associated types cannot have `[const]` trait bounds
.object = trait objects cannot have `[const]` trait bounds

View file

@ -49,14 +49,14 @@ enum SelfSemantic {
}
enum TraitOrTraitImpl {
Trait { span: Span, constness_span: Option<Span> },
Trait { span: Span, constness: Const },
TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref_span: Span },
}
impl TraitOrTraitImpl {
fn constness(&self) -> Option<Span> {
match self {
Self::Trait { constness_span: Some(span), .. }
Self::Trait { constness: Const::Yes(span), .. }
| Self::TraitImpl { constness: Const::Yes(span), .. } => Some(*span),
_ => None,
}
@ -110,15 +110,10 @@ impl<'a> AstValidator<'a> {
self.outer_trait_or_trait_impl = old;
}
fn with_in_trait(
&mut self,
span: Span,
constness_span: Option<Span>,
f: impl FnOnce(&mut Self),
) {
fn with_in_trait(&mut self, span: Span, constness: Const, f: impl FnOnce(&mut Self)) {
let old = mem::replace(
&mut self.outer_trait_or_trait_impl,
Some(TraitOrTraitImpl::Trait { span, constness_span }),
Some(TraitOrTraitImpl::Trait { span, constness }),
);
f(self);
self.outer_trait_or_trait_impl = old;
@ -273,7 +268,7 @@ impl<'a> AstValidator<'a> {
};
let make_trait_const_sugg = if const_trait_impl
&& let TraitOrTraitImpl::Trait { span, constness_span: None } = parent
&& let TraitOrTraitImpl::Trait { span, constness: ast::Const::No } = parent
{
Some(span.shrink_to_lo())
} else {
@ -1131,10 +1126,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
visit::walk_item(self, item)
}
ItemKind::Trait(box Trait { is_auto, generics, ident, bounds, items, .. }) => {
ItemKind::Trait(box Trait {
constness,
is_auto,
generics,
ident,
bounds,
items,
..
}) => {
self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
let is_const_trait =
// FIXME(const_trait_impl) remove this
let alt_const_trait_span =
attr::find_by_name(&item.attrs, sym::const_trait).map(|attr| attr.span);
let constness = match (*constness, alt_const_trait_span) {
(Const::Yes(span), _) | (Const::No, Some(span)) => Const::Yes(span),
(Const::No, None) => Const::No,
};
if *is_auto == IsAuto::Yes {
// Auto traits cannot have generics, super traits nor contain items.
self.deny_generic_params(generics, ident.span);
@ -1145,13 +1153,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
// Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
// context for the supertraits.
let disallowed =
is_const_trait.is_none().then(|| TildeConstReason::Trait { span: item.span });
let disallowed = matches!(constness, ast::Const::No)
.then(|| TildeConstReason::Trait { span: item.span });
self.with_tilde_const(disallowed, |this| {
this.visit_generics(generics);
walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
});
self.with_in_trait(item.span, is_const_trait, |this| {
self.with_in_trait(item.span, constness, |this| {
walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait);
});
}
@ -1373,29 +1381,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
match bound {
GenericBound::Trait(trait_ref) => {
match (ctxt, trait_ref.modifiers.constness, trait_ref.modifiers.polarity) {
(BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_))
if !self.features.more_maybe_bounds() =>
{
self.sess
.create_feature_err(
errors::OptionalTraitSupertrait {
span: trait_ref.span,
path_str: pprust::path_to_string(&trait_ref.trait_ref.path),
},
sym::more_maybe_bounds,
)
.emit();
}
(BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_))
if !self.features.more_maybe_bounds() =>
{
self.sess
.create_feature_err(
errors::OptionalTraitObject { span: trait_ref.span },
sym::more_maybe_bounds,
)
.emit();
}
(
BoundKind::TraitObject,
BoundConstness::Always(_),

View file

@ -566,22 +566,6 @@ pub(crate) struct NestedLifetimes {
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(ast_passes_optional_trait_supertrait)]
#[note]
pub(crate) struct OptionalTraitSupertrait {
#[primary_span]
pub span: Span,
pub path_str: String,
}
#[derive(Diagnostic)]
#[diag(ast_passes_optional_trait_object)]
pub(crate) struct OptionalTraitObject {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(ast_passes_const_bound_trait_object)]
pub(crate) struct ConstBoundTraitObject {
@ -590,7 +574,7 @@ pub(crate) struct ConstBoundTraitObject {
}
// FIXME(const_trait_impl): Consider making the note/reason the message of the diagnostic.
// FIXME(const_trait_impl): Provide structured suggestions (e.g., add `const` / `#[const_trait]` here).
// FIXME(const_trait_impl): Provide structured suggestions (e.g., add `const` here).
#[derive(Diagnostic)]
#[diag(ast_passes_tilde_const_disallowed)]
pub(crate) struct TildeConstDisallowed {

View file

@ -357,6 +357,7 @@ impl<'a> State<'a> {
self.bclose(item.span, empty, cb);
}
ast::ItemKind::Trait(box ast::Trait {
constness,
safety,
is_auto,
ident,
@ -366,6 +367,7 @@ impl<'a> State<'a> {
}) => {
let (cb, ib) = self.head("");
self.print_visibility(&item.vis);
self.print_constness(*constness);
self.print_safety(*safety);
self.print_is_auto(*is_auto);
self.word_nbsp("trait");

View file

@ -110,6 +110,22 @@ pub enum DeprecatedSince {
Err,
}
#[derive(
Copy,
Debug,
Eq,
PartialEq,
Encodable,
Decodable,
Clone,
HashStable_Generic,
PrintAttribute
)]
pub enum CoverageStatus {
On,
Off,
}
impl Deprecation {
/// Whether an item marked with #[deprecated(since = "X")] is currently
/// deprecated (i.e., whether X is not greater than the current rustc
@ -274,6 +290,9 @@ pub enum AttributeKind {
/// Represents `#[const_trait]`.
ConstTrait(Span),
/// Represents `#[coverage]`.
Coverage(Span, CoverageStatus),
///Represents `#[rustc_deny_explicit_impl]`.
DenyExplicitImpl(Span),
@ -374,6 +393,9 @@ pub enum AttributeKind {
/// Represents `#[path]`
Path(Symbol, Span),
/// Represents `#[pointee]`
Pointee(Span),
/// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
PubTransparent(Span),
@ -417,6 +439,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_unsafe_specialization_marker]`.
UnsafeSpecializationMarker(Span),
/// Represents `#[unstable_feature_bound]`.
UnstableFeatureBound(ThinVec<(Symbol, Span)>),
/// Represents `#[used]`
Used { used_by: UsedBy, span: Span },
// tidy-alphabetical-end

View file

@ -28,6 +28,7 @@ impl AttributeKind {
ConstStability { .. } => Yes,
ConstStabilityIndirect => No,
ConstTrait(..) => No,
Coverage(..) => No,
DenyExplicitImpl(..) => No,
Deprecation { .. } => Yes,
DoNotImplementViaObject(..) => No,
@ -40,9 +41,9 @@ impl AttributeKind {
Fundamental { .. } => Yes,
Ignore { .. } => No,
Inline(..) => No,
LinkName { .. } => Yes,
LinkName { .. } => Yes, // Needed for rustdoc
LinkOrdinal { .. } => No,
LinkSection { .. } => No,
LinkSection { .. } => Yes, // Needed for rustdoc
LoopMatch(..) => No,
MacroTransparency(..) => Yes,
Marker(..) => No,
@ -50,13 +51,14 @@ impl AttributeKind {
MustUse { .. } => Yes,
Naked(..) => No,
NoImplicitPrelude(..) => No,
NoMangle(..) => No,
NonExhaustive(..) => Yes,
NoMangle(..) => Yes, // Needed for rustdoc
NonExhaustive(..) => Yes, // Needed for rustdoc
OmitGdbPrettyPrinterSection => No,
Optimize(..) => No,
ParenSugar(..) => No,
PassByValue(..) => Yes,
Path(..) => No,
Pointee(..) => No,
PubTransparent(..) => Yes,
Repr { .. } => No,
RustcLayoutScalarValidRangeEnd(..) => Yes,
@ -70,6 +72,7 @@ impl AttributeKind {
TrackCaller(..) => Yes,
TypeConst(..) => Yes,
UnsafeSpecializationMarker(..) => No,
UnstableFeatureBound(..) => No,
Used { .. } => No,
// tidy-alphabetical-end
}

View file

@ -24,7 +24,7 @@ use rustc_ast::token::CommentKind;
use rustc_ast::{AttrStyle, IntTy, UintTy};
use rustc_ast_pretty::pp::Printer;
use rustc_span::hygiene::Transparency;
use rustc_span::{Span, Symbol};
use rustc_span::{ErrorGuaranteed, Span, Symbol};
pub use stability::*;
use thin_vec::ThinVec;
pub use version::*;
@ -170,7 +170,7 @@ macro_rules! print_tup {
}
print_tup!(A B C D E F G H);
print_skip!(Span, ());
print_skip!(Span, (), ErrorGuaranteed);
print_disp!(u16, bool, NonZero<u32>);
print_debug!(Symbol, UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency);

View file

@ -1,7 +1,7 @@
use std::num::NonZero;
use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute};
use rustc_span::{Symbol, sym};
use rustc_span::{ErrorGuaranteed, Symbol, sym};
use crate::{PrintAttribute, RustcVersion};
@ -153,7 +153,7 @@ pub enum StableSince {
/// Stabilized in the upcoming version, whatever number that is.
Current,
/// Failed to parse a stabilization version.
Err,
Err(ErrorGuaranteed),
}
impl StabilityLevel {

View file

@ -136,6 +136,9 @@ attr_parsing_unrecognized_repr_hint =
attr_parsing_unstable_cfg_target_compact =
compact `cfg(target(..))` is experimental and subject to change
attr_parsing_unstable_feature_bound_incompatible_stability = Item annotated with `#[unstable_feature_bound]` should not be stable
.help = If this item is meant to be stable, do not use any functions annotated with `#[unstable_feature_bound]`. Otherwise, mark this item as unstable with `#[unstable]`
attr_parsing_unsupported_literal_cfg_boolean =
literal in `cfg` predicate value must be a boolean
attr_parsing_unsupported_literal_cfg_string =

View file

@ -27,6 +27,26 @@ impl<S: Stage> CombineAttributeParser<S> for AllowInternalUnstableParser {
}
}
pub(crate) struct UnstableFeatureBoundParser;
impl<S: Stage> CombineAttributeParser<S> for UnstableFeatureBoundParser {
const PATH: &'static [rustc_span::Symbol] = &[sym::unstable_feature_bound];
type Item = (Symbol, Span);
const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::UnstableFeatureBound(items);
const TEMPLATE: AttributeTemplate = template!(Word, List: "feat1, feat2, ...");
fn extend<'c>(
cx: &'c mut AcceptContext<'_, '_, S>,
args: &'c ArgParser<'_>,
) -> impl IntoIterator<Item = Self::Item> {
if !cx.features().staged_api() {
cx.emit_err(session_diagnostics::StabilityOutsideStd { span: cx.attr_span });
}
parse_unstable(cx, args, <Self as CombineAttributeParser<S>>::PATH[0])
.into_iter()
.zip(iter::repeat(cx.attr_span))
}
}
pub(crate) struct AllowConstFnUnstableParser;
impl<S: Stage> CombineAttributeParser<S> for AllowConstFnUnstableParser {
const PATH: &[Symbol] = &[sym::rustc_allow_const_fn_unstable];

View file

@ -9,7 +9,7 @@ use rustc_session::parse::feature_err;
use rustc_span::{Span, Symbol, sym};
use thin_vec::ThinVec;
use crate::context::{AcceptContext, Stage};
use crate::context::{AcceptContext, ShouldEmit, Stage};
use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, NameValueParser};
use crate::{
CfgMatchesLintEmitter, fluent_generated, parse_version, session_diagnostics, try_gate_cfg,
@ -90,7 +90,7 @@ fn parse_cfg_entry_version<S: Stage>(
list: &MetaItemListParser<'_>,
meta_span: Span,
) -> Option<CfgEntry> {
try_gate_cfg(sym::version, meta_span, cx.sess(), Some(cx.features()));
try_gate_cfg(sym::version, meta_span, cx.sess(), cx.features_option());
let Some(version) = list.single() else {
cx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral { span: list.span });
return None;
@ -119,7 +119,9 @@ fn parse_cfg_entry_target<S: Stage>(
list: &MetaItemListParser<'_>,
meta_span: Span,
) -> Option<CfgEntry> {
if !cx.features().cfg_target_compact() {
if let Some(features) = cx.features_option()
&& !features.cfg_target_compact()
{
feature_err(
cx.sess(),
sym::cfg_target_compact,
@ -186,12 +188,13 @@ pub fn eval_config_entry(
cfg_entry: &CfgEntry,
id: NodeId,
features: Option<&Features>,
emit_lints: ShouldEmit,
) -> EvalConfigResult {
match cfg_entry {
CfgEntry::All(subs, ..) => {
let mut all = None;
for sub in subs {
let res = eval_config_entry(sess, sub, id, features);
let res = eval_config_entry(sess, sub, id, features, emit_lints);
// We cannot short-circuit because `eval_config_entry` emits some lints
if !res.as_bool() {
all.get_or_insert(res);
@ -202,7 +205,7 @@ pub fn eval_config_entry(
CfgEntry::Any(subs, span) => {
let mut any = None;
for sub in subs {
let res = eval_config_entry(sess, sub, id, features);
let res = eval_config_entry(sess, sub, id, features, emit_lints);
// We cannot short-circuit because `eval_config_entry` emits some lints
if res.as_bool() {
any.get_or_insert(res);
@ -214,7 +217,7 @@ pub fn eval_config_entry(
})
}
CfgEntry::Not(sub, span) => {
if eval_config_entry(sess, sub, id, features).as_bool() {
if eval_config_entry(sess, sub, id, features, emit_lints).as_bool() {
EvalConfigResult::False { reason: cfg_entry.clone(), reason_span: *span }
} else {
EvalConfigResult::True
@ -228,24 +231,28 @@ pub fn eval_config_entry(
}
}
CfgEntry::NameValue { name, name_span, value, span } => {
match sess.psess.check_config.expecteds.get(name) {
Some(ExpectedValues::Some(values)) if !values.contains(&value.map(|(v, _)| v)) => {
id.emit_span_lint(
sess,
UNEXPECTED_CFGS,
*span,
BuiltinLintDiag::UnexpectedCfgValue((*name, *name_span), *value),
);
if let ShouldEmit::ErrorsAndLints = emit_lints {
match sess.psess.check_config.expecteds.get(name) {
Some(ExpectedValues::Some(values))
if !values.contains(&value.map(|(v, _)| v)) =>
{
id.emit_span_lint(
sess,
UNEXPECTED_CFGS,
*span,
BuiltinLintDiag::UnexpectedCfgValue((*name, *name_span), *value),
);
}
None if sess.psess.check_config.exhaustive_names => {
id.emit_span_lint(
sess,
UNEXPECTED_CFGS,
*span,
BuiltinLintDiag::UnexpectedCfgName((*name, *name_span), *value),
);
}
_ => { /* not unexpected */ }
}
None if sess.psess.check_config.exhaustive_names => {
id.emit_span_lint(
sess,
UNEXPECTED_CFGS,
*span,
BuiltinLintDiag::UnexpectedCfgName((*name, *name_span), *value),
);
}
_ => { /* not unexpected */ }
}
if sess.psess.config.contains(&(*name, value.map(|(v, _)| v))) {

View file

@ -1,4 +1,4 @@
use rustc_attr_data_structures::{AttributeKind, OptimizeAttr, UsedBy};
use rustc_attr_data_structures::{AttributeKind, CoverageStatus, OptimizeAttr, UsedBy};
use rustc_feature::{AttributeTemplate, template};
use rustc_session::parse::feature_err;
use rustc_span::{Span, Symbol, sym};
@ -52,6 +52,45 @@ impl<S: Stage> NoArgsAttributeParser<S> for ColdParser {
const CREATE: fn(Span) -> AttributeKind = AttributeKind::Cold;
}
pub(crate) struct CoverageParser;
impl<S: Stage> SingleAttributeParser<S> for CoverageParser {
const PATH: &[Symbol] = &[sym::coverage];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const TEMPLATE: AttributeTemplate = template!(OneOf: &[sym::off, sym::on]);
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
let Some(args) = args.list() else {
cx.expected_specific_argument_and_list(cx.attr_span, vec!["on", "off"]);
return None;
};
let Some(arg) = args.single() else {
cx.expected_single_argument(args.span);
return None;
};
let fail_incorrect_argument = |span| cx.expected_specific_argument(span, vec!["on", "off"]);
let Some(arg) = arg.meta_item() else {
fail_incorrect_argument(args.span);
return None;
};
let status = match arg.path().word_sym() {
Some(sym::off) => CoverageStatus::Off,
Some(sym::on) => CoverageStatus::On,
None | Some(_) => {
fail_incorrect_argument(arg.span());
return None;
}
};
Some(AttributeKind::Coverage(cx.attr_span, status))
}
}
pub(crate) struct ExportNameParser;
impl<S: Stage> SingleAttributeParser<S> for ExportNameParser {

View file

@ -98,6 +98,16 @@ impl<S: Stage> AttributeParser<S> for StabilityParser {
}
}
if let Some((Stability { level: StabilityLevel::Stable { .. }, .. }, _)) = self.stability {
for other_attr in cx.all_attrs {
if other_attr.word_is(sym::unstable_feature_bound) {
cx.emit_err(session_diagnostics::UnstableFeatureBoundIncompatibleStability {
span: cx.target_span,
});
}
}
}
let (stability, span) = self.stability?;
Some(AttributeKind::Stability { stability, span })
@ -282,12 +292,12 @@ pub(crate) fn parse_stability<S: Stage>(
} else if let Some(version) = parse_version(since) {
StableSince::Version(version)
} else {
cx.emit_err(session_diagnostics::InvalidSince { span: cx.attr_span });
StableSince::Err
let err = cx.emit_err(session_diagnostics::InvalidSince { span: cx.attr_span });
StableSince::Err(err)
}
} else {
cx.emit_err(session_diagnostics::MissingSince { span: cx.attr_span });
StableSince::Err
let err = cx.emit_err(session_diagnostics::MissingSince { span: cx.attr_span });
StableSince::Err(err)
};
match feature {

View file

@ -91,6 +91,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for DoNotImplementViaObjectParser {
const CREATE: fn(Span) -> AttributeKind = AttributeKind::DoNotImplementViaObject;
}
// FIXME(const_trait_impl): remove this
// Const traits
pub(crate) struct ConstTraitParser;
@ -145,3 +146,10 @@ impl<S: Stage> NoArgsAttributeParser<S> for FundamentalParser {
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Fundamental;
}
pub(crate) struct PointeeParser;
impl<S: Stage> NoArgsAttributeParser<S> for PointeeParser {
const PATH: &[Symbol] = &[sym::pointee];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::Pointee;
}

View file

@ -13,10 +13,13 @@ use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, HirI
use rustc_session::Session;
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser};
use crate::attributes::allow_unstable::{
AllowConstFnUnstableParser, AllowInternalUnstableParser, UnstableFeatureBoundParser,
};
use crate::attributes::codegen_attrs::{
ColdParser, ExportNameParser, NakedParser, NoMangleParser, OmitGdbPrettyPrinterSectionParser,
OptimizeParser, TargetFeatureParser, TrackCallerParser, UsedParser,
ColdParser, CoverageParser, ExportNameParser, NakedParser, NoMangleParser,
OmitGdbPrettyPrinterSectionParser, OptimizeParser, TargetFeatureParser, TrackCallerParser,
UsedParser,
};
use crate::attributes::confusables::ConfusablesParser;
use crate::attributes::deprecation::DeprecationParser;
@ -47,8 +50,8 @@ use crate::attributes::test_attrs::IgnoreParser;
use crate::attributes::traits::{
AllowIncoherentImplParser, CoherenceIsCoreParser, CoinductiveParser, ConstTraitParser,
DenyExplicitImplParser, DoNotImplementViaObjectParser, FundamentalParser, MarkerParser,
ParenSugarParser, SkipDuringMethodDispatchParser, SpecializationTraitParser, TypeConstParser,
UnsafeSpecializationMarkerParser,
ParenSugarParser, PointeeParser, SkipDuringMethodDispatchParser, SpecializationTraitParser,
TypeConstParser, UnsafeSpecializationMarkerParser,
};
use crate::attributes::transparency::TransparencyParser;
use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
@ -133,9 +136,11 @@ attribute_parsers!(
Combine<AllowInternalUnstableParser>,
Combine<ReprParser>,
Combine<TargetFeatureParser>,
Combine<UnstableFeatureBoundParser>,
// tidy-alphabetical-end
// tidy-alphabetical-start
Single<CoverageParser>,
Single<DeprecationParser>,
Single<DummyParser>,
Single<ExportNameParser>,
@ -177,6 +182,7 @@ attribute_parsers!(
Single<WithoutArgs<OmitGdbPrettyPrinterSectionParser>>,
Single<WithoutArgs<ParenSugarParser>>,
Single<WithoutArgs<PassByValueParser>>,
Single<WithoutArgs<PointeeParser>>,
Single<WithoutArgs<PubTransparentParser>>,
Single<WithoutArgs<SpecializationTraitParser>>,
Single<WithoutArgs<StdInternalSymbolParser>>,
@ -222,7 +228,7 @@ impl Stage for Early {
sess: &'sess Session,
diag: impl for<'x> Diagnostic<'x>,
) -> ErrorGuaranteed {
if self.emit_errors {
if self.emit_errors.should_emit() {
sess.dcx().emit_err(diag)
} else {
sess.dcx().create_err(diag).delay_as_bug()
@ -253,7 +259,7 @@ pub struct Early {
/// Whether to emit errors or delay them as a bug
/// For most attributes, the attribute will be parsed again in the `Late` stage and in this case the errors should be delayed
/// But for some, such as `cfg`, the attribute will be removed before the `Late` stage so errors must be emitted
pub emit_errors: bool,
pub emit_errors: ShouldEmit,
}
/// used when parsing attributes during ast lowering
pub struct Late;
@ -448,6 +454,25 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
reason: AttributeParseErrorReason::ExpectedSpecificArgument {
possibilities,
strings: false,
list: false,
},
})
}
pub(crate) fn expected_specific_argument_and_list(
&self,
span: Span,
possibilities: Vec<&'static str>,
) -> ErrorGuaranteed {
self.emit_err(AttributeParseError {
span,
attr_span: self.attr_span,
template: self.template.clone(),
attribute: self.attr_path.clone(),
reason: AttributeParseErrorReason::ExpectedSpecificArgument {
possibilities,
strings: false,
list: true,
},
})
}
@ -465,6 +490,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
reason: AttributeParseErrorReason::ExpectedSpecificArgument {
possibilities,
strings: true,
list: false,
},
})
}
@ -554,6 +580,25 @@ pub enum OmitDoc {
Skip,
}
#[derive(Copy, Clone)]
pub enum ShouldEmit {
/// The operation will emit errors and lints.
/// This is usually what you need.
ErrorsAndLints,
/// The operation will emit *not* errors and lints.
/// Use this if you are *sure* that this operation will be called at a different time with `ShouldEmit::Emit`.
Nothing,
}
impl ShouldEmit {
pub fn should_emit(&self) -> bool {
match self {
ShouldEmit::ErrorsAndLints => true,
ShouldEmit::Nothing => false,
}
}
}
/// Context created once, for example as part of the ast lowering
/// context, through which all attributes can be lowered.
pub struct AttributeParser<'sess, S: Stage = Late> {
@ -596,7 +641,7 @@ impl<'sess> AttributeParser<'sess, Early> {
tools: Vec::new(),
parse_only: Some(sym),
sess,
stage: Early { emit_errors: false },
stage: Early { emit_errors: ShouldEmit::Nothing },
};
let mut parsed = p.parse_attribute_list(
attrs,
@ -619,7 +664,7 @@ impl<'sess> AttributeParser<'sess, Early> {
target_span: Span,
target_node_id: NodeId,
features: Option<&'sess Features>,
emit_errors: bool,
emit_errors: ShouldEmit,
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> T,
template: &AttributeTemplate,
) -> T {

View file

@ -95,7 +95,7 @@ pub use attributes::cfg_old::*;
pub use attributes::util::{
find_crate_name, is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version,
};
pub use context::{AttributeParser, Early, Late, OmitDoc};
pub use context::{AttributeParser, Early, Late, OmitDoc, ShouldEmit};
pub use lints::emit_attribute_lint;
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }

View file

@ -503,6 +503,14 @@ pub(crate) struct UnrecognizedReprHint {
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_unstable_feature_bound_incompatible_stability)]
#[help]
pub(crate) struct UnstableFeatureBoundIncompatibleStability {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_naked_functions_incompatible_attribute, code = E0736)]
pub(crate) struct NakedFunctionIncompatibleAttribute {
@ -525,7 +533,9 @@ pub(crate) struct LinkOrdinalOutOfRange {
pub(crate) enum AttributeParseErrorReason {
ExpectedNoArgs,
ExpectedStringLiteral { byte_string: Option<Span> },
ExpectedStringLiteral {
byte_string: Option<Span>,
},
ExpectedIntegerLiteral,
ExpectedAtLeastOneArgument,
ExpectedSingleArgument,
@ -533,7 +543,12 @@ pub(crate) enum AttributeParseErrorReason {
UnexpectedLiteral,
ExpectedNameValue(Option<Symbol>),
DuplicateKey(Symbol),
ExpectedSpecificArgument { possibilities: Vec<&'static str>, strings: bool },
ExpectedSpecificArgument {
possibilities: Vec<&'static str>,
strings: bool,
/// Should we tell the user to write a list when they didn't?
list: bool,
},
}
pub(crate) struct AttributeParseError {
@ -607,7 +622,11 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
format!("expected this to be of the form `{name} = \"...\"`"),
);
}
AttributeParseErrorReason::ExpectedSpecificArgument { possibilities, strings } => {
AttributeParseErrorReason::ExpectedSpecificArgument {
possibilities,
strings,
list: false,
} => {
let quote = if strings { '"' } else { '`' };
match possibilities.as_slice() {
&[] => {}
@ -633,6 +652,38 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
}
}
}
AttributeParseErrorReason::ExpectedSpecificArgument {
possibilities,
strings,
list: true,
} => {
let quote = if strings { '"' } else { '`' };
match possibilities.as_slice() {
&[] => {}
&[x] => {
diag.span_label(
self.span,
format!(
"this attribute is only valid with {quote}{x}{quote} as an argument"
),
);
}
[first, second] => {
diag.span_label(self.span, format!("this attribute is only valid with either {quote}{first}{quote} or {quote}{second}{quote} as an argument"));
}
[first @ .., second_to_last, last] => {
let mut res = String::new();
for i in first {
res.push_str(&format!("{quote}{i}{quote}, "));
}
res.push_str(&format!(
"{quote}{second_to_last}{quote} or {quote}{last}{quote}"
));
diag.span_label(self.span, format!("this attribute is only valid with one of the following arguments: {res}"));
}
}
}
}
let suggestions = self.template.suggestions(false, &name);

View file

@ -1,3 +1,4 @@
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::LocalDefId;
use rustc_infer::infer::canonical::QueryRegionConstraints;
use rustc_infer::infer::outlives::env::RegionBoundPairs;
@ -7,7 +8,7 @@ use rustc_infer::infer::{InferCtxt, SubregionOrigin};
use rustc_infer::traits::query::type_op::DeeplyNormalize;
use rustc_middle::bug;
use rustc_middle::ty::{
self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions,
self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, elaborate, fold_regions,
};
use rustc_span::Span;
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
@ -70,10 +71,12 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
#[instrument(skip(self), level = "debug")]
pub(super) fn convert_all(&mut self, query_constraints: &QueryRegionConstraints<'tcx>) {
let QueryRegionConstraints { outlives } = query_constraints;
let QueryRegionConstraints { outlives, assumptions } = query_constraints;
let assumptions =
elaborate::elaborate_outlives_assumptions(self.infcx.tcx, assumptions.iter().copied());
for &(predicate, constraint_category) in outlives {
self.convert(predicate, constraint_category);
self.convert(predicate, constraint_category, &assumptions);
}
}
@ -112,15 +115,20 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
self.category = outlives_requirement.category;
self.span = outlives_requirement.blame_span;
self.convert(ty::OutlivesPredicate(subject, outlived_region), self.category);
self.convert(
ty::OutlivesPredicate(subject, outlived_region),
self.category,
&Default::default(),
);
}
(self.category, self.span, self.from_closure) = backup;
}
fn convert(
&mut self,
predicate: ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>,
predicate: ty::ArgOutlivesPredicate<'tcx>,
constraint_category: ConstraintCategory<'tcx>,
higher_ranked_assumptions: &FxHashSet<ty::ArgOutlivesPredicate<'tcx>>,
) {
let tcx = self.infcx.tcx;
debug!("generate: constraints at: {:#?}", self.locations);
@ -150,7 +158,15 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
}
let mut next_outlives_predicates = vec![];
for (ty::OutlivesPredicate(k1, r2), constraint_category) in outlives_predicates {
for (pred, constraint_category) in outlives_predicates {
// Constraint is implied by a coroutine's well-formedness.
if self.infcx.tcx.sess.opts.unstable_opts.higher_ranked_assumptions
&& higher_ranked_assumptions.contains(&pred)
{
continue;
}
let ty::OutlivesPredicate(k1, r2) = pred;
match k1.kind() {
GenericArgKind::Lifetime(r1) => {
let r1_vid = self.to_region_vid(r1);
@ -266,14 +282,15 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
&self,
ty: Ty<'tcx>,
next_outlives_predicates: &mut Vec<(
ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>,
ty::ArgOutlivesPredicate<'tcx>,
ConstraintCategory<'tcx>,
)>,
) -> Ty<'tcx> {
match self.param_env.and(DeeplyNormalize { value: ty }).fully_perform(self.infcx, self.span)
{
Ok(TypeOpOutput { output: ty, constraints, .. }) => {
if let Some(QueryRegionConstraints { outlives }) = constraints {
// FIXME(higher_ranked_auto): What should we do with the assumptions here?
if let Some(QueryRegionConstraints { outlives, assumptions: _ }) = constraints {
next_outlives_predicates.extend(outlives.iter().copied());
}
ty

View file

@ -131,6 +131,11 @@ pub(crate) fn type_check<'tcx>(
pre_obligations.is_empty(),
"there should be no incoming region obligations = {pre_obligations:#?}",
);
let pre_assumptions = infcx.take_registered_region_assumptions();
assert!(
pre_assumptions.is_empty(),
"there should be no incoming region assumptions = {pre_assumptions:#?}",
);
debug!(?normalized_inputs_and_output);

View file

@ -81,11 +81,11 @@ builtin_macros_cfg_accessible_literal_path = `cfg_accessible` path cannot be a l
builtin_macros_cfg_accessible_multiple_paths = multiple `cfg_accessible` paths are specified
builtin_macros_cfg_accessible_unspecified_path = `cfg_accessible` path is not specified
builtin_macros_cfg_select_no_matches = none of the rules in this `cfg_select` evaluated to true
builtin_macros_cfg_select_no_matches = none of the predicates in this `cfg_select` evaluated to true
builtin_macros_cfg_select_unreachable = unreachable rule
builtin_macros_cfg_select_unreachable = unreachable predicate
.label = always matches
.label2 = this rules is never reached
.label2 = this predicate is never reached
builtin_macros_coerce_pointee_requires_maybe_sized = `derive(CoercePointee)` requires `{$name}` to be marked `?Sized`

View file

@ -1,12 +1,12 @@
use rustc_ast::tokenstream::TokenStream;
use rustc_attr_parsing as attr;
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
use rustc_parse::parser::cfg_select::{CfgSelectBranches, CfgSelectRule, parse_cfg_select};
use rustc_parse::parser::cfg_select::{CfgSelectBranches, CfgSelectPredicate, parse_cfg_select};
use rustc_span::{Ident, Span, sym};
use crate::errors::{CfgSelectNoMatches, CfgSelectUnreachable};
/// Selects the first arm whose rule evaluates to true.
/// Selects the first arm whose predicate evaluates to true.
fn select_arm(ecx: &ExtCtxt<'_>, branches: CfgSelectBranches) -> Option<(TokenStream, Span)> {
for (cfg, tt, arm_span) in branches.reachable {
if attr::cfg_matches(
@ -30,11 +30,11 @@ pub(super) fn expand_cfg_select<'cx>(
ExpandResult::Ready(match parse_cfg_select(&mut ecx.new_parser_from_tts(tts)) {
Ok(branches) => {
if let Some((underscore, _, _)) = branches.wildcard {
// Warn for every unreachable rule. We store the fully parsed branch for rustfmt.
for (rule, _, _) in &branches.unreachable {
let span = match rule {
CfgSelectRule::Wildcard(underscore) => underscore.span,
CfgSelectRule::Cfg(cfg) => cfg.span(),
// Warn for every unreachable predicate. We store the fully parsed branch for rustfmt.
for (predicate, _, _) in &branches.unreachable {
let span = match predicate {
CfgSelectPredicate::Wildcard(underscore) => underscore.span,
CfgSelectPredicate::Cfg(cfg) => cfg.span(),
};
let err = CfgSelectUnreachable { span, wildcard_span: underscore.span };
ecx.dcx().emit_warn(err);
@ -50,7 +50,7 @@ pub(super) fn expand_cfg_select<'cx>(
Ident::with_dummy_span(sym::cfg_select),
);
} else {
// Emit a compiler error when none of the rules matched.
// Emit a compiler error when none of the predicates matched.
let guar = ecx.dcx().emit_err(CfgSelectNoMatches { span: sp });
DummyResult::any(sp, guar)
}

View file

@ -23,6 +23,7 @@ pub(crate) fn expand_deriving_copy(
methods: Vec::new(),
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
};
trait_def.expand(cx, mitem, item, push);
@ -46,6 +47,7 @@ pub(crate) fn expand_deriving_const_param_ty(
methods: Vec::new(),
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
};
trait_def.expand(cx, mitem, item, push);
@ -60,6 +62,7 @@ pub(crate) fn expand_deriving_const_param_ty(
methods: Vec::new(),
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
};
trait_def.expand(cx, mitem, item, push);
@ -83,6 +86,7 @@ pub(crate) fn expand_deriving_unsized_const_param_ty(
methods: Vec::new(),
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
};
trait_def.expand(cx, mitem, item, push);

View file

@ -87,6 +87,7 @@ pub(crate) fn expand_deriving_clone(
}],
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
};
trait_def.expand_ext(cx, mitem, item, push, is_simple)

View file

@ -43,6 +43,7 @@ pub(crate) fn expand_deriving_eq(
}],
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
};
trait_def.expand_ext(cx, mitem, item, push, true)
}

View file

@ -34,6 +34,7 @@ pub(crate) fn expand_deriving_ord(
}],
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
};
trait_def.expand(cx, mitem, item, push)

View file

@ -30,6 +30,7 @@ pub(crate) fn expand_deriving_partial_eq(
methods: Vec::new(),
associated_types: Vec::new(),
is_const: false,
is_staged_api_crate: cx.ecfg.features.staged_api(),
};
structural_trait_def.expand(cx, mitem, item, push);
@ -58,6 +59,7 @@ pub(crate) fn expand_deriving_partial_eq(
methods,
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
};
trait_def.expand(cx, mitem, item, push)
}

View file

@ -64,6 +64,7 @@ pub(crate) fn expand_deriving_partial_ord(
methods: vec![partial_cmp_def],
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
};
trait_def.expand(cx, mitem, item, push)
}

View file

@ -41,6 +41,7 @@ pub(crate) fn expand_deriving_debug(
}],
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
};
trait_def.expand(cx, mitem, item, push)
}

View file

@ -51,6 +51,7 @@ pub(crate) fn expand_deriving_default(
}],
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
};
trait_def.expand(cx, mitem, item, push)
}

View file

@ -181,9 +181,11 @@ use std::{iter, vec};
pub(crate) use StaticFields::*;
pub(crate) use SubstructureFields::*;
use rustc_ast::ptr::P;
use rustc_ast::token::{IdentIsRaw, LitKind, Token, TokenKind};
use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenTree};
use rustc_ast::{
self as ast, AnonConst, BindingMode, ByRef, EnumDef, Expr, GenericArg, GenericParamKind,
Generics, Mutability, PatKind, VariantData,
self as ast, AnonConst, AttrArgs, BindingMode, ByRef, DelimArgs, EnumDef, Expr, GenericArg,
GenericParamKind, Generics, Mutability, PatKind, Safety, VariantData,
};
use rustc_attr_data_structures::{AttributeKind, ReprPacked};
use rustc_attr_parsing::AttributeParser;
@ -222,6 +224,8 @@ pub(crate) struct TraitDef<'a> {
pub associated_types: Vec<(Ident, Ty)>,
pub is_const: bool,
pub is_staged_api_crate: bool,
}
pub(crate) struct MethodDef<'a> {
@ -784,8 +788,45 @@ impl<'a> TraitDef<'a> {
// Create the type of `self`.
let path = cx.path_all(self.span, false, vec![type_ident], self_params);
let self_type = cx.ty_path(path);
let rustc_const_unstable =
cx.path_ident(self.span, Ident::new(sym::rustc_const_unstable, self.span));
let mut attrs = thin_vec![cx.attr_word(sym::automatically_derived, self.span),];
// Only add `rustc_const_unstable` attributes if `derive_const` is used within libcore/libstd,
// Other crates don't need stability attributes, so adding them is not useful, but libcore needs them
// on all const trait impls.
if self.is_const && self.is_staged_api_crate {
attrs.push(
cx.attr_nested(
rustc_ast::AttrItem {
unsafety: Safety::Default,
path: rustc_const_unstable,
args: AttrArgs::Delimited(DelimArgs {
dspan: DelimSpan::from_single(self.span),
delim: rustc_ast::token::Delimiter::Parenthesis,
tokens: [
TokenKind::Ident(sym::feature, IdentIsRaw::No),
TokenKind::Eq,
TokenKind::lit(LitKind::Str, sym::derive_const, None),
TokenKind::Comma,
TokenKind::Ident(sym::issue, IdentIsRaw::No),
TokenKind::Eq,
TokenKind::lit(LitKind::Str, sym::derive_const_issue, None),
]
.into_iter()
.map(|kind| {
TokenTree::Token(Token { kind, span: self.span }, Spacing::Alone)
})
.collect(),
}),
tokens: None,
},
self.span,
),
)
}
let attrs = thin_vec![cx.attr_word(sym::automatically_derived, self.span),];
let opt_trait_ref = Some(trait_ref);
cx.item(

View file

@ -41,6 +41,7 @@ pub(crate) fn expand_deriving_hash(
}],
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
};
hash_trait_def.expand(cx, mitem, item, push);

View file

@ -4,8 +4,8 @@ use std::sync::Arc;
use rustc_ast as ast;
use rustc_ast::ptr::P;
use rustc_ast::token;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{join_path_idents, token};
use rustc_ast_pretty::pprust;
use rustc_expand::base::{
DummyResult, ExpandResult, ExtCtxt, MacEager, MacResult, MacroExpanderResult, resolve_path,
@ -100,7 +100,7 @@ pub(crate) fn expand_mod(
let sp = cx.with_def_site_ctxt(sp);
check_zero_tts(cx, sp, tts, "module_path!");
let mod_path = &cx.current_expansion.module.mod_path;
let string = mod_path.iter().map(|x| x.to_string()).collect::<Vec<String>>().join("::");
let string = join_path_idents(mod_path);
ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&string))))
}

View file

@ -5,7 +5,7 @@ use std::assert_matches::assert_matches;
use std::iter;
use rustc_ast::ptr::P;
use rustc_ast::{self as ast, GenericParamKind, attr};
use rustc_ast::{self as ast, GenericParamKind, attr, join_path_idents};
use rustc_ast_pretty::pprust;
use rustc_errors::{Applicability, Diag, Level};
use rustc_expand::base::*;
@ -446,12 +446,7 @@ fn get_location_info(cx: &ExtCtxt<'_>, fn_: &ast::Fn) -> (Symbol, usize, usize,
}
fn item_path(mod_path: &[Ident], item_ident: &Ident) -> String {
mod_path
.iter()
.chain(iter::once(item_ident))
.map(|x| x.to_string())
.collect::<Vec<String>>()
.join("::")
join_path_idents(mod_path.iter().chain(iter::once(item_ident)))
}
enum ShouldPanic {

View file

@ -11,6 +11,12 @@
#[derive(Copy, Clone, PartialEq, Debug)]
struct f32x4(pub [f32; 4]);
impl f32x4 {
fn into_array(self) -> [f32; 4] {
unsafe { std::mem::transmute(self) }
}
}
use std::intrinsics::simd::*;
fn main() {
@ -29,22 +35,22 @@ fn main() {
unsafe {
let min0 = simd_fmin(x, y);
let min1 = simd_fmin(y, x);
assert_eq!(min0, min1);
assert_eq!(min0.into_array(), min1.into_array());
let e = f32x4([1.0, 1.0, 3.0, 3.0]);
assert_eq!(min0, e);
assert_eq!(min0.into_array(), e.into_array());
let minn = simd_fmin(x, n);
assert_eq!(minn, x);
assert_eq!(minn.into_array(), x.into_array());
let minn = simd_fmin(y, n);
assert_eq!(minn, y);
assert_eq!(minn.into_array(), y.into_array());
let max0 = simd_fmax(x, y);
let max1 = simd_fmax(y, x);
assert_eq!(max0, max1);
assert_eq!(max0.into_array(), max1.into_array());
let e = f32x4([2.0, 2.0, 4.0, 4.0]);
assert_eq!(max0, e);
assert_eq!(max0.into_array(), e.into_array());
let maxn = simd_fmax(x, n);
assert_eq!(maxn, x);
assert_eq!(maxn.into_array(), x.into_array());
let maxn = simd_fmax(y, n);
assert_eq!(maxn, y);
assert_eq!(maxn.into_array(), y.into_array());
}
}

View file

@ -348,7 +348,8 @@ fn main() {
struct V([f64; 2]);
let f = V([0.0, 1.0]);
let _a = f.0[0];
let fp = (&raw const f) as *const [f64; 2];
let _a = (unsafe { &*fp })[0];
stack_val_align();
}

View file

@ -530,8 +530,8 @@ fn codegen_cgu_content(
for (mono_item, item_data) in mono_items {
match mono_item {
MonoItem::Fn(instance) => {
if tcx.codegen_fn_attrs(instance.def_id()).flags.contains(CodegenFnAttrFlags::NAKED)
{
let flags = tcx.codegen_instance_attrs(instance.def).flags;
if flags.contains(CodegenFnAttrFlags::NAKED) {
rustc_codegen_ssa::mir::naked_asm::codegen_naked_asm(
&mut GlobalAsmContext { tcx, global_asm: &mut cx.global_asm },
instance,

View file

@ -127,7 +127,7 @@ fn codegen_and_compile_fn<'tcx>(
module: &mut dyn Module,
instance: Instance<'tcx>,
) {
if tcx.codegen_fn_attrs(instance.def_id()).flags.contains(CodegenFnAttrFlags::NAKED) {
if tcx.codegen_instance_attrs(instance.def).flags.contains(CodegenFnAttrFlags::NAKED) {
tcx.dcx()
.span_fatal(tcx.def_span(instance.def_id()), "Naked asm is not supported in JIT mode");
}

View file

@ -35,7 +35,7 @@ fn predefine_mono_items<'tcx>(
is_compiler_builtins,
);
let is_naked = tcx
.codegen_fn_attrs(instance.def_id())
.codegen_instance_attrs(instance.def)
.flags
.contains(CodegenFnAttrFlags::NAKED);
module

View file

@ -14,8 +14,6 @@ permissions:
env:
# Enable backtraces for easier debugging
RUST_BACKTRACE: 1
# TODO: remove when confish.sh is removed.
OVERWRITE_TARGET_TRIPLE: m68k-unknown-linux-gnu
jobs:
build:
@ -59,14 +57,12 @@ jobs:
- name: Setup path to libgccjit
run: |
sudo dpkg -i gcc-m68k-15.deb
sudo dpkg --force-overwrite -i gcc-m68k-15.deb
echo 'gcc-path = "/usr/lib/"' > config.toml
- name: Set env
run: |
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
#- name: Cache rust repository
## We only clone the rust repository for rustc tests
@ -86,16 +82,20 @@ jobs:
- name: Build sample project with target defined as JSON spec
run: |
./y.sh prepare --only-libcore --cross
./y.sh build --sysroot --features compiler_builtins/no-f16-f128 --target-triple m68k-unknown-linux-gnu --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
./y.sh cargo build --manifest-path=./tests/hello-world/Cargo.toml --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
./y.sh build --sysroot --features compiler-builtins-no-f16-f128 --target-triple m68k-unknown-linux-gnu --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ./y.sh cargo build --manifest-path=./tests/hello-world/Cargo.toml --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
./y.sh clean all
- name: Build
run: |
./y.sh prepare --only-libcore --cross
./y.sh build --sysroot --features compiler_builtins/no-f16-f128 --target-triple m68k-unknown-linux-gnu
./y.sh test --mini-tests
CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu ./y.sh test --cargo-tests
./y.sh build --sysroot --features compiler-builtins-no-f16-f128 --target-triple m68k-unknown-linux-gnu
./y.sh test --mini-tests --target-triple m68k-unknown-linux-gnu
# FIXME: since https://github.com/rust-lang/rust/pull/140809, we cannot run programs for architectures not
# supported by the object crate, since this adds a dependency on symbols.o for the panic runtime.
# And as such, a wrong order of the object files in the linker command now fails with an undefined reference
# to some symbols like __rustc::rust_panic.
#CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu ./y.sh test --cargo-tests --target-triple m68k-unknown-linux-gnu
./y.sh clean all
- name: Prepare dependencies
@ -104,9 +104,23 @@ jobs:
git config --global user.name "User"
./y.sh prepare --cross
- name: Run tests
run: |
./y.sh test --release --clean --build-sysroot --sysroot-features compiler_builtins/no-f16-f128 ${{ matrix.commands }}
# FIXME: We cannot run programs for architectures not supported by the object crate. See comment above.
#- name: Run tests
#run: |
#./y.sh test --target-triple m68k-unknown-linux-gnu --release --clean --build-sysroot --sysroot-features compiler-builtins-no-f16-f128 ${{ matrix.commands }}
# FIXME: We cannot run programs for architectures not supported by the object crate. See comment above.
#- name: Run Hello World!
#run: |
#./y.sh build --target-triple m68k-unknown-linux-gnu
#vm_dir=$(pwd)/vm
#cd tests/hello-world
#CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ../../y.sh cargo build --target m68k-unknown-linux-gnu
#sudo cp target/m68k-unknown-linux-gnu/debug/hello_world $vm_dir/home/
#sudo chroot $vm_dir qemu-m68k-static /home/hello_world > hello_world_stdout
#expected_output="40"
#test $(cat hello_world_stdout) == $expected_output || (echo "Output differs. Actual output: $(cat hello_world_stdout)"; exit 1)
# Summary job for the merge queue.
# ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!

View file

@ -78,7 +78,8 @@ jobs:
- name: Run tests
run: |
# FIXME(antoyo): we cannot enable LTO for stdarch tests currently because of some failing LTO tests using proc-macros.
echo -n 'lto = "fat"' >> build_system/build_sysroot/Cargo.toml
# FIXME(antoyo): this should probably not be needed since we embed the LTO bitcode.
printf '[profile.release]\nlto = "fat"\n' >> build/build_sysroot/sysroot_src/library/Cargo.toml
EMBED_LTO_BITCODE=1 ./y.sh test --release --clean --release-sysroot --build-sysroot --keep-lto-tests ${{ matrix.commands }}
- name: Run y.sh cargo build

View file

@ -1,502 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "addr2line"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
dependencies = [
"compiler_builtins",
"gimli",
"rustc-std-workspace-alloc",
"rustc-std-workspace-core",
]
[[package]]
name = "adler2"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-core",
]
[[package]]
name = "alloc"
version = "0.0.0"
dependencies = [
"compiler_builtins",
"core",
]
[[package]]
name = "alloctests"
version = "0.0.0"
dependencies = [
"rand",
"rand_xorshift",
]
[[package]]
name = "cc"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8"
dependencies = [
"shlex",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-core",
]
[[package]]
name = "compiler_builtins"
version = "0.1.160"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6376049cfa92c0aa8b9ac95fae22184b981c658208d4ed8a1dc553cd83612895"
dependencies = [
"cc",
"rustc-std-workspace-core",
]
[[package]]
name = "core"
version = "0.0.0"
[[package]]
name = "coretests"
version = "0.0.0"
dependencies = [
"rand",
"rand_xorshift",
]
[[package]]
name = "dlmalloc"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cff88b751e7a276c4ab0e222c3f355190adc6dde9ce39c851db39da34990df7"
dependencies = [
"cfg-if",
"compiler_builtins",
"libc",
"rustc-std-workspace-core",
"windows-sys",
]
[[package]]
name = "fortanix-sgx-abi"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57cafc2274c10fab234f176b25903ce17e690fca7597090d50880e047a0389c5"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-core",
]
[[package]]
name = "getopts"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
dependencies = [
"rustc-std-workspace-core",
"rustc-std-workspace-std",
"unicode-width",
]
[[package]]
name = "gimli"
version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-alloc",
"rustc-std-workspace-core",
]
[[package]]
name = "hashbrown"
version = "0.15.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-alloc",
"rustc-std-workspace-core",
]
[[package]]
name = "hermit-abi"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-alloc",
"rustc-std-workspace-core",
]
[[package]]
name = "libc"
version = "0.2.172"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
dependencies = [
"rustc-std-workspace-core",
]
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-core",
]
[[package]]
name = "miniz_oxide"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
dependencies = [
"adler2",
"compiler_builtins",
"rustc-std-workspace-alloc",
"rustc-std-workspace-core",
]
[[package]]
name = "object"
version = "0.36.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
dependencies = [
"compiler_builtins",
"memchr",
"rustc-std-workspace-alloc",
"rustc-std-workspace-core",
]
[[package]]
name = "panic_abort"
version = "0.0.0"
dependencies = [
"alloc",
"compiler_builtins",
"core",
"libc",
]
[[package]]
name = "panic_unwind"
version = "0.0.0"
dependencies = [
"alloc",
"cfg-if",
"compiler_builtins",
"core",
"libc",
"unwind",
]
[[package]]
name = "proc_macro"
version = "0.0.0"
dependencies = [
"core",
"rustc-literal-escaper",
"std",
]
[[package]]
name = "profiler_builtins"
version = "0.0.0"
dependencies = [
"cc",
]
[[package]]
name = "r-efi"
version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-core",
]
[[package]]
name = "r-efi-alloc"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e43c53ff1a01d423d1cb762fd991de07d32965ff0ca2e4f80444ac7804198203"
dependencies = [
"compiler_builtins",
"r-efi",
"rustc-std-workspace-core",
]
[[package]]
name = "rand"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
dependencies = [
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
[[package]]
name = "rand_xorshift"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a"
dependencies = [
"rand_core",
]
[[package]]
name = "rustc-demangle"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-core",
]
[[package]]
name = "rustc-literal-escaper"
version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0041b6238913c41fe704213a4a9329e2f685a156d1781998128b4149c230ad04"
dependencies = [
"rustc-std-workspace-std",
]
[[package]]
name = "rustc-std-workspace-alloc"
version = "1.99.0"
dependencies = [
"alloc",
]
[[package]]
name = "rustc-std-workspace-core"
version = "1.99.0"
dependencies = [
"core",
]
[[package]]
name = "rustc-std-workspace-std"
version = "1.99.0"
dependencies = [
"std",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "std"
version = "0.0.0"
dependencies = [
"addr2line",
"alloc",
"cfg-if",
"compiler_builtins",
"core",
"dlmalloc",
"fortanix-sgx-abi",
"hashbrown",
"hermit-abi",
"libc",
"miniz_oxide",
"object",
"panic_abort",
"panic_unwind",
"r-efi",
"r-efi-alloc",
"rand",
"rand_xorshift",
"rustc-demangle",
"std_detect",
"unwind",
"wasi",
"windows-targets 0.0.0",
]
[[package]]
name = "std_detect"
version = "0.1.5"
dependencies = [
"cfg-if",
"compiler_builtins",
"libc",
"rustc-std-workspace-alloc",
"rustc-std-workspace-core",
]
[[package]]
name = "sysroot"
version = "0.0.0"
dependencies = [
"proc_macro",
"profiler_builtins",
"std",
"test",
]
[[package]]
name = "test"
version = "0.0.0"
dependencies = [
"core",
"getopts",
"libc",
"std",
]
[[package]]
name = "unicode-width"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-core",
"rustc-std-workspace-std",
]
[[package]]
name = "unwind"
version = "0.0.0"
dependencies = [
"cfg-if",
"compiler_builtins",
"core",
"libc",
"unwinding",
]
[[package]]
name = "unwinding"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8393f2782b6060a807337ff353780c1ca15206f9ba2424df18cb6e733bd7b345"
dependencies = [
"compiler_builtins",
"gimli",
"rustc-std-workspace-core",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-alloc",
"rustc-std-workspace-core",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-targets"
version = "0.0.0"
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"

View file

@ -1,39 +0,0 @@
[package]
authors = ["rustc_codegen_gcc devs"]
name = "sysroot"
version = "0.0.0"
resolver = "2"
[dependencies]
core = { path = "./sysroot_src/library/core" }
compiler_builtins = { path = "./sysroot_src/library/compiler-builtins/compiler-builtins" }
alloc = { path = "./sysroot_src/library/alloc" }
std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] }
test = { path = "./sysroot_src/library/test" }
proc_macro = { path = "./sysroot_src/library/proc_macro" }
[patch.crates-io]
rustc-std-workspace-core = { path = "./sysroot_src/library/rustc-std-workspace-core" }
rustc-std-workspace-alloc = { path = "./sysroot_src/library/rustc-std-workspace-alloc" }
rustc-std-workspace-std = { path = "./sysroot_src/library/rustc-std-workspace-std" }
compiler_builtins = { path = "./sysroot_src/library/compiler-builtins/compiler-builtins" }
# For compiler-builtins we always use a high number of codegen units.
# The goal here is to place every single intrinsic into its own object
# file to avoid symbol clashes with the system libgcc if possible. Note
# that this number doesn't actually produce this many object files, we
# just don't create more than this number of object files.
#
# It's a bit of a bummer that we have to pass this here, unfortunately.
# Ideally this would be specified through an env var to Cargo so Cargo
# knows how many CGUs are for this specific crate, but for now
# per-crate configuration isn't specifiable in the environment.
[profile.dev.package.compiler_builtins]
codegen-units = 10000
[profile.release.package.compiler_builtins]
codegen-units = 10000
[profile.release]
debug = "limited"
#lto = "fat" # TODO(antoyo): re-enable when the failing LTO tests regarding proc-macros are fixed.

View file

@ -5,7 +5,7 @@ use std::path::Path;
use crate::config::{Channel, ConfigInfo};
use crate::utils::{
copy_file, create_dir, get_sysroot_dir, run_command, run_command_with_output_and_env, walk_dir,
create_dir, get_sysroot_dir, run_command, run_command_with_output_and_env, walk_dir,
};
#[derive(Default)]
@ -53,11 +53,11 @@ impl BuildArg {
}
}
fn cleanup_sysroot_previous_build(start_dir: &Path) {
fn cleanup_sysroot_previous_build(library_dir: &Path) {
// Cleanup for previous run
// Clean target dir except for build scripts and incremental cache
let _ = walk_dir(
start_dir.join("target"),
library_dir.join("target"),
&mut |dir: &Path| {
for top in &["debug", "release"] {
let _ = fs::remove_dir_all(dir.join(top).join("build"));
@ -95,31 +95,13 @@ fn cleanup_sysroot_previous_build(start_dir: &Path) {
&mut |_| Ok(()),
false,
);
let _ = fs::remove_file(start_dir.join("Cargo.lock"));
let _ = fs::remove_file(start_dir.join("test_target/Cargo.lock"));
let _ = fs::remove_dir_all(start_dir.join("sysroot"));
}
pub fn create_build_sysroot_content(start_dir: &Path) -> Result<(), String> {
if !start_dir.is_dir() {
create_dir(start_dir)?;
}
copy_file("build_system/build_sysroot/Cargo.toml", start_dir.join("Cargo.toml"))?;
copy_file("build_system/build_sysroot/Cargo.lock", start_dir.join("Cargo.lock"))?;
let src_dir = start_dir.join("src");
if !src_dir.is_dir() {
create_dir(&src_dir)?;
}
copy_file("build_system/build_sysroot/lib.rs", start_dir.join("src/lib.rs"))
}
pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Result<(), String> {
let start_dir = get_sysroot_dir();
cleanup_sysroot_previous_build(&start_dir);
create_build_sysroot_content(&start_dir)?;
let library_dir = start_dir.join("sysroot_src").join("library");
cleanup_sysroot_previous_build(&library_dir);
// Builds libs
let mut rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default();
@ -157,9 +139,13 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
rustflags.push_str(&cg_rustflags);
}
args.push(&"--features");
args.push(&"backtrace");
let mut env = env.clone();
env.insert("RUSTFLAGS".to_string(), rustflags);
run_command_with_output_and_env(&args, Some(&start_dir), Some(&env))?;
let sysroot_dir = library_dir.join("sysroot");
run_command_with_output_and_env(&args, Some(&sysroot_dir), Some(&env))?;
// Copy files to sysroot
let sysroot_path = start_dir.join(format!("sysroot/lib/rustlib/{}/lib/", config.target_triple));
@ -169,7 +155,7 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
run_command(&[&"cp", &"-r", &dir_to_copy, &sysroot_path], None).map(|_| ())
};
walk_dir(
start_dir.join(format!("target/{}/{}/deps", config.target_triple, channel)),
library_dir.join(format!("target/{}/{}/deps", config.target_triple, channel)),
&mut copier.clone(),
&mut copier,
false,
@ -178,7 +164,7 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
// Copy the source files to the sysroot (Rust for Linux needs this).
let sysroot_src_path = start_dir.join("sysroot/lib/rustlib/src/rust");
create_dir(&sysroot_src_path)?;
run_command(&[&"cp", &"-r", &start_dir.join("sysroot_src/library/"), &sysroot_src_path], None)?;
run_command(&[&"cp", &"-r", &library_dir, &sysroot_src_path], None)?;
Ok(())
}

View file

@ -352,11 +352,6 @@ impl ConfigInfo {
None => return Err("no host found".to_string()),
};
if self.target_triple.is_empty()
&& let Some(overwrite) = env.get("OVERWRITE_TARGET_TRIPLE")
{
self.target_triple = overwrite.clone();
}
if self.target_triple.is_empty() {
self.target_triple = self.host_triple.clone();
}

View file

@ -303,19 +303,6 @@ pub fn create_dir<P: AsRef<Path>>(path: P) -> Result<(), String> {
})
}
pub fn copy_file<F: AsRef<Path>, T: AsRef<Path>>(from: F, to: T) -> Result<(), String> {
fs::copy(&from, &to)
.map_err(|error| {
format!(
"Failed to copy file `{}` into `{}`: {:?}",
from.as_ref().display(),
to.as_ref().display(),
error
)
})
.map(|_| ())
}
/// This function differs from `git_clone` in how it handles *where* the repository will be cloned.
/// In `git_clone`, it is cloned in the provided path. In this function, the path you provide is
/// the parent folder. So if you pass "a" as folder and try to clone "b.git", it will be cloned into

View file

@ -62,14 +62,14 @@ generate it in [gimple.md](./doc/gimple.md).
* Run `./y.sh prepare --cross` so that the sysroot is patched for the cross-compiling case.
* Set the path to the cross-compiling libgccjit in `gcc-path` (in `config.toml`).
* Make sure you have the linker for your target (for instance `m68k-unknown-linux-gnu-gcc`) in your `$PATH`. Currently, the linker name is hardcoded as being `$TARGET-gcc`. Specify the target when building the sysroot: `./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu`.
* Build your project by specifying the target: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../y.sh cargo build --target m68k-unknown-linux-gnu`.
* Make sure you have the linker for your target (for instance `m68k-unknown-linux-gnu-gcc`) in your `$PATH`. You can specify which linker to use via `CG_RUSTFLAGS="-Clinker=<linker>"`, for instance: `CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc"`. Specify the target when building the sysroot: `./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu`.
* Build your project by specifying the target and the linker to use: `CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ../y.sh cargo build --target m68k-unknown-linux-gnu`.
If the target is not yet supported by the Rust compiler, create a [target specification file](https://docs.rust-embedded.org/embedonomicon/custom-target.html) (note that the `arch` specified in this file must be supported by the rust compiler).
Then, you can use it the following way:
* Add the target specification file using `--target` as an **absolute** path to build the sysroot: `./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu --target $(pwd)/m68k-unknown-linux-gnu.json`
* Build your project by specifying the target specification file: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../y.sh cargo build --target path/to/m68k-unknown-linux-gnu.json`.
* Build your project by specifying the target specification file: `../y.sh cargo build --target path/to/m68k-unknown-linux-gnu.json`.
If you get the following error:

View file

@ -6,7 +6,7 @@
)]
#![no_core]
#![allow(dead_code, internal_features, non_camel_case_types)]
#![rustfmt::skip]
#![rustfmt_skip]
extern crate mini_core;
@ -198,10 +198,17 @@ fn main() {
assert_eq!(intrinsics::align_of::<u16>() as u8, 2);
assert_eq!(intrinsics::align_of_val(&a) as u8, intrinsics::align_of::<&str>() as u8);
assert!(!const { intrinsics::needs_drop::<u8>() });
assert!(!const { intrinsics::needs_drop::<[u8]>() });
assert!(const { intrinsics::needs_drop::<NoisyDrop>() });
assert!(const { intrinsics::needs_drop::<NoisyDropUnsized>() });
/*
* TODO: re-enable in the next sync.
let u8_needs_drop = const { intrinsics::needs_drop::<u8>() };
assert!(!u8_needs_drop);
let slice_needs_drop = const { intrinsics::needs_drop::<[u8]>() };
assert!(!slice_needs_drop);
let noisy_drop = const { intrinsics::needs_drop::<NoisyDrop>() };
assert!(noisy_drop);
let noisy_unsized_drop = const { intrinsics::needs_drop::<NoisyDropUnsized>() };
assert!(noisy_unsized_drop);
*/
Unique {
pointer: 0 as *const &str,

View file

@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2025-06-28"
channel = "nightly-2025-07-04"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]

View file

@ -87,7 +87,7 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
#[cfg_attr(not(feature = "master"), allow(unused_variables))] func: Function<'gcc>,
instance: ty::Instance<'tcx>,
) {
let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id());
let codegen_fn_attrs = cx.tcx.codegen_instance_attrs(instance.def);
#[cfg(feature = "master")]
{

View file

@ -24,7 +24,7 @@ use std::sync::Arc;
use gccjit::{Context, OutputKind};
use object::read::archive::ArchiveFile;
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared};
use rustc_codegen_ssa::back::symbol_export;
use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput};
use rustc_codegen_ssa::traits::*;
@ -176,7 +176,7 @@ pub(crate) fn run_fat(
cgcx: &CodegenContext<GccCodegenBackend>,
modules: Vec<FatLtoInput<GccCodegenBackend>>,
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
) -> Result<LtoModuleCodegen<GccCodegenBackend>, FatalError> {
) -> Result<ModuleCodegen<GccContext>, FatalError> {
let dcx = cgcx.create_dcx();
let dcx = dcx.handle();
let lto_data = prepare_lto(cgcx, dcx)?;
@ -201,7 +201,7 @@ fn fat_lto(
mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
tmp_path: TempDir,
//symbols_below_threshold: &[String],
) -> Result<LtoModuleCodegen<GccCodegenBackend>, FatalError> {
) -> Result<ModuleCodegen<GccContext>, FatalError> {
let _timer = cgcx.prof.generic_activity("GCC_fat_lto_build_monolithic_module");
info!("going for a fat lto");
@ -334,7 +334,7 @@ fn fat_lto(
// of now.
module.module_llvm.temp_dir = Some(tmp_path);
Ok(LtoModuleCodegen::Fat(module))
Ok(module)
}
pub struct ModuleBuffer(PathBuf);
@ -358,7 +358,7 @@ pub(crate) fn run_thin(
cgcx: &CodegenContext<GccCodegenBackend>,
modules: Vec<(String, ThinBuffer)>,
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
) -> Result<(Vec<LtoModuleCodegen<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
) -> Result<(Vec<ThinModule<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
let dcx = cgcx.create_dcx();
let dcx = dcx.handle();
let lto_data = prepare_lto(cgcx, dcx)?;
@ -427,7 +427,7 @@ fn thin_lto(
tmp_path: TempDir,
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
//_symbols_below_threshold: &[String],
) -> Result<(Vec<LtoModuleCodegen<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
) -> Result<(Vec<ThinModule<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_global_analysis");
info!("going for that thin, thin LTO");
@ -573,8 +573,7 @@ fn thin_lto(
}*/
info!(" - {}: re-compiled", module_name);
opt_jobs
.push(LtoModuleCodegen::Thin(ThinModule { shared: shared.clone(), idx: module_index }));
opt_jobs.push(ThinModule { shared: shared.clone(), idx: module_index });
}
// Save the current ThinLTO import information for the next compilation

View file

@ -16,10 +16,12 @@ use crate::{GccCodegenBackend, GccContext};
pub(crate) fn codegen(
cgcx: &CodegenContext<GccCodegenBackend>,
dcx: DiagCtxtHandle<'_>,
module: ModuleCodegen<GccContext>,
config: &ModuleConfig,
) -> Result<CompiledModule, FatalError> {
let dcx = cgcx.create_dcx();
let dcx = dcx.handle();
let _timer = cgcx.prof.generic_activity_with_arg("GCC_module_codegen", &*module.name);
{
let context = &module.module_llvm.context;

View file

@ -971,7 +971,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
fn volatile_load(&mut self, ty: Type<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> {
let ptr = self.context.new_cast(self.location, ptr, ty.make_volatile().make_pointer());
ptr.dereference(self.location).to_rvalue()
// (FractalFir): We insert a local here, to ensure this volatile load can't move across
// blocks.
let local = self.current_func().new_local(self.location, ty, "volatile_tmp");
self.block.add_assignment(self.location, local, ptr.dereference(self.location).to_rvalue());
local.to_rvalue()
}
fn atomic_load(

View file

@ -105,7 +105,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
let is_hidden = if is_generic {
// This is a monomorphization of a generic function.
if !(cx.tcx.sess.opts.share_generics()
|| tcx.codegen_fn_attrs(instance_def_id).inline
|| tcx.codegen_instance_attrs(instance.def).inline
== rustc_attr_data_structures::InlineAttr::Never)
{
// When not sharing generics, all instances are in the same

View file

@ -93,7 +93,7 @@ use gccjit::{CType, Context, OptimizationLevel};
use gccjit::{TargetInfo, Version};
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule};
use rustc_codegen_ssa::back::write::{
CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryFn,
};
@ -273,6 +273,10 @@ fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> {
}
impl ExtraBackendMethods for GccCodegenBackend {
fn supports_parallel(&self) -> bool {
false
}
fn codegen_allocator(
&self,
tcx: TyCtxt<'_>,
@ -341,8 +345,7 @@ impl Deref for SyncContext {
}
unsafe impl Send for SyncContext {}
// FIXME(antoyo): that shouldn't be Sync. Parallel compilation is currently disabled with "-Zno-parallel-llvm".
// TODO: disable it here by returning false in CodegenBackend::supports_parallel().
// FIXME(antoyo): that shouldn't be Sync. Parallel compilation is currently disabled with "CodegenBackend::supports_parallel()".
unsafe impl Sync for SyncContext {}
impl WriteBackendMethods for GccCodegenBackend {
@ -353,11 +356,16 @@ impl WriteBackendMethods for GccCodegenBackend {
type ThinData = ThinData;
type ThinBuffer = ThinBuffer;
fn run_fat_lto(
fn run_and_optimize_fat_lto(
cgcx: &CodegenContext<Self>,
modules: Vec<FatLtoInput<Self>>,
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
) -> Result<LtoModuleCodegen<Self>, FatalError> {
diff_fncs: Vec<AutoDiffItem>,
) -> Result<ModuleCodegen<Self::Module>, FatalError> {
if !diff_fncs.is_empty() {
unimplemented!();
}
back::lto::run_fat(cgcx, modules, cached_modules)
}
@ -365,7 +373,7 @@ impl WriteBackendMethods for GccCodegenBackend {
cgcx: &CodegenContext<Self>,
modules: Vec<(String, Self::ThinBuffer)>,
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError> {
) -> Result<(Vec<ThinModule<Self>>, Vec<WorkProduct>), FatalError> {
back::lto::run_thin(cgcx, modules, cached_modules)
}
@ -387,14 +395,6 @@ impl WriteBackendMethods for GccCodegenBackend {
Ok(())
}
fn optimize_fat(
_cgcx: &CodegenContext<Self>,
_module: &mut ModuleCodegen<Self::Module>,
) -> Result<(), FatalError> {
// TODO(antoyo)
Ok(())
}
fn optimize_thin(
cgcx: &CodegenContext<Self>,
thin: ThinModule<Self>,
@ -404,11 +404,10 @@ impl WriteBackendMethods for GccCodegenBackend {
fn codegen(
cgcx: &CodegenContext<Self>,
dcx: DiagCtxtHandle<'_>,
module: ModuleCodegen<Self::Module>,
config: &ModuleConfig,
) -> Result<CompiledModule, FatalError> {
back::write::codegen(cgcx, dcx, module, config)
back::write::codegen(cgcx, module, config)
}
fn prepare_thin(
@ -429,15 +428,6 @@ impl WriteBackendMethods for GccCodegenBackend {
) -> Result<ModuleCodegen<Self::Module>, FatalError> {
back::write::link(cgcx, dcx, modules)
}
fn autodiff(
_cgcx: &CodegenContext<Self>,
_module: &ModuleCodegen<Self::Module>,
_diff_functions: Vec<AutoDiffItem>,
_config: &ModuleConfig,
) -> Result<(), FatalError> {
unimplemented!()
}
}
/// This is the entrypoint for a hot plugged rustc_codegen_gccjit

View file

@ -53,7 +53,7 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
self.linkage.set(base::linkage_to_gcc(linkage));
let decl = self.declare_fn(symbol_name, fn_abi);
//let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
//let attrs = self.tcx.codegen_instance_attrs(instance.def);
attributes::from_fn_attrs(self, decl, instance);
@ -64,7 +64,7 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
if linkage != Linkage::Internal && self.tcx.is_compiler_builtins(LOCAL_CRATE) {
#[cfg(feature = "master")]
decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
} else {
} else if visibility != Visibility::Default {
#[cfg(feature = "master")]
decl.add_attribute(FnAttribute::Visibility(base::visibility_to_gcc(visibility)));
}

View file

@ -80,3 +80,5 @@ tests/ui/uninhabited/uninhabited-transparent-return-abi.rs
tests/ui/coroutine/panic-drops-resume.rs
tests/ui/coroutine/panic-drops.rs
tests/ui/coroutine/panic-safe.rs
tests/ui/process/nofile-limit.rs
tests/ui/simd/intrinsic/generic-arithmetic-pass.rs

View file

@ -16,6 +16,7 @@ add_asm:
ret"
);
#[cfg(target_arch = "x86_64")]
extern "C" {
fn add_asm(a: i64, b: i64) -> i64;
}

View file

@ -3,8 +3,6 @@
// Run-time:
// status: 0
#![feature(const_black_box)]
fn main() {
use std::hint::black_box;
@ -15,14 +13,14 @@ fn main() {
}};
}
check!(i32, (black_box(0.0f32) as i32));
check!(i32, black_box(0.0f32) as i32);
check!(u64, (black_box(f32::NAN) as u64));
check!(u128, (black_box(f32::NAN) as u128));
check!(u64, black_box(f32::NAN) as u64);
check!(u128, black_box(f32::NAN) as u128);
check!(i64, (black_box(f64::NAN) as i64));
check!(u64, (black_box(f64::NAN) as u64));
check!(i64, black_box(f64::NAN) as i64);
check!(u64, black_box(f64::NAN) as u64);
check!(i16, (black_box(f32::MIN) as i16));
check!(i16, (black_box(f32::MAX) as i16));
check!(i16, black_box(f32::MIN) as i16);
check!(i16, black_box(f32::MAX) as i16);
}

View file

@ -3,8 +3,6 @@
// Run-time:
// status: 0
#![feature(const_black_box)]
fn main() {
use std::hint::black_box;

View file

@ -5,13 +5,14 @@
use std::mem::MaybeUninit;
#[allow(dead_code)]
#[derive(Debug)]
struct Struct {
pointer: *const (),
func: unsafe fn(*const ()),
}
fn func(ptr: *const ()) {
fn func(_ptr: *const ()) {
}
fn main() {

View file

@ -6,8 +6,6 @@
mod libc {
#[link(name = "c")]
extern "C" {
pub fn puts(s: *const u8) -> i32;
pub fn sigaction(signum: i32, act: *const sigaction, oldact: *mut sigaction) -> i32;
pub fn mmap(addr: *mut (), len: usize, prot: i32, flags: i32, fd: i32, offset: i64) -> *mut ();
pub fn mprotect(addr: *mut (), len: usize, prot: i32) -> i32;
@ -61,7 +59,7 @@ fn main() {
panic!("error: mmap failed");
}
let p_count = (&mut COUNT) as *mut u32;
let p_count = (&raw mut COUNT) as *mut u32;
p_count.write_volatile(0);
// Trigger segfaults
@ -94,7 +92,7 @@ fn main() {
}
unsafe extern "C" fn segv_handler(_: i32, _: *mut (), _: *mut ()) {
let p_count = (&mut COUNT) as *mut u32;
let p_count = (&raw mut COUNT) as *mut u32;
p_count.write_volatile(p_count.read_volatile() + 1);
let count = p_count.read_volatile();

View file

@ -1,5 +1,4 @@
codegen_llvm_autodiff_without_enable = using the autodiff feature requires -Z autodiff=Enable
codegen_llvm_autodiff_without_lto = using the autodiff feature requires using fat-lto
codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err}

View file

@ -344,7 +344,7 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
llfn: &'ll Value,
instance: ty::Instance<'tcx>,
) {
let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id());
let codegen_fn_attrs = cx.tcx.codegen_instance_attrs(instance.def);
let mut to_add = SmallVec::<[_; 16]>::new();

View file

@ -7,7 +7,7 @@ use std::sync::Arc;
use std::{io, iter, slice};
use object::read::archive::ArchiveFile;
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared};
use rustc_codegen_ssa::back::symbol_export;
use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput};
use rustc_codegen_ssa::traits::*;
@ -201,7 +201,7 @@ pub(crate) fn run_fat(
cgcx: &CodegenContext<LlvmCodegenBackend>,
modules: Vec<FatLtoInput<LlvmCodegenBackend>>,
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
) -> Result<LtoModuleCodegen<LlvmCodegenBackend>, FatalError> {
) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> {
let dcx = cgcx.create_dcx();
let dcx = dcx.handle();
let (symbols_below_threshold, upstream_modules) = prepare_lto(cgcx, dcx)?;
@ -217,7 +217,7 @@ pub(crate) fn run_thin(
cgcx: &CodegenContext<LlvmCodegenBackend>,
modules: Vec<(String, ThinBuffer)>,
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
) -> Result<(Vec<LtoModuleCodegen<LlvmCodegenBackend>>, Vec<WorkProduct>), FatalError> {
) -> Result<(Vec<ThinModule<LlvmCodegenBackend>>, Vec<WorkProduct>), FatalError> {
let dcx = cgcx.create_dcx();
let dcx = dcx.handle();
let (symbols_below_threshold, upstream_modules) = prepare_lto(cgcx, dcx)?;
@ -248,7 +248,7 @@ fn fat_lto(
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
symbols_below_threshold: &[*const libc::c_char],
) -> Result<LtoModuleCodegen<LlvmCodegenBackend>, FatalError> {
) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> {
let _timer = cgcx.prof.generic_activity("LLVM_fat_lto_build_monolithic_module");
info!("going for a fat lto");
@ -366,7 +366,7 @@ fn fat_lto(
save_temp_bitcode(cgcx, &module, "lto.after-restriction");
}
Ok(LtoModuleCodegen::Fat(module))
Ok(module)
}
pub(crate) struct Linker<'a>(&'a mut llvm::Linker<'a>);
@ -436,7 +436,7 @@ fn thin_lto(
serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
symbols_below_threshold: &[*const libc::c_char],
) -> Result<(Vec<LtoModuleCodegen<LlvmCodegenBackend>>, Vec<WorkProduct>), FatalError> {
) -> Result<(Vec<ThinModule<LlvmCodegenBackend>>, Vec<WorkProduct>), FatalError> {
let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_global_analysis");
unsafe {
info!("going for that thin, thin LTO");
@ -568,10 +568,7 @@ fn thin_lto(
}
info!(" - {}: re-compiled", module_name);
opt_jobs.push(LtoModuleCodegen::Thin(ThinModule {
shared: Arc::clone(&shared),
idx: module_index,
}));
opt_jobs.push(ThinModule { shared: Arc::clone(&shared), idx: module_index });
}
// Save the current ThinLTO import information for the next compilation

View file

@ -39,6 +39,7 @@ impl OwnedTargetMachine {
debug_info_compression: &CStr,
use_emulated_tls: bool,
args_cstr_buff: &[u8],
use_wasm_eh: bool,
) -> Result<Self, LlvmError<'static>> {
assert!(args_cstr_buff.len() > 0);
assert!(
@ -72,6 +73,7 @@ impl OwnedTargetMachine {
use_emulated_tls,
args_cstr_buff.as_ptr() as *const c_char,
args_cstr_buff.len(),
use_wasm_eh,
)
};

View file

@ -15,6 +15,7 @@ use rustc_codegen_ssa::back::write::{
BitcodeSection, CodegenContext, EmitObj, ModuleConfig, TargetMachineFactoryConfig,
TargetMachineFactoryFn,
};
use rustc_codegen_ssa::base::wants_wasm_eh;
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind};
use rustc_data_structures::profiling::SelfProfilerRef;
@ -285,6 +286,8 @@ pub(crate) fn target_machine_factory(
let file_name_display_preference =
sess.filename_display_preference(RemapPathScopeComponents::DEBUGINFO);
let use_wasm_eh = wants_wasm_eh(sess);
Arc::new(move |config: TargetMachineFactoryConfig| {
let path_to_cstring_helper = |path: Option<PathBuf>| -> CString {
let path = path.unwrap_or_default();
@ -321,6 +324,7 @@ pub(crate) fn target_machine_factory(
&debuginfo_compression,
use_emulated_tls,
&args_cstr_buff,
use_wasm_eh,
)
})
}
@ -817,10 +821,12 @@ pub(crate) fn link(
pub(crate) fn codegen(
cgcx: &CodegenContext<LlvmCodegenBackend>,
dcx: DiagCtxtHandle<'_>,
module: ModuleCodegen<ModuleLlvm>,
config: &ModuleConfig,
) -> Result<CompiledModule, FatalError> {
let dcx = cgcx.create_dcx();
let dcx = dcx.handle();
let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen", &*module.name);
{
let llmod = module.module_llvm.llmod();
@ -879,9 +885,7 @@ pub(crate) fn codegen(
.generic_activity_with_arg("LLVM_module_codegen_embed_bitcode", &*module.name);
let thin_bc =
module.thin_lto_buffer.as_deref().expect("cannot find embedded bitcode");
unsafe {
embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, &thin_bc);
}
embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, &thin_bc);
}
}
@ -945,7 +949,7 @@ pub(crate) fn codegen(
// binaries. So we must clone the module to produce the asm output
// if we are also producing object code.
let llmod = if let EmitObj::ObjectCode(_) = config.emit_obj {
unsafe { llvm::LLVMCloneModule(llmod) }
llvm::LLVMCloneModule(llmod)
} else {
llmod
};
@ -1073,7 +1077,7 @@ pub(crate) fn bitcode_section_name(cgcx: &CodegenContext<LlvmCodegenBackend>) ->
}
/// Embed the bitcode of an LLVM module for LTO in the LLVM module itself.
unsafe fn embed_bitcode(
fn embed_bitcode(
cgcx: &CodegenContext<LlvmCodegenBackend>,
llcx: &llvm::Context,
llmod: &llvm::Module,
@ -1115,43 +1119,40 @@ unsafe fn embed_bitcode(
// Unfortunately, LLVM provides no way to set custom section flags. For ELF
// and COFF we emit the sections using module level inline assembly for that
// reason (see issue #90326 for historical background).
unsafe {
if cgcx.target_is_like_darwin
|| cgcx.target_is_like_aix
|| cgcx.target_arch == "wasm32"
|| cgcx.target_arch == "wasm64"
{
// We don't need custom section flags, create LLVM globals.
let llconst = common::bytes_in_context(llcx, bitcode);
let llglobal =
llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.module");
llvm::set_initializer(llglobal, llconst);
llvm::set_section(llglobal, bitcode_section_name(cgcx));
llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
if cgcx.target_is_like_darwin
|| cgcx.target_is_like_aix
|| cgcx.target_arch == "wasm32"
|| cgcx.target_arch == "wasm64"
{
// We don't need custom section flags, create LLVM globals.
let llconst = common::bytes_in_context(llcx, bitcode);
let llglobal = llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.module");
llvm::set_initializer(llglobal, llconst);
let llconst = common::bytes_in_context(llcx, cmdline.as_bytes());
let llglobal =
llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.cmdline");
llvm::set_initializer(llglobal, llconst);
let section = if cgcx.target_is_like_darwin {
c"__LLVM,__cmdline"
} else if cgcx.target_is_like_aix {
c".info"
} else {
c".llvmcmd"
};
llvm::set_section(llglobal, section);
llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
llvm::set_section(llglobal, bitcode_section_name(cgcx));
llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
let llconst = common::bytes_in_context(llcx, cmdline.as_bytes());
let llglobal = llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.cmdline");
llvm::set_initializer(llglobal, llconst);
let section = if cgcx.target_is_like_darwin {
c"__LLVM,__cmdline"
} else if cgcx.target_is_like_aix {
c".info"
} else {
// We need custom section flags, so emit module-level inline assembly.
let section_flags = if cgcx.is_pe_coff { "n" } else { "e" };
let asm = create_section_with_flags_asm(".llvmbc", section_flags, bitcode);
llvm::append_module_inline_asm(llmod, &asm);
let asm = create_section_with_flags_asm(".llvmcmd", section_flags, cmdline.as_bytes());
llvm::append_module_inline_asm(llmod, &asm);
}
c".llvmcmd"
};
llvm::set_section(llglobal, section);
llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
} else {
// We need custom section flags, so emit module-level inline assembly.
let section_flags = if cgcx.is_pe_coff { "n" } else { "e" };
let asm = create_section_with_flags_asm(".llvmbc", section_flags, bitcode);
llvm::append_module_inline_asm(llmod, &asm);
let asm = create_section_with_flags_asm(".llvmcmd", section_flags, cmdline.as_bytes());
llvm::append_module_inline_asm(llmod, &asm);
}
}

View file

@ -302,10 +302,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
return;
}
let id_str = "branch_weights";
let id = unsafe {
llvm::LLVMMDStringInContext2(self.cx.llcx, id_str.as_ptr().cast(), id_str.len())
};
let id = self.cx.create_metadata(b"branch_weights");
// For switch instructions with 2 targets, the `llvm.expect` intrinsic is used.
// This function handles switch instructions with more than 2 targets and it needs to
@ -637,17 +634,16 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
} else if place.layout.is_llvm_immediate() {
let mut const_llval = None;
let llty = place.layout.llvm_type(self);
unsafe {
if let Some(global) = llvm::LLVMIsAGlobalVariable(place.val.llval) {
if llvm::LLVMIsGlobalConstant(global) == llvm::True {
if let Some(init) = llvm::LLVMGetInitializer(global) {
if self.val_ty(init) == llty {
const_llval = Some(init);
}
if let Some(global) = llvm::LLVMIsAGlobalVariable(place.val.llval) {
if llvm::LLVMIsGlobalConstant(global) == llvm::True {
if let Some(init) = llvm::LLVMGetInitializer(global) {
if self.val_ty(init) == llty {
const_llval = Some(init);
}
}
}
}
let llval = const_llval.unwrap_or_else(|| {
let load = self.load(llty, place.val.llval, place.val.align);
if let abi::BackendRepr::Scalar(scalar) = place.layout.backend_repr {
@ -1721,7 +1717,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
} else {
cfi::typeid_for_fnabi(self.tcx, fn_abi, options)
};
let typeid_metadata = self.cx.typeid_metadata(typeid).unwrap();
let typeid_metadata = self.cx.create_metadata(typeid.as_bytes());
let dbg_loc = self.get_dbg_loc();
// Test whether the function pointer is associated with the type identifier using the

View file

@ -2,7 +2,6 @@ use std::ptr;
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, AutoDiffItem, DiffActivity, DiffMode};
use rustc_codegen_ssa::ModuleCodegen;
use rustc_codegen_ssa::back::write::ModuleConfig;
use rustc_codegen_ssa::common::TypeKind;
use rustc_codegen_ssa::traits::BaseTypeCodegenMethods;
use rustc_errors::FatalError;
@ -76,12 +75,12 @@ fn match_args_from_caller_to_enzyme<'ll>(
outer_pos = 1;
}
let enzyme_const = cx.create_metadata("enzyme_const".to_string()).unwrap();
let enzyme_out = cx.create_metadata("enzyme_out".to_string()).unwrap();
let enzyme_dup = cx.create_metadata("enzyme_dup".to_string()).unwrap();
let enzyme_dupv = cx.create_metadata("enzyme_dupv".to_string()).unwrap();
let enzyme_dupnoneed = cx.create_metadata("enzyme_dupnoneed".to_string()).unwrap();
let enzyme_dupnoneedv = cx.create_metadata("enzyme_dupnoneedv".to_string()).unwrap();
let enzyme_const = cx.create_metadata(b"enzyme_const");
let enzyme_out = cx.create_metadata(b"enzyme_out");
let enzyme_dup = cx.create_metadata(b"enzyme_dup");
let enzyme_dupv = cx.create_metadata(b"enzyme_dupv");
let enzyme_dupnoneed = cx.create_metadata(b"enzyme_dupnoneed");
let enzyme_dupnoneedv = cx.create_metadata(b"enzyme_dupnoneedv");
while activity_pos < inputs.len() {
let diff_activity = inputs[activity_pos as usize];
@ -378,12 +377,12 @@ fn generate_enzyme_call<'ll>(
let mut args = Vec::with_capacity(num_args as usize + 1);
args.push(fn_to_diff);
let enzyme_primal_ret = cx.create_metadata("enzyme_primal_return".to_string()).unwrap();
let enzyme_primal_ret = cx.create_metadata(b"enzyme_primal_return");
if matches!(attrs.ret_activity, DiffActivity::Dual | DiffActivity::Active) {
args.push(cx.get_metadata_value(enzyme_primal_ret));
}
if attrs.width > 1 {
let enzyme_width = cx.create_metadata("enzyme_width".to_string()).unwrap();
let enzyme_width = cx.create_metadata(b"enzyme_width");
args.push(cx.get_metadata_value(enzyme_width));
args.push(cx.get_const_int(cx.type_i64(), attrs.width as u64));
}
@ -461,7 +460,6 @@ pub(crate) fn differentiate<'ll>(
module: &'ll ModuleCodegen<ModuleLlvm>,
cgcx: &CodegenContext<LlvmCodegenBackend>,
diff_items: Vec<AutoDiffItem>,
_config: &ModuleConfig,
) -> Result<(), FatalError> {
for item in &diff_items {
trace!("{}", item);

View file

@ -102,7 +102,7 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
let is_hidden = if is_generic {
// This is a monomorphization of a generic function.
if !(cx.tcx.sess.opts.share_generics()
|| tcx.codegen_fn_attrs(instance_def_id).inline
|| tcx.codegen_instance_attrs(instance.def).inline
== rustc_attr_data_structures::InlineAttr::Never)
{
// When not sharing generics, all instances are in the same

View file

@ -215,10 +215,10 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
bug!("symbol `{}` is already defined", sym);
});
llvm::set_initializer(g, sc);
unsafe {
llvm::LLVMSetGlobalConstant(g, True);
llvm::LLVMSetUnnamedAddress(g, llvm::UnnamedAddr::Global);
}
llvm::set_global_constant(g, true);
llvm::set_unnamed_address(g, llvm::UnnamedAddr::Global);
llvm::set_linkage(g, llvm::Linkage::InternalLinkage);
// Cast to default address space if globals are in a different addrspace
let g = self.const_pointercast(g, self.type_ptr());

View file

@ -17,13 +17,12 @@ use rustc_middle::ty::{self, Instance};
use rustc_middle::{bug, span_bug};
use tracing::{debug, instrument, trace};
use crate::common::{AsCCharPtr, CodegenCx};
use crate::common::CodegenCx;
use crate::errors::SymbolAlreadyDefined;
use crate::llvm::{self, True};
use crate::type_::Type;
use crate::type_of::LayoutLlvmExt;
use crate::value::Value;
use crate::{base, debuginfo};
use crate::{base, debuginfo, llvm};
pub(crate) fn const_alloc_to_llvm<'ll>(
cx: &CodegenCx<'ll, '_>,
@ -247,7 +246,7 @@ impl<'ll> CodegenCx<'ll, '_> {
};
llvm::set_initializer(gv, cv);
set_global_alignment(self, gv, align);
llvm::SetUnnamedAddress(gv, llvm::UnnamedAddr::Global);
llvm::set_unnamed_address(gv, llvm::UnnamedAddr::Global);
gv
}
@ -272,9 +271,8 @@ impl<'ll> CodegenCx<'ll, '_> {
return gv;
}
let gv = self.static_addr_of_mut(cv, align, kind);
unsafe {
llvm::LLVMSetGlobalConstant(gv, True);
}
llvm::set_global_constant(gv, true);
self.const_globals.borrow_mut().insert(cv, gv);
gv
}
@ -398,149 +396,140 @@ impl<'ll> CodegenCx<'ll, '_> {
}
fn codegen_static_item(&mut self, def_id: DefId) {
unsafe {
assert!(
llvm::LLVMGetInitializer(
self.instances.borrow().get(&Instance::mono(self.tcx, def_id)).unwrap()
)
.is_none()
);
let attrs = self.tcx.codegen_fn_attrs(def_id);
assert!(
llvm::LLVMGetInitializer(
self.instances.borrow().get(&Instance::mono(self.tcx, def_id)).unwrap()
)
.is_none()
);
let attrs = self.tcx.codegen_fn_attrs(def_id);
let Ok((v, alloc)) = codegen_static_initializer(self, def_id) else {
// Error has already been reported
return;
};
let alloc = alloc.inner();
let Ok((v, alloc)) = codegen_static_initializer(self, def_id) else {
// Error has already been reported
return;
};
let alloc = alloc.inner();
let val_llty = self.val_ty(v);
let val_llty = self.val_ty(v);
let g = self.get_static_inner(def_id, val_llty);
let llty = self.get_type_of_global(g);
let g = self.get_static_inner(def_id, val_llty);
let llty = self.get_type_of_global(g);
let g = if val_llty == llty {
g
} else {
// codegen_static_initializer creates the global value just from the
// `Allocation` data by generating one big struct value that is just
// all the bytes and pointers after each other. This will almost never
// match the type that the static was declared with. Unfortunately
// we can't just LLVMConstBitCast our way out of it because that has very
// specific rules on what can be cast. So instead of adding a new way to
// generate static initializers that match the static's type, we picked
// the easier option and retroactively change the type of the static item itself.
let name = llvm::get_value_name(g);
llvm::set_value_name(g, b"");
let g = if val_llty == llty {
g
} else {
// codegen_static_initializer creates the global value just from the
// `Allocation` data by generating one big struct value that is just
// all the bytes and pointers after each other. This will almost never
// match the type that the static was declared with. Unfortunately
// we can't just LLVMConstBitCast our way out of it because that has very
// specific rules on what can be cast. So instead of adding a new way to
// generate static initializers that match the static's type, we picked
// the easier option and retroactively change the type of the static item itself.
let name = String::from_utf8(llvm::get_value_name(g))
.expect("we declare our statics with a utf8-valid name");
llvm::set_value_name(g, b"");
let linkage = llvm::get_linkage(g);
let visibility = llvm::get_visibility(g);
let linkage = llvm::get_linkage(g);
let visibility = llvm::get_visibility(g);
let new_g = llvm::LLVMRustGetOrInsertGlobal(
self.llmod,
name.as_c_char_ptr(),
name.len(),
val_llty,
);
let new_g = self.declare_global(&name, val_llty);
llvm::set_linkage(new_g, linkage);
llvm::set_visibility(new_g, visibility);
llvm::set_linkage(new_g, linkage);
llvm::set_visibility(new_g, visibility);
// The old global has had its name removed but is returned by
// get_static since it is in the instance cache. Provide an
// alternative lookup that points to the new global so that
// global_asm! can compute the correct mangled symbol name
// for the global.
self.renamed_statics.borrow_mut().insert(def_id, new_g);
// The old global has had its name removed but is returned by
// get_static since it is in the instance cache. Provide an
// alternative lookup that points to the new global so that
// global_asm! can compute the correct mangled symbol name
// for the global.
self.renamed_statics.borrow_mut().insert(def_id, new_g);
// To avoid breaking any invariants, we leave around the old
// global for the moment; we'll replace all references to it
// with the new global later. (See base::codegen_backend.)
self.statics_to_rauw.borrow_mut().push((g, new_g));
new_g
};
set_global_alignment(self, g, alloc.align);
llvm::set_initializer(g, v);
// To avoid breaking any invariants, we leave around the old
// global for the moment; we'll replace all references to it
// with the new global later. (See base::codegen_backend.)
self.statics_to_rauw.borrow_mut().push((g, new_g));
new_g
};
set_global_alignment(self, g, alloc.align);
llvm::set_initializer(g, v);
self.assume_dso_local(g, true);
self.assume_dso_local(g, true);
// Forward the allocation's mutability (picked by the const interner) to LLVM.
if alloc.mutability.is_not() {
llvm::LLVMSetGlobalConstant(g, llvm::True);
}
// Forward the allocation's mutability (picked by the const interner) to LLVM.
if alloc.mutability.is_not() {
llvm::set_global_constant(g, true);
}
debuginfo::build_global_var_di_node(self, def_id, g);
debuginfo::build_global_var_di_node(self, def_id, g);
if attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) {
llvm::set_thread_local_mode(g, self.tls_model);
}
if attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) {
llvm::set_thread_local_mode(g, self.tls_model);
}
// Wasm statics with custom link sections get special treatment as they
// go into custom sections of the wasm executable. The exception to this
// is the `.init_array` section which are treated specially by the wasm linker.
if self.tcx.sess.target.is_like_wasm
&& attrs
.link_section
.map(|link_section| !link_section.as_str().starts_with(".init_array"))
.unwrap_or(true)
{
if let Some(section) = attrs.link_section {
let section = llvm::LLVMMDStringInContext2(
self.llcx,
section.as_str().as_c_char_ptr(),
section.as_str().len(),
);
assert!(alloc.provenance().ptrs().is_empty());
// Wasm statics with custom link sections get special treatment as they
// go into custom sections of the wasm executable. The exception to this
// is the `.init_array` section which are treated specially by the wasm linker.
if self.tcx.sess.target.is_like_wasm
&& attrs
.link_section
.map(|link_section| !link_section.as_str().starts_with(".init_array"))
.unwrap_or(true)
{
if let Some(section) = attrs.link_section {
let section = self.create_metadata(section.as_str().as_bytes());
assert!(alloc.provenance().ptrs().is_empty());
// The `inspect` method is okay here because we checked for provenance, and
// because we are doing this access to inspect the final interpreter state (not
// as part of the interpreter execution).
let bytes =
alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len());
let alloc =
llvm::LLVMMDStringInContext2(self.llcx, bytes.as_c_char_ptr(), bytes.len());
let data = [section, alloc];
let meta = llvm::LLVMMDNodeInContext2(self.llcx, data.as_ptr(), data.len());
let val = self.get_metadata_value(meta);
// The `inspect` method is okay here because we checked for provenance, and
// because we are doing this access to inspect the final interpreter state (not
// as part of the interpreter execution).
let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len());
let alloc = self.create_metadata(bytes);
let data = [section, alloc];
let meta =
unsafe { llvm::LLVMMDNodeInContext2(self.llcx, data.as_ptr(), data.len()) };
let val = self.get_metadata_value(meta);
unsafe {
llvm::LLVMAddNamedMetadataOperand(
self.llmod,
c"wasm.custom_sections".as_ptr(),
val,
);
}
} else {
base::set_link_section(g, attrs);
)
};
}
} else {
base::set_link_section(g, attrs);
}
base::set_variable_sanitizer_attrs(g, attrs);
base::set_variable_sanitizer_attrs(g, attrs);
if attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) {
// `USED` and `USED_LINKER` can't be used together.
assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER));
if attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) {
// `USED` and `USED_LINKER` can't be used together.
assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER));
// The semantics of #[used] in Rust only require the symbol to make it into the
// object file. It is explicitly allowed for the linker to strip the symbol if it
// is dead, which means we are allowed to use `llvm.compiler.used` instead of
// `llvm.used` here.
//
// Additionally, https://reviews.llvm.org/D97448 in LLVM 13 started emitting unique
// sections with SHF_GNU_RETAIN flag for llvm.used symbols, which may trigger bugs
// in the handling of `.init_array` (the static constructor list) in versions of
// the gold linker (prior to the one released with binutils 2.36).
//
// That said, we only ever emit these when `#[used(compiler)]` is explicitly
// requested. This is to avoid similar breakage on other targets, in particular
// MachO targets have *their* static constructor lists broken if `llvm.compiler.used`
// is emitted rather than `llvm.used`. However, that check happens when assigning
// the `CodegenFnAttrFlags` in the `codegen_fn_attrs` query, so we don't need to
// take care of it here.
self.add_compiler_used_global(g);
}
if attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) {
// `USED` and `USED_LINKER` can't be used together.
assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER));
// The semantics of #[used] in Rust only require the symbol to make it into the
// object file. It is explicitly allowed for the linker to strip the symbol if it
// is dead, which means we are allowed to use `llvm.compiler.used` instead of
// `llvm.used` here.
//
// Additionally, https://reviews.llvm.org/D97448 in LLVM 13 started emitting unique
// sections with SHF_GNU_RETAIN flag for llvm.used symbols, which may trigger bugs
// in the handling of `.init_array` (the static constructor list) in versions of
// the gold linker (prior to the one released with binutils 2.36).
//
// That said, we only ever emit these when `#[used(compiler)]` is explicitly
// requested. This is to avoid similar breakage on other targets, in particular
// MachO targets have *their* static constructor lists broken if `llvm.compiler.used`
// is emitted rather than `llvm.used`. However, that check happens when assigning
// the `CodegenFnAttrFlags` in the `codegen_fn_attrs` query, so we don't need to
// take care of it here.
self.add_compiler_used_global(g);
}
if attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) {
// `USED` and `USED_LINKER` can't be used together.
assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER));
self.add_used_global(g);
}
self.add_used_global(g);
}
}

View file

@ -34,7 +34,6 @@ use smallvec::SmallVec;
use crate::back::write::to_llvm_code_model;
use crate::callee::get_fn;
use crate::common::AsCCharPtr;
use crate::debuginfo::metadata::apply_vcall_visibility_metadata;
use crate::llvm::Metadata;
use crate::type_::Type;
@ -169,6 +168,8 @@ pub(crate) unsafe fn create_module<'ll>(
let mod_name = SmallCStr::new(mod_name);
let llmod = unsafe { llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx) };
let cx = SimpleCx::new(llmod, llcx, tcx.data_layout.pointer_size());
let mut target_data_layout = sess.target.data_layout.to_string();
let llvm_version = llvm_util::get_version();
@ -206,6 +207,11 @@ pub(crate) unsafe fn create_module<'ll>(
// LLVM 21 updated the default layout on nvptx: https://github.com/llvm/llvm-project/pull/124961
target_data_layout = target_data_layout.replace("e-p6:32:32-i64", "e-i64");
}
if sess.target.arch == "amdgpu" {
// LLVM 21 adds the address width for address space 8.
// See https://github.com/llvm/llvm-project/pull/139419
target_data_layout = target_data_layout.replace("p8:128:128:128:48", "p8:128:128")
}
}
// Ensure the data-layout values hardcoded remain the defaults.
@ -473,18 +479,14 @@ pub(crate) unsafe fn create_module<'ll>(
#[allow(clippy::option_env_unwrap)]
let rustc_producer =
format!("rustc version {}", option_env!("CFG_VERSION").expect("CFG_VERSION"));
let name_metadata = unsafe {
llvm::LLVMMDStringInContext2(
llcx,
rustc_producer.as_c_char_ptr(),
rustc_producer.as_bytes().len(),
)
};
let name_metadata = cx.create_metadata(rustc_producer.as_bytes());
unsafe {
llvm::LLVMAddNamedMetadataOperand(
llmod,
c"llvm.ident".as_ptr(),
&llvm::LLVMMetadataAsValue(llcx, llvm::LLVMMDNodeInContext2(llcx, &name_metadata, 1)),
&cx.get_metadata_value(llvm::LLVMMDNodeInContext2(llcx, &name_metadata, 1)),
);
}
@ -698,10 +700,10 @@ impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
}
}
pub(crate) fn create_metadata(&self, name: String) -> Option<&'ll Metadata> {
Some(unsafe {
pub(crate) fn create_metadata(&self, name: &[u8]) -> &'ll Metadata {
unsafe {
llvm::LLVMMDStringInContext2(self.llcx(), name.as_ptr() as *const c_char, name.len())
})
}
}
pub(crate) fn get_functions(&self) -> Vec<&'ll Value> {

View file

@ -74,7 +74,7 @@ pub(crate) fn get_or_insert_gdb_debug_scripts_section_global<'ll>(
llvm::set_section(section_var, c".debug_gdb_scripts");
llvm::set_initializer(section_var, cx.const_bytes(section_contents));
llvm::LLVMSetGlobalConstant(section_var, llvm::True);
llvm::LLVMSetUnnamedAddress(section_var, llvm::UnnamedAddr::Global);
llvm::set_unnamed_address(section_var, llvm::UnnamedAddr::Global);
llvm::set_linkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
// This should make sure that the whole section is not larger than
// the string it contains. Otherwise we get a warning from GDB.

View file

@ -5,7 +5,7 @@ use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::{iter, ptr};
use libc::{c_char, c_longlong, c_uint};
use libc::{c_longlong, c_uint};
use rustc_abi::{Align, Size};
use rustc_codegen_ssa::debuginfo::type_names::{VTableNameKind, cpp_like_debuginfo};
use rustc_codegen_ssa::traits::*;
@ -1582,13 +1582,9 @@ pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>(
};
let trait_ref_typeid = typeid_for_trait_ref(cx.tcx, trait_ref);
let typeid = cx.create_metadata(trait_ref_typeid.as_bytes());
unsafe {
let typeid = llvm::LLVMMDStringInContext2(
cx.llcx,
trait_ref_typeid.as_ptr() as *const c_char,
trait_ref_typeid.as_bytes().len(),
);
let v = [llvm::LLVMValueAsMetadata(cx.const_usize(0)), typeid];
llvm::LLVMRustGlobalAddMetadata(
vtable,
@ -1630,7 +1626,7 @@ pub(crate) fn create_vtable_di_node<'ll, 'tcx>(
// When full debuginfo is enabled, we want to try and prevent vtables from being
// merged. Otherwise debuggers will have a hard time mapping from dyn pointer
// to concrete type.
llvm::SetUnnamedAddress(vtable, llvm::UnnamedAddr::No);
llvm::set_unnamed_address(vtable, llvm::UnnamedAddr::No);
let vtable_name =
compute_debuginfo_vtable_name(cx.tcx, ty, poly_trait_ref, VTableNameKind::GlobalVariable);

View file

@ -49,7 +49,7 @@ pub(crate) fn declare_simple_fn<'ll>(
};
llvm::SetFunctionCallConv(llfn, callconv);
llvm::SetUnnamedAddress(llfn, unnamed);
llvm::set_unnamed_address(llfn, unnamed);
llvm::set_visibility(llfn, visibility);
llfn
@ -176,7 +176,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
{
let typeid = cfi::typeid_for_instance(self.tcx, instance, options);
if typeids.insert(typeid.clone()) {
self.add_type_metadata(llfn, typeid);
self.add_type_metadata(llfn, typeid.as_bytes());
}
}
} else {
@ -189,7 +189,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
.map(cfi::TypeIdOptions::from_iter)
{
let typeid = cfi::typeid_for_fnabi(self.tcx, fn_abi, options);
self.add_type_metadata(llfn, typeid);
self.add_type_metadata(llfn, typeid.as_bytes());
}
}
}

View file

@ -37,10 +37,6 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for ParseTargetMachineConfig<'_> {
}
}
#[derive(Diagnostic)]
#[diag(codegen_llvm_autodiff_without_lto)]
pub(crate) struct AutoDiffWithoutLTO;
#[derive(Diagnostic)]
#[diag(codegen_llvm_autodiff_without_enable)]
pub(crate) struct AutoDiffWithoutEnable;

View file

@ -26,11 +26,11 @@ use std::mem::ManuallyDrop;
use back::owned_target_machine::OwnedTargetMachine;
use back::write::{create_informational_target_machine, create_target_machine};
use context::SimpleCx;
use errors::{AutoDiffWithoutLTO, ParseTargetMachineConfig};
use errors::ParseTargetMachineConfig;
use llvm_util::target_config;
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule};
use rustc_codegen_ssa::back::write::{
CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryConfig, TargetMachineFactoryFn,
};
@ -43,7 +43,7 @@ use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::ty::TyCtxt;
use rustc_middle::util::Providers;
use rustc_session::Session;
use rustc_session::config::{Lto, OptLevel, OutputFilenames, PrintKind, PrintRequest};
use rustc_session::config::{OptLevel, OutputFilenames, PrintKind, PrintRequest};
use rustc_span::Symbol;
mod back {
@ -174,18 +174,29 @@ impl WriteBackendMethods for LlvmCodegenBackend {
) -> Result<ModuleCodegen<Self::Module>, FatalError> {
back::write::link(cgcx, dcx, modules)
}
fn run_fat_lto(
fn run_and_optimize_fat_lto(
cgcx: &CodegenContext<Self>,
modules: Vec<FatLtoInput<Self>>,
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
) -> Result<LtoModuleCodegen<Self>, FatalError> {
back::lto::run_fat(cgcx, modules, cached_modules)
diff_fncs: Vec<AutoDiffItem>,
) -> Result<ModuleCodegen<Self::Module>, FatalError> {
let mut module = back::lto::run_fat(cgcx, modules, cached_modules)?;
if !diff_fncs.is_empty() {
builder::autodiff::differentiate(&module, cgcx, diff_fncs)?;
}
let dcx = cgcx.create_dcx();
let dcx = dcx.handle();
back::lto::run_pass_manager(cgcx, dcx, &mut module, false)?;
Ok(module)
}
fn run_thin_lto(
cgcx: &CodegenContext<Self>,
modules: Vec<(String, Self::ThinBuffer)>,
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError> {
) -> Result<(Vec<ThinModule<Self>>, Vec<WorkProduct>), FatalError> {
back::lto::run_thin(cgcx, modules, cached_modules)
}
fn optimize(
@ -196,14 +207,6 @@ impl WriteBackendMethods for LlvmCodegenBackend {
) -> Result<(), FatalError> {
back::write::optimize(cgcx, dcx, module, config)
}
fn optimize_fat(
cgcx: &CodegenContext<Self>,
module: &mut ModuleCodegen<Self::Module>,
) -> Result<(), FatalError> {
let dcx = cgcx.create_dcx();
let dcx = dcx.handle();
back::lto::run_pass_manager(cgcx, dcx, module, false)
}
fn optimize_thin(
cgcx: &CodegenContext<Self>,
thin: ThinModule<Self>,
@ -212,11 +215,10 @@ impl WriteBackendMethods for LlvmCodegenBackend {
}
fn codegen(
cgcx: &CodegenContext<Self>,
dcx: DiagCtxtHandle<'_>,
module: ModuleCodegen<Self::Module>,
config: &ModuleConfig,
) -> Result<CompiledModule, FatalError> {
back::write::codegen(cgcx, dcx, module, config)
back::write::codegen(cgcx, module, config)
}
fn prepare_thin(
module: ModuleCodegen<Self::Module>,
@ -227,19 +229,6 @@ impl WriteBackendMethods for LlvmCodegenBackend {
fn serialize_module(module: ModuleCodegen<Self::Module>) -> (String, Self::ModuleBuffer) {
(module.name, back::lto::ModuleBuffer::new(module.module_llvm.llmod()))
}
/// Generate autodiff rules
fn autodiff(
cgcx: &CodegenContext<Self>,
module: &ModuleCodegen<Self::Module>,
diff_fncs: Vec<AutoDiffItem>,
config: &ModuleConfig,
) -> Result<(), FatalError> {
if cgcx.lto != Lto::Fat {
let dcx = cgcx.create_dcx();
return Err(dcx.handle().emit_almost_fatal(AutoDiffWithoutLTO));
}
builder::autodiff::differentiate(module, cgcx, diff_fncs, config)
}
}
impl LlvmCodegenBackend {

View file

@ -1009,7 +1009,7 @@ unsafe extern "C" {
ModuleID: *const c_char,
C: &Context,
) -> &Module;
pub(crate) fn LLVMCloneModule(M: &Module) -> &Module;
pub(crate) safe fn LLVMCloneModule(M: &Module) -> &Module;
/// Data layout. See Module::getDataLayout.
pub(crate) fn LLVMGetDataLayoutStr(M: &Module) -> *const c_char;
@ -1168,18 +1168,18 @@ unsafe extern "C" {
pub(crate) fn LLVMGlobalGetValueType(Global: &Value) -> &Type;
// Operations on global variables
pub(crate) fn LLVMIsAGlobalVariable(GlobalVar: &Value) -> Option<&Value>;
pub(crate) safe fn LLVMIsAGlobalVariable(GlobalVar: &Value) -> Option<&Value>;
pub(crate) fn LLVMAddGlobal<'a>(M: &'a Module, Ty: &'a Type, Name: *const c_char) -> &'a Value;
pub(crate) fn LLVMGetNamedGlobal(M: &Module, Name: *const c_char) -> Option<&Value>;
pub(crate) fn LLVMGetFirstGlobal(M: &Module) -> Option<&Value>;
pub(crate) fn LLVMGetNextGlobal(GlobalVar: &Value) -> Option<&Value>;
pub(crate) fn LLVMDeleteGlobal(GlobalVar: &Value);
pub(crate) fn LLVMGetInitializer(GlobalVar: &Value) -> Option<&Value>;
pub(crate) safe fn LLVMGetInitializer(GlobalVar: &Value) -> Option<&Value>;
pub(crate) fn LLVMSetInitializer<'a>(GlobalVar: &'a Value, ConstantVal: &'a Value);
pub(crate) fn LLVMIsThreadLocal(GlobalVar: &Value) -> Bool;
pub(crate) safe fn LLVMIsThreadLocal(GlobalVar: &Value) -> Bool;
pub(crate) fn LLVMSetThreadLocalMode(GlobalVar: &Value, Mode: ThreadLocalMode);
pub(crate) fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool;
pub(crate) fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool);
pub(crate) safe fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool;
pub(crate) safe fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool);
pub(crate) safe fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool);
// Operations on attributes
@ -1718,7 +1718,7 @@ unsafe extern "C" {
pub(crate) safe fn LLVMMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value;
pub(crate) fn LLVMSetUnnamedAddress(Global: &Value, UnnamedAddr: UnnamedAddr);
pub(crate) safe fn LLVMSetUnnamedAddress(Global: &Value, UnnamedAddr: UnnamedAddr);
pub(crate) fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&ConstantInt>;
@ -2425,6 +2425,7 @@ unsafe extern "C" {
UseEmulatedTls: bool,
ArgsCstrBuff: *const c_char,
ArgsCstrBuffLen: usize,
UseWasmEH: bool,
) -> *mut TargetMachine;
pub(crate) fn LLVMRustDisposeTargetMachine(T: *mut TargetMachine);

View file

@ -217,10 +217,8 @@ pub(crate) fn SetUniqueComdat(llmod: &Module, val: &Value) {
set_comdat(llmod, val, &name);
}
pub(crate) fn SetUnnamedAddress(global: &Value, unnamed: UnnamedAddr) {
unsafe {
LLVMSetUnnamedAddress(global, unnamed);
}
pub(crate) fn set_unnamed_address(global: &Value, unnamed: UnnamedAddr) {
LLVMSetUnnamedAddress(global, unnamed);
}
pub(crate) fn set_thread_local_mode(global: &Value, mode: ThreadLocalMode) {
@ -260,9 +258,7 @@ pub(crate) fn set_initializer(llglobal: &Value, constant_val: &Value) {
}
pub(crate) fn set_global_constant(llglobal: &Value, is_constant: bool) {
unsafe {
LLVMSetGlobalConstant(llglobal, if is_constant { ffi::True } else { ffi::False });
}
LLVMSetGlobalConstant(llglobal, if is_constant { ffi::True } else { ffi::False });
}
pub(crate) fn get_linkage(llglobal: &Value) -> Linkage {

View file

@ -55,8 +55,8 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
let lldecl = self.declare_fn(symbol_name, fn_abi, Some(instance));
llvm::set_linkage(lldecl, base::linkage_to_llvm(linkage));
let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
base::set_link_section(lldecl, attrs);
let attrs = self.tcx.codegen_instance_attrs(instance.def);
base::set_link_section(lldecl, &attrs);
if (linkage == Linkage::LinkOnceODR || linkage == Linkage::WeakODR)
&& self.tcx.sess.target.supports_comdat()
{
@ -131,8 +131,8 @@ impl CodegenCx<'_, '_> {
}
// Thread-local variables generally don't support copy relocations.
let is_thread_local_var = unsafe { llvm::LLVMIsAGlobalVariable(llval) }
.is_some_and(|v| unsafe { llvm::LLVMIsThreadLocal(v) } == llvm::True);
let is_thread_local_var = llvm::LLVMIsAGlobalVariable(llval)
.is_some_and(|v| llvm::LLVMIsThreadLocal(v) == llvm::True);
if is_thread_local_var {
return false;
}

View file

@ -2,7 +2,7 @@ use std::borrow::Borrow;
use std::hash::{Hash, Hasher};
use std::{fmt, ptr};
use libc::{c_char, c_uint};
use libc::c_uint;
use rustc_abi::{AddressSpace, Align, Integer, Reg, Size};
use rustc_codegen_ssa::common::TypeKind;
use rustc_codegen_ssa::traits::*;
@ -298,8 +298,8 @@ impl<'ll, 'tcx> LayoutTypeCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
}
impl<'ll, 'tcx> TypeMembershipCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
fn add_type_metadata(&self, function: &'ll Value, typeid: String) {
let typeid_metadata = self.typeid_metadata(typeid).unwrap();
fn add_type_metadata(&self, function: &'ll Value, typeid: &[u8]) {
let typeid_metadata = self.create_metadata(typeid);
unsafe {
let v = [llvm::LLVMValueAsMetadata(self.const_usize(0)), typeid_metadata];
llvm::LLVMRustGlobalAddMetadata(
@ -310,8 +310,8 @@ impl<'ll, 'tcx> TypeMembershipCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
}
}
fn set_type_metadata(&self, function: &'ll Value, typeid: String) {
let typeid_metadata = self.typeid_metadata(typeid).unwrap();
fn set_type_metadata(&self, function: &'ll Value, typeid: &[u8]) {
let typeid_metadata = self.create_metadata(typeid);
unsafe {
let v = [llvm::LLVMValueAsMetadata(self.const_usize(0)), typeid_metadata];
llvm::LLVMGlobalSetMetadata(
@ -322,10 +322,8 @@ impl<'ll, 'tcx> TypeMembershipCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
}
}
fn typeid_metadata(&self, typeid: String) -> Option<&'ll Metadata> {
Some(unsafe {
llvm::LLVMMDStringInContext2(self.llcx, typeid.as_ptr() as *const c_char, typeid.len())
})
fn typeid_metadata(&self, typeid: &[u8]) -> Option<&'ll Metadata> {
Some(self.create_metadata(typeid))
}
fn add_kcfi_type_metadata(&self, function: &'ll Value, kcfi_typeid: u32) {

View file

@ -2542,12 +2542,7 @@ fn add_order_independent_options(
// sections to ensure we have all the data for PGO.
let keep_metadata =
crate_type == CrateType::Dylib || sess.opts.cg.profile_generate.enabled();
if crate_type != CrateType::Executable || !sess.opts.unstable_opts.export_executable_symbols
{
cmd.gc_sections(keep_metadata);
} else {
cmd.no_gc_sections();
}
cmd.gc_sections(keep_metadata);
}
cmd.set_output_kind(link_output_kind, crate_type, out_filename);

View file

@ -326,7 +326,6 @@ pub(crate) trait Linker {
link_or_cc_args(self, &[path]);
}
fn gc_sections(&mut self, keep_metadata: bool);
fn no_gc_sections(&mut self);
fn full_relro(&mut self);
fn partial_relro(&mut self);
fn no_relro(&mut self);
@ -688,12 +687,6 @@ impl<'a> Linker for GccLinker<'a> {
}
}
fn no_gc_sections(&mut self) {
if self.is_gnu || self.sess.target.is_like_wasm {
self.link_arg("--no-gc-sections");
}
}
fn optimize(&mut self) {
if !self.is_gnu && !self.sess.target.is_like_wasm {
return;
@ -1010,10 +1003,6 @@ impl<'a> Linker for MsvcLinker<'a> {
}
}
fn no_gc_sections(&mut self) {
self.link_arg("/OPT:NOREF,NOICF");
}
fn full_relro(&mut self) {
// noop
}
@ -1243,10 +1232,6 @@ impl<'a> Linker for EmLinker<'a> {
// noop
}
fn no_gc_sections(&mut self) {
// noop
}
fn optimize(&mut self) {
// Emscripten performs own optimizations
self.cc_arg(match self.sess.opts.optimize {
@ -1418,10 +1403,6 @@ impl<'a> Linker for WasmLd<'a> {
self.link_arg("--gc-sections");
}
fn no_gc_sections(&mut self) {
self.link_arg("--no-gc-sections");
}
fn optimize(&mut self) {
// The -O flag is, as of late 2023, only used for merging of strings and debuginfo, and
// only differentiates -O0 and -O1. It does not apply to LTO.
@ -1567,10 +1548,6 @@ impl<'a> Linker for L4Bender<'a> {
}
}
fn no_gc_sections(&mut self) {
self.link_arg("--no-gc-sections");
}
fn optimize(&mut self) {
// GNU-style linkers support optimization with -O. GNU ld doesn't
// need a numeric argument, but other linkers do.
@ -1734,10 +1711,6 @@ impl<'a> Linker for AixLinker<'a> {
self.link_arg("-bgc");
}
fn no_gc_sections(&mut self) {
self.link_arg("-bnogc");
}
fn optimize(&mut self) {}
fn pgo_gen(&mut self) {
@ -1982,8 +1955,6 @@ impl<'a> Linker for PtxLinker<'a> {
fn gc_sections(&mut self, _keep_metadata: bool) {}
fn no_gc_sections(&mut self) {}
fn pgo_gen(&mut self) {}
fn no_crt_objects(&mut self) {}
@ -2057,8 +2028,6 @@ impl<'a> Linker for LlbcLinker<'a> {
fn gc_sections(&mut self, _keep_metadata: bool) {}
fn no_gc_sections(&mut self) {}
fn pgo_gen(&mut self) {}
fn no_crt_objects(&mut self) {}
@ -2139,8 +2108,6 @@ impl<'a> Linker for BpfLinker<'a> {
fn gc_sections(&mut self, _keep_metadata: bool) {}
fn no_gc_sections(&mut self) {}
fn pgo_gen(&mut self) {}
fn no_crt_objects(&mut self) {}

View file

@ -1,13 +1,8 @@
use std::ffi::CString;
use std::sync::Arc;
use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
use rustc_data_structures::memmap::Mmap;
use rustc_errors::FatalError;
use super::write::CodegenContext;
use crate::ModuleCodegen;
use crate::back::write::ModuleConfig;
use crate::traits::*;
pub struct ThinModule<B: WriteBackendMethods> {
@ -42,61 +37,6 @@ pub struct ThinShared<B: WriteBackendMethods> {
pub module_names: Vec<CString>,
}
pub enum LtoModuleCodegen<B: WriteBackendMethods> {
Fat(ModuleCodegen<B::Module>),
Thin(ThinModule<B>),
}
impl<B: WriteBackendMethods> LtoModuleCodegen<B> {
pub fn name(&self) -> &str {
match *self {
LtoModuleCodegen::Fat(_) => "everything",
LtoModuleCodegen::Thin(ref m) => m.name(),
}
}
/// Optimize this module within the given codegen context.
pub fn optimize(
self,
cgcx: &CodegenContext<B>,
) -> Result<ModuleCodegen<B::Module>, FatalError> {
match self {
LtoModuleCodegen::Fat(mut module) => {
B::optimize_fat(cgcx, &mut module)?;
Ok(module)
}
LtoModuleCodegen::Thin(thin) => B::optimize_thin(cgcx, thin),
}
}
/// A "gauge" of how costly it is to optimize this module, used to sort
/// biggest modules first.
pub fn cost(&self) -> u64 {
match *self {
// Only one module with fat LTO, so the cost doesn't matter.
LtoModuleCodegen::Fat(_) => 0,
LtoModuleCodegen::Thin(ref m) => m.cost(),
}
}
/// Run autodiff on Fat LTO module
pub fn autodiff(
self,
cgcx: &CodegenContext<B>,
diff_fncs: Vec<AutoDiffItem>,
config: &ModuleConfig,
) -> Result<LtoModuleCodegen<B>, FatalError> {
match &self {
LtoModuleCodegen::Fat(module) => {
B::autodiff(cgcx, &module, diff_fncs, config)?;
}
_ => panic!("autodiff called with non-fat LTO module"),
}
Ok(self)
}
}
pub enum SerializedModule<M: ModuleBufferMethods> {
Local(M),
FromRlib(Vec<u8>),

View file

@ -397,50 +397,31 @@ impl<B: WriteBackendMethods> CodegenContext<B> {
}
}
fn generate_lto_work<B: ExtraBackendMethods>(
fn generate_thin_lto_work<B: ExtraBackendMethods>(
cgcx: &CodegenContext<B>,
autodiff: Vec<AutoDiffItem>,
needs_fat_lto: Vec<FatLtoInput<B>>,
needs_thin_lto: Vec<(String, B::ThinBuffer)>,
import_only_modules: Vec<(SerializedModule<B::ModuleBuffer>, WorkProduct)>,
) -> Vec<(WorkItem<B>, u64)> {
let _prof_timer = cgcx.prof.generic_activity("codegen_generate_lto_work");
let _prof_timer = cgcx.prof.generic_activity("codegen_thin_generate_lto_work");
if !needs_fat_lto.is_empty() {
assert!(needs_thin_lto.is_empty());
let mut module =
B::run_fat_lto(cgcx, needs_fat_lto, import_only_modules).unwrap_or_else(|e| e.raise());
if cgcx.lto == Lto::Fat && !autodiff.is_empty() {
let config = cgcx.config(ModuleKind::Regular);
module = module.autodiff(cgcx, autodiff, config).unwrap_or_else(|e| e.raise());
}
// We are adding a single work item, so the cost doesn't matter.
vec![(WorkItem::LTO(module), 0)]
} else {
if !autodiff.is_empty() {
let dcx = cgcx.create_dcx();
dcx.handle().emit_fatal(AutodiffWithoutLto {});
}
assert!(needs_fat_lto.is_empty());
let (lto_modules, copy_jobs) = B::run_thin_lto(cgcx, needs_thin_lto, import_only_modules)
.unwrap_or_else(|e| e.raise());
lto_modules
.into_iter()
.map(|module| {
let cost = module.cost();
(WorkItem::LTO(module), cost)
})
.chain(copy_jobs.into_iter().map(|wp| {
(
WorkItem::CopyPostLtoArtifacts(CachedModuleCodegen {
name: wp.cgu_name.clone(),
source: wp,
}),
0, // copying is very cheap
)
}))
.collect()
}
let (lto_modules, copy_jobs) =
B::run_thin_lto(cgcx, needs_thin_lto, import_only_modules).unwrap_or_else(|e| e.raise());
lto_modules
.into_iter()
.map(|module| {
let cost = module.cost();
(WorkItem::ThinLto(module), cost)
})
.chain(copy_jobs.into_iter().map(|wp| {
(
WorkItem::CopyPostLtoArtifacts(CachedModuleCodegen {
name: wp.cgu_name.clone(),
source: wp,
}),
0, // copying is very cheap
)
}))
.collect()
}
struct CompiledModules {
@ -470,6 +451,7 @@ pub(crate) fn start_async_codegen<B: ExtraBackendMethods>(
backend: B,
tcx: TyCtxt<'_>,
target_cpu: String,
autodiff_items: &[AutoDiffItem],
) -> OngoingCodegen<B> {
let (coordinator_send, coordinator_receive) = channel();
@ -488,6 +470,7 @@ pub(crate) fn start_async_codegen<B: ExtraBackendMethods>(
backend.clone(),
tcx,
&crate_info,
autodiff_items,
shared_emitter,
codegen_worker_send,
coordinator_receive,
@ -736,15 +719,23 @@ pub(crate) enum WorkItem<B: WriteBackendMethods> {
/// Copy the post-LTO artifacts from the incremental cache to the output
/// directory.
CopyPostLtoArtifacts(CachedModuleCodegen),
/// Performs (Thin)LTO on the given module.
LTO(lto::LtoModuleCodegen<B>),
/// Performs fat LTO on the given module.
FatLto {
needs_fat_lto: Vec<FatLtoInput<B>>,
import_only_modules: Vec<(SerializedModule<B::ModuleBuffer>, WorkProduct)>,
autodiff: Vec<AutoDiffItem>,
},
/// Performs thin-LTO on the given module.
ThinLto(lto::ThinModule<B>),
}
impl<B: WriteBackendMethods> WorkItem<B> {
fn module_kind(&self) -> ModuleKind {
match *self {
WorkItem::Optimize(ref m) => m.kind,
WorkItem::CopyPostLtoArtifacts(_) | WorkItem::LTO(_) => ModuleKind::Regular,
WorkItem::CopyPostLtoArtifacts(_) | WorkItem::FatLto { .. } | WorkItem::ThinLto(_) => {
ModuleKind::Regular
}
}
}
@ -792,7 +783,8 @@ impl<B: WriteBackendMethods> WorkItem<B> {
match self {
WorkItem::Optimize(m) => desc("opt", "optimize module", &m.name),
WorkItem::CopyPostLtoArtifacts(m) => desc("cpy", "copy LTO artifacts for", &m.name),
WorkItem::LTO(m) => desc("lto", "LTO module", m.name()),
WorkItem::FatLto { .. } => desc("lto", "fat LTO module", "everything"),
WorkItem::ThinLto(m) => desc("lto", "thin-LTO module", m.name()),
}
}
}
@ -996,12 +988,24 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
})
}
fn execute_lto_work_item<B: ExtraBackendMethods>(
fn execute_fat_lto_work_item<B: ExtraBackendMethods>(
cgcx: &CodegenContext<B>,
module: lto::LtoModuleCodegen<B>,
needs_fat_lto: Vec<FatLtoInput<B>>,
import_only_modules: Vec<(SerializedModule<B::ModuleBuffer>, WorkProduct)>,
autodiff: Vec<AutoDiffItem>,
module_config: &ModuleConfig,
) -> Result<WorkItemResult<B>, FatalError> {
let module = module.optimize(cgcx)?;
let module = B::run_and_optimize_fat_lto(cgcx, needs_fat_lto, import_only_modules, autodiff)?;
let module = B::codegen(cgcx, module, module_config)?;
Ok(WorkItemResult::Finished(module))
}
fn execute_thin_lto_work_item<B: ExtraBackendMethods>(
cgcx: &CodegenContext<B>,
module: lto::ThinModule<B>,
module_config: &ModuleConfig,
) -> Result<WorkItemResult<B>, FatalError> {
let module = B::optimize_thin(cgcx, module)?;
finish_intra_module_work(cgcx, module, module_config)
}
@ -1010,11 +1014,8 @@ fn finish_intra_module_work<B: ExtraBackendMethods>(
module: ModuleCodegen<B::Module>,
module_config: &ModuleConfig,
) -> Result<WorkItemResult<B>, FatalError> {
let dcx = cgcx.create_dcx();
let dcx = dcx.handle();
if !cgcx.opts.unstable_opts.combine_cgu || module.kind == ModuleKind::Allocator {
let module = B::codegen(cgcx, dcx, module, module_config)?;
let module = B::codegen(cgcx, module, module_config)?;
Ok(WorkItemResult::Finished(module))
} else {
Ok(WorkItemResult::NeedsLink(module))
@ -1031,9 +1032,6 @@ pub(crate) enum Message<B: WriteBackendMethods> {
/// Sent from a backend worker thread.
WorkItem { result: Result<WorkItemResult<B>, Option<WorkerFatalError>>, worker_id: usize },
/// A vector containing all the AutoDiff tasks that we have to pass to Enzyme.
AddAutoDiffItems(Vec<AutoDiffItem>),
/// The frontend has finished generating something (backend IR or a
/// post-LTO artifact) for a codegen unit, and it should be passed to the
/// backend. Sent from the main thread.
@ -1100,6 +1098,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
backend: B,
tcx: TyCtxt<'_>,
crate_info: &CrateInfo,
autodiff_items: &[AutoDiffItem],
shared_emitter: SharedEmitter,
codegen_worker_send: Sender<CguMessage>,
coordinator_receive: Receiver<Box<dyn Any + Send>>,
@ -1109,6 +1108,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
) -> thread::JoinHandle<Result<CompiledModules, ()>> {
let coordinator_send = tx_to_llvm_workers;
let sess = tcx.sess;
let autodiff_items = autodiff_items.to_vec();
let mut each_linked_rlib_for_lto = Vec::new();
drop(link::each_linked_rlib(crate_info, None, &mut |cnum, path| {
@ -1362,7 +1362,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
// This is where we collect codegen units that have gone all the way
// through codegen and LLVM.
let mut autodiff_items = Vec::new();
let mut compiled_modules = vec![];
let mut compiled_allocator_module = None;
let mut needs_link = Vec::new();
@ -1474,20 +1473,37 @@ fn start_executing_work<B: ExtraBackendMethods>(
let needs_thin_lto = mem::take(&mut needs_thin_lto);
let import_only_modules = mem::take(&mut lto_import_only_modules);
for (work, cost) in generate_lto_work(
&cgcx,
autodiff_items.clone(),
needs_fat_lto,
needs_thin_lto,
import_only_modules,
) {
let insertion_index = work_items
.binary_search_by_key(&cost, |&(_, cost)| cost)
.unwrap_or_else(|e| e);
work_items.insert(insertion_index, (work, cost));
if !needs_fat_lto.is_empty() {
assert!(needs_thin_lto.is_empty());
work_items.push((
WorkItem::FatLto {
needs_fat_lto,
import_only_modules,
autodiff: autodiff_items.clone(),
},
0,
));
if cgcx.parallel {
helper.request_token();
}
} else {
if !autodiff_items.is_empty() {
let dcx = cgcx.create_dcx();
dcx.handle().emit_fatal(AutodiffWithoutLto {});
}
for (work, cost) in
generate_thin_lto_work(&cgcx, needs_thin_lto, import_only_modules)
{
let insertion_index = work_items
.binary_search_by_key(&cost, |&(_, cost)| cost)
.unwrap_or_else(|e| e);
work_items.insert(insertion_index, (work, cost));
if cgcx.parallel {
helper.request_token();
}
}
}
}
@ -1616,10 +1632,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
main_thread_state = MainThreadState::Idle;
}
Message::AddAutoDiffItems(mut items) => {
autodiff_items.append(&mut items);
}
Message::CodegenComplete => {
if codegen_state != Aborted {
codegen_state = Completed;
@ -1702,7 +1714,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
let dcx = dcx.handle();
let module = B::run_link(&cgcx, dcx, needs_link).map_err(|_| ())?;
let module =
B::codegen(&cgcx, dcx, module, cgcx.config(ModuleKind::Regular)).map_err(|_| ())?;
B::codegen(&cgcx, module, cgcx.config(ModuleKind::Regular)).map_err(|_| ())?;
compiled_modules.push(module);
}
@ -1842,10 +1854,22 @@ fn spawn_work<'a, B: ExtraBackendMethods>(
);
Ok(execute_copy_from_cache_work_item(&cgcx, m, module_config))
}
WorkItem::LTO(m) => {
WorkItem::FatLto { needs_fat_lto, import_only_modules, autodiff } => {
let _timer = cgcx
.prof
.generic_activity_with_arg("codegen_module_perform_lto", "everything");
execute_fat_lto_work_item(
&cgcx,
needs_fat_lto,
import_only_modules,
autodiff,
module_config,
)
}
WorkItem::ThinLto(m) => {
let _timer =
cgcx.prof.generic_activity_with_arg("codegen_module_perform_lto", m.name());
execute_lto_work_item(&cgcx, m, module_config)
execute_thin_lto_work_item(&cgcx, m, module_config)
}
})
};
@ -2082,10 +2106,6 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
drop(self.coordinator.sender.send(Box::new(Message::CodegenComplete::<B>)));
}
pub(crate) fn submit_autodiff_items(&self, items: Vec<AutoDiffItem>) {
drop(self.coordinator.sender.send(Box::new(Message::<B>::AddAutoDiffItems(items))));
}
pub(crate) fn check_for_errors(&self, sess: &Session) {
self.shared_emitter_main.check(sess, false);
}

View file

@ -647,7 +647,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
) -> OngoingCodegen<B> {
// Skip crate items and just output metadata in -Z no-codegen mode.
if tcx.sess.opts.unstable_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() {
let ongoing_codegen = start_async_codegen(backend, tcx, target_cpu);
let ongoing_codegen = start_async_codegen(backend, tcx, target_cpu, &[]);
ongoing_codegen.codegen_finished(tcx);
@ -667,7 +667,6 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
// codegen units.
let MonoItemPartitions { codegen_units, autodiff_items, .. } =
tcx.collect_and_partition_mono_items(());
let autodiff_fncs = autodiff_items.to_vec();
// Force all codegen_unit queries so they are already either red or green
// when compile_codegen_unit accesses them. We are not able to re-execute
@ -680,7 +679,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
}
}
let ongoing_codegen = start_async_codegen(backend.clone(), tcx, target_cpu);
let ongoing_codegen = start_async_codegen(backend.clone(), tcx, target_cpu, autodiff_items);
// Codegen an allocator shim, if necessary.
if let Some(kind) = allocator_kind_for_codegen(tcx) {
@ -710,10 +709,6 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
);
}
if !autodiff_fncs.is_empty() {
ongoing_codegen.submit_autodiff_items(autodiff_fncs);
}
// For better throughput during parallel processing by LLVM, we used to sort
// CGUs largest to smallest. This would lead to better thread utilization
// by, for example, preventing a large CGU from being processed last and

View file

@ -139,7 +139,8 @@ pub(crate) fn load_vtable<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
&& bx.cx().sess().lto() == Lto::Fat
{
if let Some(trait_ref) = dyn_trait_in_self(bx.tcx(), ty) {
let typeid = bx.typeid_metadata(typeid_for_trait_ref(bx.tcx(), trait_ref)).unwrap();
let typeid =
bx.typeid_metadata(typeid_for_trait_ref(bx.tcx(), trait_ref).as_bytes()).unwrap();
let func = bx.type_checked_load(llvtable, vtable_byte_offset, typeid);
return func;
} else if nonnull {

View file

@ -356,7 +356,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
LocalRef::Operand(operand) => {
// Don't spill operands onto the stack in naked functions.
// See: https://github.com/rust-lang/rust/issues/42779
let attrs = bx.tcx().codegen_fn_attrs(self.instance.def_id());
let attrs = bx.tcx().codegen_instance_attrs(self.instance.def);
if attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
return;
}

Some files were not shown because too many files have changed in this diff Show more