Merge ref '69d4d5fc0e4d' from rust-lang/rust

Pull recent changes from https://github.com/rust-lang/rust via Josh.

Upstream ref: 69d4d5fc0e
Filtered ref: 55f7a9f34e7b6dccf3ed08a163109a5e83c36b85
Upstream diff: https://github.com/rust-lang/rust/compare/8401398e1f14a24670ee1a3203713dc2f0f8b3a8...69d4d5fc0e4db60272aac85ef27ecccef5764f3a

This merge was created using https://github.com/rust-lang/josh-sync.
This commit is contained in:
The rustc-josh-sync Cronjob Bot
2025-11-17 04:23:02 +00:00
1205 changed files with 18972 additions and 11268 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ name: Post merge analysis
on:
push:
branches:
- master
- main
jobs:
analysis:
+1 -1
View File
@@ -48,7 +48,7 @@ no_llvm_build
/llvm/
/mingw-build/
/build
/build-rust-analyzer/
/build-rust-analyzer
/dist/
/unicode-downloads
/target
+34 -34
View File
@@ -80,9 +80,9 @@ dependencies = [
[[package]]
name = "annotate-snippets"
version = "0.12.8"
version = "0.12.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "025c7edcdffa4ccc5c0905f472a0ae3759378cfbef88ef518a3575e19ae3aebd"
checksum = "a44baf24dd94e781f74dfe67ffee75a09a57971ddf0f615a178b4f6d404b48ff"
dependencies = [
"anstyle",
"unicode-width 0.2.2",
@@ -1288,7 +1288,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
dependencies = [
"libc",
"windows-sys 0.52.0",
"windows-sys 0.60.2",
]
[[package]]
@@ -2154,7 +2154,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
dependencies = [
"cfg-if",
"windows-targets 0.52.6",
"windows-targets 0.53.3",
]
[[package]]
@@ -3766,7 +3766,7 @@ dependencies = [
name = "rustc_errors"
version = "0.0.0"
dependencies = [
"annotate-snippets 0.12.8",
"annotate-snippets 0.12.9",
"anstream",
"anstyle",
"derive_setters",
@@ -4905,7 +4905,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.52.0",
"windows-sys 0.61.2",
]
[[package]]
@@ -5273,9 +5273,9 @@ dependencies = [
[[package]]
name = "stringdex"
version = "0.0.2"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18b3bd4f10d15ef859c40291769f0d85209de6b0f1c30713ff9cdf45ac43ea36"
checksum = "556a6126952cb2f5150057c98a77cc6c771027dea2825bf7fa03d3d638b0a4f8"
dependencies = [
"stacker",
]
@@ -6070,9 +6070,9 @@ dependencies = [
[[package]]
name = "wasi-preview1-component-adapter-provider"
version = "37.0.2"
version = "38.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d0fcd636ad2b29a7c0490799a23ad61d1c8dedfafdb970447fddd0549502b60"
checksum = "7ec3ef3783e18f2457796ed91b1e6c2adc46f2905f740d1527ab3053fe8e5682"
[[package]]
name = "wasm-bindgen"
@@ -6134,9 +6134,9 @@ dependencies = [
[[package]]
name = "wasm-component-ld"
version = "0.5.18"
version = "0.5.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11f565dfcfd9aabb10d865b608a92ce1f93051aeb56f4c89550ed9cd97d8ce0e"
checksum = "4bfc50dd0b883d841bc1dba5ff7020ca52fa7b2c3bb1266d8bf6a09dd032e115"
dependencies = [
"anyhow",
"clap",
@@ -6144,7 +6144,7 @@ dependencies = [
"libc",
"tempfile",
"wasi-preview1-component-adapter-provider",
"wasmparser 0.240.0",
"wasmparser 0.241.2",
"wat",
"windows-sys 0.61.2",
"winsplit",
@@ -6171,24 +6171,24 @@ dependencies = [
[[package]]
name = "wasm-encoder"
version = "0.240.0"
version = "0.241.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06d642d8c5ecc083aafe9ceb32809276a304547a3a6eeecceb5d8152598bc71f"
checksum = "e01164c9dda68301e34fdae536c23ed6fe90ce6d97213ccc171eebbd3d02d6b8"
dependencies = [
"leb128fmt",
"wasmparser 0.240.0",
"wasmparser 0.241.2",
]
[[package]]
name = "wasm-metadata"
version = "0.240.0"
version = "0.241.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee093e1e1ccffa005b9b778f7a10ccfd58e25a20eccad294a1a93168d076befb"
checksum = "876fe286f2fa416386deedebe8407e6f19e0b5aeaef3d03161e77a15fa80f167"
dependencies = [
"anyhow",
"indexmap",
"wasm-encoder 0.240.0",
"wasmparser 0.240.0",
"wasm-encoder 0.241.2",
"wasmparser 0.241.2",
]
[[package]]
@@ -6213,9 +6213,9 @@ dependencies = [
[[package]]
name = "wasmparser"
version = "0.240.0"
version = "0.241.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b722dcf61e0ea47440b53ff83ccb5df8efec57a69d150e4f24882e4eba7e24a4"
checksum = "46d90019b1afd4b808c263e428de644f3003691f243387d30d673211ee0cb8e8"
dependencies = [
"bitflags",
"hashbrown",
@@ -6226,22 +6226,22 @@ dependencies = [
[[package]]
name = "wast"
version = "240.0.0"
version = "241.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0efe1c93db4ac562b9733e3dca19ed7fc878dba29aef22245acf84f13da4a19"
checksum = "63f66e07e2ddf531fef6344dbf94d112df7c2f23ed6ffb10962e711500b8d816"
dependencies = [
"bumpalo",
"leb128fmt",
"memchr",
"unicode-width 0.2.2",
"wasm-encoder 0.240.0",
"wasm-encoder 0.241.2",
]
[[package]]
name = "wat"
version = "1.240.0"
version = "1.241.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ec9b6eab7ecd4d639d78515e9ea491c9bacf494aa5eda10823bd35992cf8c1e"
checksum = "45f923705c40830af909c5dec2352ec2821202e4a66008194585e1917458a26d"
dependencies = [
"wast",
]
@@ -6679,9 +6679,9 @@ dependencies = [
[[package]]
name = "wit-component"
version = "0.240.0"
version = "0.241.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dc5474b078addc5fe8a72736de8da3acfb3ff324c2491133f8b59594afa1a20"
checksum = "1fd0c57df25e7ee612d946d3b7646c1ddb2310f8280aa2c17e543b66e0812241"
dependencies = [
"anyhow",
"bitflags",
@@ -6690,17 +6690,17 @@ dependencies = [
"serde",
"serde_derive",
"serde_json",
"wasm-encoder 0.240.0",
"wasm-encoder 0.241.2",
"wasm-metadata",
"wasmparser 0.240.0",
"wasmparser 0.241.2",
"wit-parser",
]
[[package]]
name = "wit-parser"
version = "0.240.0"
version = "0.241.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9875ea3fa272f57cc1fc50f225a7b94021a7878c484b33792bccad0d93223439"
checksum = "09ef1c6ad67f35c831abd4039c02894de97034100899614d1c44e2268ad01c91"
dependencies = [
"anyhow",
"id-arena",
@@ -6711,7 +6711,7 @@ dependencies = [
"serde_derive",
"serde_json",
"unicode-xid",
"wasmparser 0.240.0",
"wasmparser 0.241.2",
]
[[package]]
+5 -2
View File
@@ -59,7 +59,10 @@
# toolchain or changing LLVM locally, you probably want to leave this enabled.
#
# Set this to `true` to download if CI llvm available otherwise it builds
# from `src/llvm-project`.
# from `src/llvm-project`. If you set it to `true`, it's safe and time-saving to run
# `git submodule deinit src/llvm-project` to avoid git updating the llvm-project submodule
# when building compiler locally.
#
#
# Set this to `"if-unchanged"` to download only if the llvm-project has not
# been modified. You can also use this if you are unsure whether you're on a
@@ -320,7 +323,7 @@
#build.npm = "npm"
# Python interpreter to use for various tasks throughout the build, notably
# rustdoc tests, the lldb python interpreter, and some dist bits and pieces.
# rustdoc tests, and some dist bits and pieces.
#
# Defaults to the Python interpreter used to execute x.py.
#build.python = "python"
+47 -4
View File
@@ -269,13 +269,56 @@ pub fn supports_c_variadic(self) -> CVariadicStatus {
| Self::Aapcs { .. }
| Self::Win64 { .. }
| Self::SysV64 { .. }
| Self::EfiApi => CVariadicStatus::Stable,
Self::System { .. } => {
CVariadicStatus::Unstable { feature: rustc_span::sym::extern_system_varargs }
}
| Self::EfiApi
| Self::System { .. } => CVariadicStatus::Stable,
_ => CVariadicStatus::NotSupported,
}
}
/// Returns whether the ABI supports guaranteed tail calls.
#[cfg(feature = "nightly")]
pub fn supports_guaranteed_tail_call(self) -> bool {
match self {
Self::CmseNonSecureCall | Self::CmseNonSecureEntry => {
// See https://godbolt.org/z/9jhdeqErv. The CMSE calling conventions clear registers
// before returning, and hence cannot guarantee a tail call.
false
}
Self::AvrInterrupt
| Self::AvrNonBlockingInterrupt
| Self::Msp430Interrupt
| Self::RiscvInterruptM
| Self::RiscvInterruptS
| Self::X86Interrupt => {
// See https://godbolt.org/z/Edfjnxxcq. Interrupts cannot be called directly.
false
}
Self::GpuKernel | Self::PtxKernel => {
// See https://godbolt.org/z/jq5TE5jK1.
false
}
Self::Custom => {
// This ABI does not support calls at all (except via assembly).
false
}
Self::C { .. }
| Self::System { .. }
| Self::Rust
| Self::RustCall
| Self::RustCold
| Self::RustInvalid
| Self::Unadjusted
| Self::EfiApi
| Self::Aapcs { .. }
| Self::Cdecl { .. }
| Self::Stdcall { .. }
| Self::Fastcall { .. }
| Self::Thiscall { .. }
| Self::Vectorcall { .. }
| Self::SysV64 { .. }
| Self::Win64 { .. } => true,
}
}
}
pub fn all_names() -> Vec<&'static str> {
+10 -7
View File
@@ -648,9 +648,10 @@ pub fn to_ty(&self) -> Option<Box<Ty>> {
PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
PatKind::MacCall(mac) => TyKind::MacCall(mac.clone()),
// `&mut? P` can be reinterpreted as `&mut? T` where `T` is `P` reparsed as a type.
PatKind::Ref(pat, mutbl) => {
pat.to_ty().map(|ty| TyKind::Ref(None, MutTy { ty, mutbl: *mutbl }))?
}
PatKind::Ref(pat, pinned, mutbl) => pat.to_ty().map(|ty| match pinned {
Pinnedness::Not => TyKind::Ref(None, MutTy { ty, mutbl: *mutbl }),
Pinnedness::Pinned => TyKind::PinnedRef(None, MutTy { ty, mutbl: *mutbl }),
})?,
// A slice/array pattern `[P]` can be reparsed as `[T]`, an unsized array,
// when `P` can be reparsed as a type `T`.
PatKind::Slice(pats) if let [pat] = pats.as_slice() => {
@@ -696,7 +697,7 @@ pub fn walk<'ast>(&'ast self, it: &mut impl FnMut(&'ast Pat) -> bool) {
// Trivial wrappers over inner patterns.
PatKind::Box(s)
| PatKind::Deref(s)
| PatKind::Ref(s, _)
| PatKind::Ref(s, _, _)
| PatKind::Paren(s)
| PatKind::Guard(s, _) => s.walk(it),
@@ -717,7 +718,7 @@ pub fn walk<'ast>(&'ast self, it: &mut impl FnMut(&'ast Pat) -> bool) {
/// Strip off all reference patterns (`&`, `&mut`) and return the inner pattern.
pub fn peel_refs(&self) -> &Pat {
let mut current = self;
while let PatKind::Ref(inner, _) = &current.kind {
while let PatKind::Ref(inner, _, _) = &current.kind {
current = inner;
}
current
@@ -765,7 +766,9 @@ pub fn descr(&self) -> Option<String> {
PatKind::Missing => unreachable!(),
PatKind::Wild => Some("_".to_string()),
PatKind::Ident(BindingMode::NONE, ident, None) => Some(format!("{ident}")),
PatKind::Ref(pat, mutbl) => pat.descr().map(|d| format!("&{}{d}", mutbl.prefix_str())),
PatKind::Ref(pat, pinned, mutbl) => {
pat.descr().map(|d| format!("&{}{d}", pinned.prefix_str(*mutbl)))
}
_ => None,
}
}
@@ -913,7 +916,7 @@ pub enum PatKind {
Deref(Box<Pat>),
/// A reference pattern (e.g., `&mut (a, b)`).
Ref(Box<Pat>, Mutability),
Ref(Box<Pat>, Pinnedness, Mutability),
/// A literal, const block or path.
Expr(Box<Expr>),
+11 -6
View File
@@ -645,8 +645,9 @@ fn visit_assoc_item(&mut self, item: &$($lt)? $($mut)? AssocItem, ctxt: AssocCtx
fn visit_fn(
&mut self,
fk: FnKind<$($lt)? $(${ignore($mut)} '_)?>,
_: &AttrVec,
_: Span,
_: NodeId
_: NodeId,
) -> Self::Result {
walk_fn(self, fk)
}
@@ -740,6 +741,7 @@ pub trait WalkItemKind {
type Ctxt;
fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
&$($lt)? $($mut)? self,
attrs: &AttrVec,
span: Span,
id: NodeId,
visibility: &$($lt)? $($mut)? Visibility,
@@ -773,7 +775,7 @@ fn walk_item_inner<$($lt,)? K: WalkItemKind, V: $Visitor$(<$lt>)?>(
) -> V::Result {
let Item { attrs, id, kind, vis, span, tokens: _ } = item;
visit_visitable!($($mut)? visitor, id, attrs, vis);
try_visit!(kind.walk(*span, *id, vis, ctxt, visitor));
try_visit!(kind.walk(attrs, *span, *id, vis, ctxt, visitor));
visit_visitable!($($mut)? visitor, span);
V::Result::output()
}
@@ -799,6 +801,7 @@ impl WalkItemKind for ItemKind {
type Ctxt = ();
fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
&$($lt)? $($mut)? self,
attrs: &AttrVec,
span: Span,
id: NodeId,
visibility: &$($lt)? $($mut)? Visibility,
@@ -808,7 +811,7 @@ fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
match self {
ItemKind::Fn(func) => {
let kind = FnKind::Fn(FnCtxt::Free, visibility, &$($mut)? *func);
try_visit!(vis.visit_fn(kind, span, id));
try_visit!(vis.visit_fn(kind, attrs, span, id));
}
ItemKind::ExternCrate(orig_name, ident) =>
visit_visitable!($($mut)? vis, orig_name, ident),
@@ -856,6 +859,7 @@ impl WalkItemKind for AssocItemKind {
type Ctxt = AssocCtxt;
fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
&$($lt)? $($mut)? self,
attrs: &AttrVec,
span: Span,
id: NodeId,
visibility: &$($lt)? $($mut)? Visibility,
@@ -867,7 +871,7 @@ fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
visit_visitable!($($mut)? vis, item),
AssocItemKind::Fn(func) => {
let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), visibility, &$($mut)? *func);
try_visit!(vis.visit_fn(kind, span, id))
try_visit!(vis.visit_fn(kind, attrs, span, id))
}
AssocItemKind::Type(alias) =>
visit_visitable!($($mut)? vis, alias),
@@ -886,6 +890,7 @@ impl WalkItemKind for ForeignItemKind {
type Ctxt = ();
fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
&$($lt)? $($mut)? self,
attrs: &AttrVec,
span: Span,
id: NodeId,
visibility: &$($lt)? $($mut)? Visibility,
@@ -897,7 +902,7 @@ fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
visit_visitable!($($mut)? vis, item),
ForeignItemKind::Fn(func) => {
let kind = FnKind::Fn(FnCtxt::Foreign, visibility, &$($mut)?*func);
try_visit!(vis.visit_fn(kind, span, id))
try_visit!(vis.visit_fn(kind, attrs, span, id))
}
ForeignItemKind::TyAlias(alias) =>
visit_visitable!($($mut)? vis, alias),
@@ -999,7 +1004,7 @@ pub fn walk_fn<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, kind: FnKind<$($lt)?
}) => {
visit_visitable!($($mut)? vis, constness, movability, capture_clause);
let kind = FnKind::Closure(binder, coroutine_kind, fn_decl, body);
try_visit!(vis.visit_fn(kind, *span, *id));
try_visit!(vis.visit_fn(kind, attrs, *span, *id));
visit_visitable!($($mut)? vis, fn_decl_span, fn_arg_span);
}
ExprKind::Block(block, opt_label) =>
+11
View File
@@ -317,4 +317,15 @@ impl Pinnedness {
pub fn is_pinned(self) -> bool {
matches!(self, Self::Pinned)
}
/// Returns `""` (empty string), "mut", `"pin mut "` or `"pin const "` depending
/// on the pinnedness and mutability.
pub fn prefix_str(self, mutbl: Mutability) -> &'static str {
match (self, mutbl) {
(Pinnedness::Pinned, Mutability::Mut) => "pin mut ",
(Pinnedness::Pinned, Mutability::Not) => "pin const ",
(Pinnedness::Not, Mutability::Mut) => "mut ",
(Pinnedness::Not, Mutability::Not) => "",
}
}
}
+31 -39
View File
@@ -13,7 +13,7 @@
use rustc_middle::ty::TyCtxt;
use rustc_session::errors::report_lit_error;
use rustc_span::source_map::{Spanned, respan};
use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, Symbol, sym};
use rustc_span::{ByteSymbol, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, sym};
use thin_vec::{ThinVec, thin_vec};
use visit::{Visitor, walk_expr};
@@ -924,7 +924,7 @@ fn make_lowered_await(
arena_vec![self; new_unchecked, get_context],
),
};
self.arena.alloc(self.expr_unsafe(call))
self.arena.alloc(self.expr_unsafe(span, call))
};
// `::std::task::Poll::Ready(result) => break result`
@@ -1771,8 +1771,14 @@ fn lower_expr_for(
let pat = self.lower_pat(pat);
let for_span =
self.mark_span_with_reason(DesugaringKind::ForLoop, self.lower_span(e.span), None);
let head_span = self.mark_span_with_reason(DesugaringKind::ForLoop, head.span, None);
let pat_span = self.mark_span_with_reason(DesugaringKind::ForLoop, pat.span, None);
let for_ctxt = for_span.ctxt();
// Try to point both the head and pat spans to their position in the for loop
// rather than inside a macro.
let head_span =
head.span.find_ancestor_in_same_ctxt(e.span).unwrap_or(head.span).with_ctxt(for_ctxt);
let pat_span =
pat.span.find_ancestor_in_same_ctxt(e.span).unwrap_or(pat.span).with_ctxt(for_ctxt);
let loop_hir_id = self.lower_node_id(e.id);
let label = self.lower_label(opt_label, e.id, loop_hir_id);
@@ -1826,7 +1832,7 @@ fn lower_expr_for(
arena_vec![self; iter],
));
// `unsafe { ... }`
let iter = self.arena.alloc(self.expr_unsafe(iter));
let iter = self.arena.alloc(self.expr_unsafe(head_span, iter));
let kind = self.make_lowered_await(head_span, iter, FutureKind::AsyncIterator);
self.arena.alloc(hir::Expr { hir_id: self.next_id(), kind, span: head_span })
}
@@ -1881,7 +1887,7 @@ fn lower_expr_for(
arena_vec![self; iter],
));
// `unsafe { ... }`
let iter = self.arena.alloc(self.expr_unsafe(iter));
let iter = self.arena.alloc(self.expr_unsafe(head_span, iter));
let inner_match_expr = self.arena.alloc(self.expr_match(
for_span,
iter,
@@ -1923,7 +1929,7 @@ fn lower_expr_for(
/// ControlFlow::Break(residual) =>
/// #[allow(unreachable_code)]
/// // If there is an enclosing `try {...}`:
/// break 'catch_target Try::from_residual(residual),
/// break 'catch_target Residual::into_try_type(residual),
/// // Otherwise:
/// return Try::from_residual(residual),
/// }
@@ -1973,7 +1979,11 @@ fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir>
let (residual_local, residual_local_nid) = self.pat_ident(try_span, residual_ident);
let residual_expr = self.expr_ident_mut(try_span, residual_ident, residual_local_nid);
let from_residual_expr = self.wrap_in_try_constructor(
hir::LangItem::TryTraitFromResidual,
if self.catch_scope.is_some() {
hir::LangItem::ResidualIntoTryType
} else {
hir::LangItem::TryTraitFromResidual
},
try_span,
self.arena.alloc(residual_expr),
unstable_span,
@@ -2097,26 +2107,6 @@ pub(super) fn expr_unit(&mut self, sp: Span) -> &'hir hir::Expr<'hir> {
self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[])))
}
fn expr_uint(&mut self, sp: Span, ty: ast::UintTy, value: u128) -> hir::Expr<'hir> {
let lit = hir::Lit {
span: self.lower_span(sp),
node: ast::LitKind::Int(value.into(), ast::LitIntType::Unsigned(ty)),
};
self.expr(sp, hir::ExprKind::Lit(lit))
}
pub(super) fn expr_usize(&mut self, sp: Span, value: usize) -> hir::Expr<'hir> {
self.expr_uint(sp, ast::UintTy::Usize, value as u128)
}
pub(super) fn expr_u32(&mut self, sp: Span, value: u32) -> hir::Expr<'hir> {
self.expr_uint(sp, ast::UintTy::U32, value as u128)
}
pub(super) fn expr_u16(&mut self, sp: Span, value: u16) -> hir::Expr<'hir> {
self.expr_uint(sp, ast::UintTy::U16, value as u128)
}
pub(super) fn expr_str(&mut self, sp: Span, value: Symbol) -> hir::Expr<'hir> {
let lit = hir::Lit {
span: self.lower_span(sp),
@@ -2125,6 +2115,14 @@ pub(super) fn expr_str(&mut self, sp: Span, value: Symbol) -> hir::Expr<'hir> {
self.expr(sp, hir::ExprKind::Lit(lit))
}
pub(super) fn expr_byte_str(&mut self, sp: Span, value: ByteSymbol) -> hir::Expr<'hir> {
let lit = hir::Lit {
span: self.lower_span(sp),
node: ast::LitKind::ByteStr(value, ast::StrStyle::Cooked),
};
self.expr(sp, hir::ExprKind::Lit(lit))
}
pub(super) fn expr_call_mut(
&mut self,
span: Span,
@@ -2256,9 +2254,12 @@ pub(super) fn expr_ident_mut(
self.expr(span, expr_path)
}
fn expr_unsafe(&mut self, expr: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
pub(super) fn expr_unsafe(
&mut self,
span: Span,
expr: &'hir hir::Expr<'hir>,
) -> hir::Expr<'hir> {
let hir_id = self.next_id();
let span = expr.span;
self.expr(
span,
hir::ExprKind::Block(
@@ -2296,15 +2297,6 @@ pub(super) fn block_expr_block(
self.arena.alloc(self.expr_block(b))
}
pub(super) fn expr_array_ref(
&mut self,
span: Span,
elements: &'hir [hir::Expr<'hir>],
) -> hir::Expr<'hir> {
let array = self.arena.alloc(self.expr(span, hir::ExprKind::Array(elements)));
self.expr_ref(span, array)
}
pub(super) fn expr_ref(&mut self, span: Span, expr: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
self.expr(span, hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, expr))
}
+198 -264
View File
@@ -4,7 +4,7 @@
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir as hir;
use rustc_session::config::FmtDebug;
use rustc_span::{DesugaringKind, Ident, Span, Symbol, sym};
use rustc_span::{ByteSymbol, DesugaringKind, Ident, Span, Symbol, sym};
use super::LoweringContext;
@@ -90,20 +90,14 @@ fn inline_literals<'fmt>(&self, mut fmt: Cow<'fmt, FormatArgs>) -> Cow<'fmt, For
let mut inlined_anything = false;
for i in 0..fmt.template.len() {
let FormatArgsPiece::Placeholder(placeholder) = &fmt.template[i] else { continue };
let Ok(arg_index) = placeholder.argument.index else { continue };
let mut literal = None;
if let FormatTrait::Display = placeholder.format_trait
if let FormatArgsPiece::Placeholder(placeholder) = &fmt.template[i]
&& let Ok(arg_index) = placeholder.argument.index
&& let FormatTrait::Display = placeholder.format_trait
&& placeholder.format_options == Default::default()
&& let arg = fmt.arguments.all_args()[arg_index].expr.peel_parens_and_refs()
&& let ExprKind::Lit(lit) = arg.kind
&& let Some(literal) = self.try_inline_lit(lit)
{
literal = self.try_inline_lit(lit);
}
if let Some(literal) = literal {
// Now we need to mutate the outer FormatArgs.
// If this is the first time, this clones the outer FormatArgs.
let fmt = fmt.to_mut();
@@ -265,136 +259,21 @@ fn make_argument<'hir>(
ctx.expr_call_mut(sp, new_fn, std::slice::from_ref(arg))
}
/// Generate a hir expression for a format_args Count.
/// Get the value for a `width` or `precision` field.
///
/// Generates:
///
/// ```text
/// <core::fmt::rt::Count>::Is(…)
/// ```
///
/// or
///
/// ```text
/// <core::fmt::rt::Count>::Param(…)
/// ```
///
/// or
///
/// ```text
/// <core::fmt::rt::Count>::Implied
/// ```
fn make_count<'hir>(
ctx: &mut LoweringContext<'_, 'hir>,
sp: Span,
count: &Option<FormatCount>,
/// Returns the value and whether it is indirect (an indexed argument) or not.
fn make_count(
count: &FormatCount,
argmap: &mut FxIndexMap<(usize, ArgumentType), Option<Span>>,
) -> hir::Expr<'hir> {
) -> (bool, u16) {
match count {
Some(FormatCount::Literal(n)) => {
let count_is = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
sp,
hir::LangItem::FormatCount,
sym::Is,
));
let value = ctx.arena.alloc_from_iter([ctx.expr_u16(sp, *n)]);
ctx.expr_call_mut(sp, count_is, value)
}
Some(FormatCount::Argument(arg)) => {
if let Ok(arg_index) = arg.index {
let (i, _) = argmap.insert_full((arg_index, ArgumentType::Usize), arg.span);
let count_param = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
sp,
hir::LangItem::FormatCount,
sym::Param,
));
let value = ctx.arena.alloc_from_iter([ctx.expr_usize(sp, i)]);
ctx.expr_call_mut(sp, count_param, value)
} else {
ctx.expr(
sp,
hir::ExprKind::Err(
ctx.dcx().span_delayed_bug(sp, "lowered bad format_args count"),
),
)
}
}
None => ctx.expr_lang_item_type_relative(sp, hir::LangItem::FormatCount, sym::Implied),
}
}
/// Generate a hir expression for a format_args placeholder specification.
///
/// Generates
///
/// ```text
/// <core::fmt::rt::Placeholder {
/// position: …usize,
/// flags: …u32,
/// precision: <core::fmt::rt::Count::…>,
/// width: <core::fmt::rt::Count::…>,
/// }
/// ```
fn make_format_spec<'hir>(
ctx: &mut LoweringContext<'_, 'hir>,
sp: Span,
placeholder: &FormatPlaceholder,
argmap: &mut FxIndexMap<(usize, ArgumentType), Option<Span>>,
) -> hir::Expr<'hir> {
let position = match placeholder.argument.index {
Ok(arg_index) => {
let (i, _) = argmap.insert_full(
(arg_index, ArgumentType::Format(placeholder.format_trait)),
placeholder.span,
);
ctx.expr_usize(sp, i)
}
Err(_) => ctx.expr(
sp,
hir::ExprKind::Err(ctx.dcx().span_delayed_bug(sp, "lowered bad format_args count")),
FormatCount::Literal(n) => (false, *n),
FormatCount::Argument(arg) => (
true,
argmap.insert_full((arg.index.unwrap_or(usize::MAX), ArgumentType::Usize), arg.span).0
as u16,
),
};
let &FormatOptions {
ref width,
ref precision,
alignment,
fill,
sign,
alternate,
zero_pad,
debug_hex,
} = &placeholder.format_options;
let fill = fill.unwrap_or(' ');
// These need to match the constants in library/core/src/fmt/rt.rs.
let align = match alignment {
Some(FormatAlignment::Left) => 0,
Some(FormatAlignment::Right) => 1,
Some(FormatAlignment::Center) => 2,
None => 3,
};
// This needs to match the constants in library/core/src/fmt/rt.rs.
let flags: u32 = fill as u32
| ((sign == Some(FormatSign::Plus)) as u32) << 21
| ((sign == Some(FormatSign::Minus)) as u32) << 22
| (alternate as u32) << 23
| (zero_pad as u32) << 24
| ((debug_hex == Some(FormatDebugHex::Lower)) as u32) << 25
| ((debug_hex == Some(FormatDebugHex::Upper)) as u32) << 26
| (width.is_some() as u32) << 27
| (precision.is_some() as u32) << 28
| align << 29
| 1 << 31; // Highest bit always set.
let flags = ctx.expr_u32(sp, flags);
let precision = make_count(ctx, sp, precision, argmap);
let width = make_count(ctx, sp, width, argmap);
let position = ctx.expr_field(Ident::new(sym::position, sp), ctx.arena.alloc(position), sp);
let flags = ctx.expr_field(Ident::new(sym::flags, sp), ctx.arena.alloc(flags), sp);
let precision = ctx.expr_field(Ident::new(sym::precision, sp), ctx.arena.alloc(precision), sp);
let width = ctx.expr_field(Ident::new(sym::width, sp), ctx.arena.alloc(width), sp);
let placeholder =
ctx.arena.alloc(ctx.make_lang_item_qpath(hir::LangItem::FormatPlaceholder, sp, None));
let fields = ctx.arena.alloc_from_iter([position, flags, precision, width]);
ctx.expr(sp, hir::ExprKind::Struct(placeholder, fields, hir::StructTailExpr::None))
}
}
fn expand_format_args<'hir>(
@@ -405,85 +284,152 @@ fn expand_format_args<'hir>(
) -> hir::ExprKind<'hir> {
let macsp = ctx.lower_span(macsp);
let mut incomplete_lit = String::new();
let lit_pieces =
ctx.arena.alloc_from_iter(fmt.template.iter().enumerate().filter_map(|(i, piece)| {
match piece {
&FormatArgsPiece::Literal(s) => {
// Coalesce adjacent literal pieces.
if let Some(FormatArgsPiece::Literal(_)) = fmt.template.get(i + 1) {
incomplete_lit.push_str(s.as_str());
None
} else if !incomplete_lit.is_empty() {
incomplete_lit.push_str(s.as_str());
let s = Symbol::intern(&incomplete_lit);
incomplete_lit.clear();
Some(ctx.expr_str(fmt.span, s))
} else {
Some(ctx.expr_str(fmt.span, s))
}
}
&FormatArgsPiece::Placeholder(_) => {
// Inject empty string before placeholders when not already preceded by a literal piece.
if i == 0 || matches!(fmt.template[i - 1], FormatArgsPiece::Placeholder(_)) {
Some(ctx.expr_str(fmt.span, sym::empty))
} else {
None
}
}
}
}));
let lit_pieces = ctx.expr_array_ref(fmt.span, lit_pieces);
// Whether we'll use the `Arguments::new_v1_formatted` form (true),
// or the `Arguments::new_v1` form (false).
let mut use_format_options = false;
// Create a list of all _unique_ (argument, format trait) combinations.
// E.g. "{0} {0:x} {0} {1}" -> [(0, Display), (0, LowerHex), (1, Display)]
//
// We use usize::MAX for arguments that don't exist, because that can never be a valid index
// into the arguments array.
let mut argmap = FxIndexMap::default();
for piece in &fmt.template {
let FormatArgsPiece::Placeholder(placeholder) = piece else { continue };
if placeholder.format_options != Default::default() {
// Can't use basic form if there's any formatting options.
use_format_options = true;
}
if let Ok(index) = placeholder.argument.index {
if argmap
.insert((index, ArgumentType::Format(placeholder.format_trait)), placeholder.span)
.is_some()
{
// Duplicate (argument, format trait) combination,
// which we'll only put once in the args array.
use_format_options = true;
let mut incomplete_lit = String::new();
let mut implicit_arg_index = 0;
let mut bytecode = Vec::new();
let template = if fmt.template.is_empty() {
// Treat empty templates as a single literal piece (with an empty string),
// so we produce `from_str("")` for those.
&[FormatArgsPiece::Literal(sym::empty)][..]
} else {
&fmt.template[..]
};
// See library/core/src/fmt/mod.rs for the format string encoding format.
for (i, piece) in template.iter().enumerate() {
match piece {
&FormatArgsPiece::Literal(sym) => {
// Coalesce adjacent literal pieces.
if let Some(FormatArgsPiece::Literal(_)) = template.get(i + 1) {
incomplete_lit.push_str(sym.as_str());
continue;
}
let mut s = if incomplete_lit.is_empty() {
sym.as_str()
} else {
incomplete_lit.push_str(sym.as_str());
&incomplete_lit
};
// If this is the last piece and was the only piece, that means
// there are no placeholders and the entire format string is just a literal.
//
// In that case, we can just use `from_str`.
if i + 1 == template.len() && bytecode.is_empty() {
// Generate:
// <core::fmt::Arguments>::from_str("meow")
let from_str = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
macsp,
hir::LangItem::FormatArguments,
if allow_const { sym::from_str } else { sym::from_str_nonconst },
));
let sym = if incomplete_lit.is_empty() { sym } else { Symbol::intern(s) };
let s = ctx.expr_str(fmt.span, sym);
let args = ctx.arena.alloc_from_iter([s]);
return hir::ExprKind::Call(from_str, args);
}
// Encode the literal in chunks of up to u16::MAX bytes, split at utf-8 boundaries.
while !s.is_empty() {
let len = s.floor_char_boundary(usize::from(u16::MAX));
if len < 0x80 {
bytecode.push(len as u8);
} else {
bytecode.push(0x80);
bytecode.extend_from_slice(&(len as u16).to_le_bytes());
}
bytecode.extend(&s.as_bytes()[..len]);
s = &s[len..];
}
incomplete_lit.clear();
}
FormatArgsPiece::Placeholder(p) => {
// Push the start byte and remember its index so we can set the option bits later.
let i = bytecode.len();
bytecode.push(0xC0);
let position = argmap
.insert_full(
(
p.argument.index.unwrap_or(usize::MAX),
ArgumentType::Format(p.format_trait),
),
p.span,
)
.0 as u64;
// This needs to match the constants in library/core/src/fmt/mod.rs.
let o = &p.format_options;
let align = match o.alignment {
Some(FormatAlignment::Left) => 0,
Some(FormatAlignment::Right) => 1,
Some(FormatAlignment::Center) => 2,
None => 3,
};
let default_flags = 0x6000_0020;
let flags: u32 = o.fill.unwrap_or(' ') as u32
| ((o.sign == Some(FormatSign::Plus)) as u32) << 21
| ((o.sign == Some(FormatSign::Minus)) as u32) << 22
| (o.alternate as u32) << 23
| (o.zero_pad as u32) << 24
| ((o.debug_hex == Some(FormatDebugHex::Lower)) as u32) << 25
| ((o.debug_hex == Some(FormatDebugHex::Upper)) as u32) << 26
| (o.width.is_some() as u32) << 27
| (o.precision.is_some() as u32) << 28
| align << 29;
if flags != default_flags {
bytecode[i] |= 1;
bytecode.extend_from_slice(&flags.to_le_bytes());
if let Some(val) = &o.width {
let (indirect, val) = make_count(val, &mut argmap);
// Only encode if nonzero; zero is the default.
if indirect || val != 0 {
bytecode[i] |= 1 << 1 | (indirect as u8) << 4;
bytecode.extend_from_slice(&val.to_le_bytes());
}
}
if let Some(val) = &o.precision {
let (indirect, val) = make_count(val, &mut argmap);
// Only encode if nonzero; zero is the default.
if indirect || val != 0 {
bytecode[i] |= 1 << 2 | (indirect as u8) << 5;
bytecode.extend_from_slice(&val.to_le_bytes());
}
}
}
if implicit_arg_index != position {
bytecode[i] |= 1 << 3;
bytecode.extend_from_slice(&(position as u16).to_le_bytes());
}
implicit_arg_index = position + 1;
}
}
}
let format_options = use_format_options.then(|| {
// Generate:
// &[format_spec_0, format_spec_1, format_spec_2]
let elements = ctx.arena.alloc_from_iter(fmt.template.iter().filter_map(|piece| {
let FormatArgsPiece::Placeholder(placeholder) = piece else { return None };
Some(make_format_spec(ctx, macsp, placeholder, &mut argmap))
}));
ctx.expr_array_ref(macsp, elements)
});
assert!(incomplete_lit.is_empty());
// Zero terminator.
bytecode.push(0);
// Ensure all argument indexes actually fit in 16 bits, as we truncated them to 16 bits before.
if argmap.len() > u16::MAX as usize {
ctx.dcx().span_err(macsp, "too many format arguments");
}
let arguments = fmt.arguments.all_args();
if allow_const && arguments.is_empty() && argmap.is_empty() {
// Generate:
// <core::fmt::Arguments>::new_const(lit_pieces)
let new = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
macsp,
hir::LangItem::FormatArguments,
sym::new_const,
));
let new_args = ctx.arena.alloc_from_iter([lit_pieces]);
return hir::ExprKind::Call(new, new_args);
}
let (let_statements, args) = if arguments.is_empty() {
// Generate:
// []
@@ -512,22 +458,30 @@ fn expand_format_args<'hir>(
// ];
let args = ctx.arena.alloc_from_iter(argmap.iter().map(
|(&(arg_index, ty), &placeholder_span)| {
let arg = &arguments[arg_index];
let placeholder_span =
placeholder_span.unwrap_or(arg.expr.span).with_ctxt(macsp.ctxt());
let arg_span = match arg.kind {
FormatArgumentKind::Captured(_) => placeholder_span,
_ => arg.expr.span.with_ctxt(macsp.ctxt()),
};
let args_ident_expr = ctx.expr_ident(macsp, args_ident, args_hir_id);
let arg = ctx.arena.alloc(ctx.expr(
arg_span,
hir::ExprKind::Field(
args_ident_expr,
Ident::new(sym::integer(arg_index), macsp),
),
));
make_argument(ctx, placeholder_span, arg, ty)
if let Some(arg) = arguments.get(arg_index) {
let placeholder_span =
placeholder_span.unwrap_or(arg.expr.span).with_ctxt(macsp.ctxt());
let arg_span = match arg.kind {
FormatArgumentKind::Captured(_) => placeholder_span,
_ => arg.expr.span.with_ctxt(macsp.ctxt()),
};
let args_ident_expr = ctx.expr_ident(macsp, args_ident, args_hir_id);
let arg = ctx.arena.alloc(ctx.expr(
arg_span,
hir::ExprKind::Field(
args_ident_expr,
Ident::new(sym::integer(arg_index), macsp),
),
));
make_argument(ctx, placeholder_span, arg, ty)
} else {
ctx.expr(
macsp,
hir::ExprKind::Err(
ctx.dcx().span_delayed_bug(macsp, "missing format_args argument"),
),
)
}
},
));
let args = ctx.arena.alloc(ctx.expr(macsp, hir::ExprKind::Array(args)));
@@ -540,58 +494,38 @@ fn expand_format_args<'hir>(
};
// Generate:
// &args
let args = ctx.expr_ref(macsp, args);
let call = if let Some(format_options) = format_options {
// Generate:
// unsafe {
// <core::fmt::Arguments>::new_v1_formatted(
// lit_pieces,
// args,
// format_options,
// )
// }
let new_v1_formatted = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
// unsafe {
// <core::fmt::Arguments>::new(b"…", &args)
// }
let template = ctx.expr_byte_str(macsp, ByteSymbol::intern(&bytecode));
let call = {
let new = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
macsp,
hir::LangItem::FormatArguments,
sym::new_v1_formatted,
sym::new,
));
let args = ctx.arena.alloc_from_iter([lit_pieces, args, format_options]);
let call = ctx.expr_call(macsp, new_v1_formatted, args);
let hir_id = ctx.next_id();
hir::ExprKind::Block(
ctx.arena.alloc(hir::Block {
stmts: &[],
expr: Some(call),
hir_id,
rules: hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::CompilerGenerated),
span: macsp,
targeted_by_break: false,
}),
None,
)
} else {
// Generate:
// <core::fmt::Arguments>::new_v1(
// lit_pieces,
// args,
// )
let new_v1 = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
macsp,
hir::LangItem::FormatArguments,
sym::new_v1,
));
let new_args = ctx.arena.alloc_from_iter([lit_pieces, args]);
hir::ExprKind::Call(new_v1, new_args)
let args = ctx.expr_ref(macsp, args);
let new_args = ctx.arena.alloc_from_iter([template, args]);
ctx.expr_call(macsp, new, new_args)
};
let call = hir::ExprKind::Block(
ctx.arena.alloc(hir::Block {
stmts: &[],
expr: Some(call),
hir_id: ctx.next_id(),
rules: hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::CompilerGenerated),
span: macsp,
targeted_by_break: false,
}),
None,
);
if !let_statements.is_empty() {
// Generate:
// {
// super let …
// super let …
// <core::fmt::Arguments>::new_…(…)
// <core::fmt::Arguments>::new(…)
// }
let call = ctx.arena.alloc(ctx.expr(macsp, call));
let block = ctx.block_all(macsp, ctx.arena.alloc_from_iter(let_statements), Some(call));
+3 -3
View File
@@ -125,9 +125,9 @@ fn insert_nested(&mut self, item: LocalDefId) {
}
impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
/// Because we want to track parent items and so forth, enable
/// deep walking so that we walk nested items in the context of
/// their outer items.
// Because we want to track parent items and so forth, enable
// deep walking so that we walk nested items in the context of
// their outer items.
fn visit_nested_item(&mut self, item: ItemId) {
debug!("visit_nested_item: {:?}", item);
+6 -1
View File
@@ -183,7 +183,12 @@ fn new(tcx: TyCtxt<'hir>, resolver: &'a mut ResolverAstLowering) -> Self {
impl_trait_defs: Vec::new(),
impl_trait_bounds: Vec::new(),
allow_contracts: [sym::contracts_internals].into(),
allow_try_trait: [sym::try_trait_v2, sym::yeet_desugar_details].into(),
allow_try_trait: [
sym::try_trait_v2,
sym::try_trait_v2_residual,
sym::yeet_desugar_details,
]
.into(),
allow_pattern_type: [sym::pattern_types, sym::pattern_type_range_trait].into(),
allow_gen_future: if tcx.features().async_fn_track_caller() {
[sym::gen_future, sym::closure_track_caller].into()
+2 -2
View File
@@ -124,8 +124,8 @@ fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'hir> {
PatKind::Deref(inner) => {
break hir::PatKind::Deref(self.lower_pat(inner));
}
PatKind::Ref(inner, mutbl) => {
break hir::PatKind::Ref(self.lower_pat(inner), *mutbl);
PatKind::Ref(inner, pinned, mutbl) => {
break hir::PatKind::Ref(self.lower_pat(inner), *pinned, *mutbl);
}
PatKind::Range(e1, e2, Spanned { node: end, .. }) => {
break hir::PatKind::Range(
+4
View File
@@ -68,6 +68,10 @@ ast_passes_c_variadic_bad_extern = `...` is not supported for `extern "{$abi}"`
.label = `extern "{$abi}"` because of this
.help = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
ast_passes_c_variadic_bad_naked_extern = `...` is not supported for `extern "{$abi}"` naked functions
.label = `extern "{$abi}"` because of this
.help = C-variadic function must have a compatible calling convention
ast_passes_c_variadic_must_be_unsafe =
functions with a C variable argument list must be unsafe
.suggestion = add the `unsafe` keyword to this definition
+86 -29
View File
@@ -21,7 +21,7 @@
use std::str::FromStr;
use itertools::{Either, Itertools};
use rustc_abi::{CanonAbi, ExternAbi, InterruptKind};
use rustc_abi::{CVariadicStatus, CanonAbi, ExternAbi, InterruptKind};
use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor, walk_list};
use rustc_ast::*;
use rustc_ast_pretty::pprust::{self, State};
@@ -35,6 +35,7 @@
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, MISSING_UNSAFE_ON_EXTERN,
PATTERNS_IN_FNS_WITHOUT_BODY,
};
use rustc_session::parse::feature_err;
use rustc_span::{Ident, Span, kw, sym};
use rustc_target::spec::{AbiMap, AbiMapping};
use thin_vec::thin_vec;
@@ -661,7 +662,7 @@ fn check_foreign_item_ascii_only(&self, ident: Ident) {
/// C-variadics must be:
/// - Non-const
/// - Either foreign, or free and `unsafe extern "C"` semantically
fn check_c_variadic_type(&self, fk: FnKind<'a>) {
fn check_c_variadic_type(&self, fk: FnKind<'a>, attrs: &'a AttrVec) {
// `...` is already rejected when it is not the final parameter.
let variadic_param = match fk.decl().inputs.last() {
Some(param) if matches!(param.ty.kind, TyKind::CVarArgs) => param,
@@ -693,36 +694,92 @@ fn check_c_variadic_type(&self, fk: FnKind<'a>) {
match fn_ctxt {
FnCtxt::Foreign => return,
FnCtxt::Free | FnCtxt::Assoc(_) => match sig.header.ext {
Extern::Implicit(_) => {
if !matches!(sig.header.safety, Safety::Unsafe(_)) {
self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
span: variadic_param.span,
unsafe_span: sig.safety_span(),
});
FnCtxt::Free | FnCtxt::Assoc(_) => {
match sig.header.ext {
Extern::Implicit(_) => {
if !matches!(sig.header.safety, Safety::Unsafe(_)) {
self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
span: variadic_param.span,
unsafe_span: sig.safety_span(),
});
}
}
Extern::Explicit(StrLit { symbol_unescaped, .. }, _) => {
// Just bail if the ABI is not even recognized.
let Ok(abi) = ExternAbi::from_str(symbol_unescaped.as_str()) else {
return;
};
self.check_c_variadic_abi(abi, attrs, variadic_param.span, sig);
if !matches!(sig.header.safety, Safety::Unsafe(_)) {
self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
span: variadic_param.span,
unsafe_span: sig.safety_span(),
});
}
}
Extern::None => {
let err = errors::CVariadicNoExtern { span: variadic_param.span };
self.dcx().emit_err(err);
}
}
Extern::Explicit(StrLit { symbol_unescaped, .. }, _) => {
if !matches!(symbol_unescaped, sym::C | sym::C_dash_unwind) {
self.dcx().emit_err(errors::CVariadicBadExtern {
span: variadic_param.span,
abi: symbol_unescaped,
extern_span: sig.extern_span(),
});
}
}
}
fn check_c_variadic_abi(
&self,
abi: ExternAbi,
attrs: &'a AttrVec,
dotdotdot_span: Span,
sig: &FnSig,
) {
// For naked functions we accept any ABI that is accepted on c-variadic
// foreign functions, if the c_variadic_naked_functions feature is enabled.
if attr::contains_name(attrs, sym::naked) {
match abi.supports_c_variadic() {
CVariadicStatus::Stable if let ExternAbi::C { .. } = abi => {
// With `c_variadic` naked c-variadic `extern "C"` functions are allowed.
}
CVariadicStatus::Stable => {
// For e.g. aapcs or sysv64 `c_variadic_naked_functions` must also be enabled.
if !self.features.enabled(sym::c_variadic_naked_functions) {
let msg = format!("Naked c-variadic `extern {abi}` functions are unstable");
feature_err(&self.sess, sym::c_variadic_naked_functions, sig.span, msg)
.emit();
}
}
CVariadicStatus::Unstable { feature } => {
// Some ABIs need additional features.
if !self.features.enabled(sym::c_variadic_naked_functions) {
let msg = format!("Naked c-variadic `extern {abi}` functions are unstable");
feature_err(&self.sess, sym::c_variadic_naked_functions, sig.span, msg)
.emit();
}
if !matches!(sig.header.safety, Safety::Unsafe(_)) {
self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
span: variadic_param.span,
unsafe_span: sig.safety_span(),
});
if !self.features.enabled(feature) {
let msg = format!(
"C-variadic functions with the {abi} calling convention are unstable"
);
feature_err(&self.sess, feature, sig.span, msg).emit();
}
}
Extern::None => {
let err = errors::CVariadicNoExtern { span: variadic_param.span };
self.dcx().emit_err(err);
CVariadicStatus::NotSupported => {
// Some ABIs, e.g. `extern "Rust"`, never support c-variadic functions.
self.dcx().emit_err(errors::CVariadicBadNakedExtern {
span: dotdotdot_span,
abi: abi.as_str(),
extern_span: sig.extern_span(),
});
}
},
}
} else if !matches!(abi, ExternAbi::C { .. }) {
self.dcx().emit_err(errors::CVariadicBadExtern {
span: dotdotdot_span,
abi: abi.as_str(),
extern_span: sig.extern_span(),
});
}
}
@@ -1106,7 +1163,7 @@ fn visit_item(&mut self, item: &'a Item) {
}
let kind = FnKind::Fn(FnCtxt::Free, &item.vis, &*func);
self.visit_fn(kind, item.span, item.id);
self.visit_fn(kind, &item.attrs, item.span, item.id);
}
ItemKind::ForeignMod(ForeignMod { extern_span, abi, safety, .. }) => {
let old_item = mem::replace(&mut self.extern_mod_span, Some(item.span));
@@ -1473,7 +1530,7 @@ fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) {
visit::walk_param_bound(self, bound)
}
fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
fn visit_fn(&mut self, fk: FnKind<'a>, attrs: &AttrVec, span: Span, id: NodeId) {
// Only associated `fn`s can have `self` parameters.
let self_semantic = match fk.ctxt() {
Some(FnCtxt::Assoc(_)) => SelfSemantic::Yes,
@@ -1492,7 +1549,7 @@ fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
self.check_extern_fn_signature(abi, ctxt, &fun.ident, &fun.sig);
}
self.check_c_variadic_type(fk);
self.check_c_variadic_type(fk, attrs);
// Functions cannot both be `const async` or `const gen`
if let Some(&FnHeader {
@@ -1643,7 +1700,7 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
{
self.visit_attrs_vis_ident(&item.attrs, &item.vis, &func.ident);
let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), &item.vis, &*func);
self.visit_fn(kind, item.span, item.id);
self.visit_fn(kind, &item.attrs, item.span, item.id);
}
AssocItemKind::Type(_) => {
let disallowed = (!parent_is_const).then(|| match self.outer_trait_or_trait_impl {
+12 -1
View File
@@ -347,7 +347,18 @@ pub(crate) struct CVariadicMustBeUnsafe {
pub(crate) struct CVariadicBadExtern {
#[primary_span]
pub span: Span,
pub abi: Symbol,
pub abi: &'static str,
#[label]
pub extern_span: Span,
}
#[derive(Diagnostic)]
#[diag(ast_passes_c_variadic_bad_naked_extern)]
#[help]
pub(crate) struct CVariadicBadNakedExtern {
#[primary_span]
pub span: Span,
pub abi: &'static str,
#[label]
pub extern_span: Span,
}
@@ -1,6 +1,5 @@
use rustc_ast as ast;
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
use rustc_ast::{NodeId, PatKind, attr, token};
use rustc_ast::{self as ast, AttrVec, NodeId, PatKind, attr, token};
use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, Features};
use rustc_session::Session;
use rustc_session::parse::{feature_err, feature_warn};
@@ -392,7 +391,7 @@ fn visit_poly_trait_ref(&mut self, t: &'a ast::PolyTraitRef) {
visit::walk_poly_trait_ref(self, t);
}
fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
fn visit_fn(&mut self, fn_kind: FnKind<'a>, _: &AttrVec, span: Span, _: NodeId) {
if let Some(_header) = fn_kind.header() {
// Stability of const fn methods are covered in `visit_assoc_item` below.
}
@@ -1807,8 +1807,14 @@ fn print_pat(&mut self, pat: &ast::Pat) {
self.print_pat(inner);
self.pclose();
}
PatKind::Ref(inner, mutbl) => {
PatKind::Ref(inner, pinned, mutbl) => {
self.word("&");
if pinned.is_pinned() {
self.word("pin ");
if mutbl.is_not() {
self.word("const ");
}
}
if mutbl.is_mut() {
self.word("mut ");
}
@@ -0,0 +1,89 @@
use rustc_ast::token::Token;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{AttrStyle, NodeId, token};
use rustc_feature::{AttributeTemplate, Features};
use rustc_hir::AttrPath;
use rustc_hir::attrs::CfgEntry;
use rustc_parse::exp;
use rustc_parse::parser::Parser;
use rustc_session::Session;
use rustc_span::{ErrorGuaranteed, Ident, Span};
use crate::parser::MetaItemOrLitParser;
use crate::{AttributeParser, ParsedDescription, ShouldEmit, parse_cfg_entry};
pub enum CfgSelectPredicate {
Cfg(CfgEntry),
Wildcard(Token),
}
#[derive(Default)]
pub struct CfgSelectBranches {
/// All the conditional branches.
pub reachable: Vec<(CfgEntry, TokenStream, Span)>,
/// The first wildcard `_ => { ... }` branch.
pub wildcard: Option<(Token, TokenStream, Span)>,
/// All branches after the first wildcard, including further wildcards.
/// These branches are kept for formatting.
pub unreachable: Vec<(CfgSelectPredicate, TokenStream, Span)>,
}
pub fn parse_cfg_select(
p: &mut Parser<'_>,
sess: &Session,
features: Option<&Features>,
lint_node_id: NodeId,
) -> Result<CfgSelectBranches, ErrorGuaranteed> {
let mut branches = CfgSelectBranches::default();
while p.token != token::Eof {
if p.eat_keyword(exp!(Underscore)) {
let underscore = p.prev_token;
p.expect(exp!(FatArrow)).map_err(|e| e.emit())?;
let tts = p.parse_delimited_token_tree().map_err(|e| e.emit())?;
let span = underscore.span.to(p.token.span);
match branches.wildcard {
None => branches.wildcard = Some((underscore, tts, span)),
Some(_) => {
branches.unreachable.push((CfgSelectPredicate::Wildcard(underscore), tts, span))
}
}
} else {
let meta = MetaItemOrLitParser::parse_single(p, ShouldEmit::ErrorsAndLints)
.map_err(|diag| diag.emit())?;
let cfg_span = meta.span();
let cfg = AttributeParser::parse_single_args(
sess,
cfg_span,
cfg_span,
AttrStyle::Inner,
AttrPath {
segments: vec![Ident::from_str("cfg_select")].into_boxed_slice(),
span: cfg_span,
},
ParsedDescription::Macro,
cfg_span,
lint_node_id,
features,
ShouldEmit::ErrorsAndLints,
&meta,
parse_cfg_entry,
&AttributeTemplate::default(),
)?;
p.expect(exp!(FatArrow)).map_err(|e| e.emit())?;
let tts = p.parse_delimited_token_tree().map_err(|e| e.emit())?;
let span = cfg_span.to(p.token.span);
match branches.wildcard {
None => branches.reachable.push((cfg, tts, span)),
Some(_) => branches.unreachable.push((CfgSelectPredicate::Cfg(cfg), tts, span)),
}
}
}
Ok(branches)
}
@@ -33,6 +33,7 @@
pub(crate) mod body;
pub(crate) mod cfg;
pub(crate) mod cfg_old;
pub(crate) mod cfg_select;
pub(crate) mod codegen_attrs;
pub(crate) mod confusables;
pub(crate) mod crate_level;
+1
View File
@@ -106,6 +106,7 @@
CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg, parse_cfg_attr, parse_cfg_entry,
};
pub use attributes::cfg_old::*;
pub use attributes::cfg_select::*;
pub use attributes::util::{is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version};
pub use context::{Early, Late, OmitDoc, ShouldEmit};
pub use interface::AttributeParser;
@@ -209,7 +209,7 @@ pub fn check_attribute_safety(
// - Normal builtin attribute
// - Writing `#[unsafe(..)]` is not permitted on normal builtin attributes
(Some(AttributeSafety::Normal), Safety::Unsafe(unsafe_span)) => {
(None | Some(AttributeSafety::Normal), Safety::Unsafe(unsafe_span)) => {
psess.dcx().emit_err(errors::InvalidAttrUnsafe {
span: unsafe_span,
name: attr_item.path.clone(),
@@ -218,15 +218,10 @@ pub fn check_attribute_safety(
// - Normal builtin attribute
// - No explicit `#[unsafe(..)]` written.
(Some(AttributeSafety::Normal), Safety::Default) => {
(None | Some(AttributeSafety::Normal), Safety::Default) => {
// OK
}
// - Non-builtin attribute
(None, Safety::Unsafe(_) | Safety::Default) => {
// OK (not checked here)
}
(
Some(AttributeSafety::Unsafe { .. } | AttributeSafety::Normal) | None,
Safety::Safe(..),
@@ -3087,6 +3087,39 @@ fn report_local_value_does_not_live_long_enough(
});
explanation.add_explanation_to_diagnostic(&self, &mut err, "", Some(borrow_span), None);
// Detect buffer reuse pattern
if let BorrowExplanation::UsedLater(_dropped_local, _, _, _) = explanation {
// Check all locals at the borrow location to find Vec<&T> types
for (local, local_decl) in self.body.local_decls.iter_enumerated() {
if let ty::Adt(adt_def, args) = local_decl.ty.kind()
&& self.infcx.tcx.is_diagnostic_item(sym::Vec, adt_def.did())
&& args.len() > 0
{
let vec_inner_ty = args.type_at(0);
// Check if Vec contains references
if vec_inner_ty.is_ref() {
let local_place = local.into();
if let Some(local_name) = self.describe_place(local_place) {
err.span_label(
local_decl.source_info.span,
format!("variable `{local_name}` declared here"),
);
err.note(
format!(
"`{local_name}` is a collection that stores borrowed references, \
but {name} does not live long enough to be stored in it"
)
);
err.help(
"buffer reuse with borrowed references requires unsafe code or restructuring"
);
break;
}
}
}
}
}
}
err
@@ -867,11 +867,12 @@ fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
for (binding_span, opt_ref_pat) in finder.ref_pat_for_binding {
if let Some(ref_pat) = opt_ref_pat
&& !finder.cannot_remove.contains(&ref_pat.hir_id)
&& let hir::PatKind::Ref(subpat, mutbl) = ref_pat.kind
&& let hir::PatKind::Ref(subpat, pinned, mutbl) = ref_pat.kind
&& let Some(ref_span) = ref_pat.span.trim_end(subpat.span)
{
let pinned_str = if pinned.is_pinned() { "pinned " } else { "" };
let mutable_str = if mutbl.is_mut() { "mutable " } else { "" };
let msg = format!("consider removing the {mutable_str}borrow");
let msg = format!("consider removing the {pinned_str}{mutable_str}borrow");
suggestions.push((ref_span, msg, "".to_string()));
} else {
let msg = "consider borrowing the pattern binding".to_string();
@@ -213,7 +213,7 @@ pub(crate) fn report_mutability_error(
AccessKind::Mutate => {
err = self.cannot_assign(span, &(item_msg + &reason));
act = "assign";
acted_on = "written";
acted_on = "written to";
span
}
AccessKind::MutableBorrow => {
@@ -518,8 +518,8 @@ pub(crate) fn report_mutability_error(
err.span_label(
span,
format!(
"`{name}` is a `{pointer_sigil}` {pointer_desc}, \
so the data it refers to cannot be {acted_on}",
"`{name}` is a `{pointer_sigil}` {pointer_desc}, so it cannot be \
{acted_on}",
),
);
@@ -542,7 +542,7 @@ pub(crate) fn report_mutability_error(
self.expected_fn_found_fn_mut_call(&mut err, span, act);
}
PlaceRef { local: _, projection: [.., ProjectionElem::Deref] } => {
PlaceRef { local, projection: [.., ProjectionElem::Deref] } => {
err.span_label(span, format!("cannot {act}"));
match opt_source {
@@ -559,11 +559,36 @@ pub(crate) fn report_mutability_error(
));
self.suggest_map_index_mut_alternatives(ty, &mut err, span);
}
_ => (),
_ => {
let local = &self.body.local_decls[local];
match local.local_info() {
LocalInfo::StaticRef { def_id, .. } => {
let span = self.infcx.tcx.def_span(def_id);
err.span_label(span, format!("this `static` cannot be {acted_on}"));
}
LocalInfo::ConstRef { def_id } => {
let span = self.infcx.tcx.def_span(def_id);
err.span_label(span, format!("this `const` cannot be {acted_on}"));
}
LocalInfo::BlockTailTemp(_) | LocalInfo::Boring
if !local.source_info.span.overlaps(span) =>
{
err.span_label(
local.source_info.span,
format!("this cannot be {acted_on}"),
);
}
_ => {}
}
}
}
}
_ => {
PlaceRef { local, .. } => {
let local = &self.body.local_decls[local];
if !local.source_info.span.overlaps(span) {
err.span_label(local.source_info.span, format!("this cannot be {acted_on}"));
}
err.span_label(span, format!("cannot {act}"));
}
}
@@ -772,11 +797,11 @@ fn construct_mut_suggestion_for_local_binding_patterns(
&& let Some(hir_id) = (BindingFinder { span: pat_span }).visit_body(&body).break_value()
&& let node = self.infcx.tcx.hir_node(hir_id)
&& let hir::Node::LetStmt(hir::LetStmt {
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
pat: hir::Pat { kind: hir::PatKind::Ref(_, _, _), .. },
..
})
| hir::Node::Param(Param {
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
pat: hir::Pat { kind: hir::PatKind::Ref(_, _, _), .. },
..
}) = node
{
@@ -1494,7 +1519,7 @@ fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) -> Self::Result {
}
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) -> Self::Result {
if let hir::Pat { kind: hir::PatKind::Ref(_, _), span, .. } = param.pat
if let hir::Pat { kind: hir::PatKind::Ref(_, _, _), span, .. } = param.pat
&& *span == self.span
{
ControlFlow::Break(param.hir_id)
@@ -690,6 +690,17 @@ fn report_escaping_data_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> Diag<
);
diag.span_label(*span, format!("`{fr_name}` escapes the {escapes_from} body here"));
} else {
diag.span_label(
*span,
format!("a temporary borrow escapes the {escapes_from} body here"),
);
if let Some((Some(outlived_name), _)) = outlived_fr_name_and_span {
diag.help(format!(
"`{outlived_name}` is declared outside the {escapes_from}, \
so any data borrowed inside the {escapes_from} cannot be stored into it"
));
}
}
// Only show an extra note if we can find an 'error region' for both of the region
+41 -35
View File
@@ -1,7 +1,9 @@
use rustc_ast::tokenstream::TokenStream;
use rustc_attr_parsing as attr;
use rustc_attr_parsing::{
CfgSelectBranches, CfgSelectPredicate, EvalConfigResult, ShouldEmit, parse_cfg_select,
};
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
use rustc_parse::parser::cfg_select::{CfgSelectBranches, CfgSelectPredicate, parse_cfg_select};
use rustc_span::{Ident, Span, sym};
use crate::errors::{CfgSelectNoMatches, CfgSelectUnreachable};
@@ -9,11 +11,11 @@
/// 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(
&cfg,
if let EvalConfigResult::True = attr::eval_config_entry(
&ecx.sess,
&cfg,
ecx.current_expansion.lint_node_id,
Some(ecx.ecfg.features),
ShouldEmit::ErrorsAndLints,
) {
return Some((tt, arm_span));
}
@@ -27,37 +29,41 @@ pub(super) fn expand_cfg_select<'cx>(
sp: Span,
tts: TokenStream,
) -> MacroExpanderResult<'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 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);
ExpandResult::Ready(
match parse_cfg_select(
&mut ecx.new_parser_from_tts(tts),
ecx.sess,
Some(ecx.ecfg.features),
ecx.current_expansion.lint_node_id,
) {
Ok(branches) => {
if let Some((underscore, _, _)) = branches.wildcard {
// 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);
}
}
if let Some((tts, arm_span)) = select_arm(ecx, branches) {
return ExpandResult::from_tts(
ecx,
tts,
sp,
arm_span,
Ident::with_dummy_span(sym::cfg_select),
);
} else {
// Emit a compiler error when none of the predicates matched.
let guar = ecx.dcx().emit_err(CfgSelectNoMatches { span: sp });
DummyResult::any(sp, guar)
}
}
if let Some((tts, arm_span)) = select_arm(ecx, branches) {
return ExpandResult::from_tts(
ecx,
tts,
sp,
arm_span,
Ident::with_dummy_span(sym::cfg_select),
);
} else {
// Emit a compiler error when none of the predicates matched.
let guar = ecx.dcx().emit_err(CfgSelectNoMatches { span: sp });
DummyResult::any(sp, guar)
}
}
Err(err) => {
let guar = err.emit();
DummyResult::any(sp, guar)
}
})
Err(guar) => DummyResult::any(sp, guar),
},
)
}
@@ -1,4 +1,4 @@
use rustc_ast::MetaItem;
use rustc_ast::{MetaItem, Safety};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::Span;
@@ -24,6 +24,8 @@ pub(crate) fn expand_deriving_copy(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
document: true,
};
trait_def.expand(cx, mitem, item, push);
@@ -48,6 +50,8 @@ pub(crate) fn expand_deriving_const_param_ty(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
document: true,
};
trait_def.expand(cx, mitem, item, push);
@@ -1,7 +1,7 @@
use rustc_ast::{self as ast, Generics, ItemKind, MetaItem, VariantData};
use rustc_ast::{self as ast, Generics, ItemKind, MetaItem, Safety, VariantData};
use rustc_data_structures::fx::FxHashSet;
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::{Ident, Span, kw, sym};
use rustc_span::{DUMMY_SP, Ident, Span, kw, sym};
use thin_vec::{ThinVec, thin_vec};
use crate::deriving::generic::ty::*;
@@ -68,6 +68,29 @@ pub(crate) fn expand_deriving_clone(
_ => cx.dcx().span_bug(span, "`#[derive(Clone)]` on trait item or impl item"),
}
// If the clone method is just copying the value, also mark the type as
// `TrivialClone` to allow some library optimizations.
if is_simple {
let trivial_def = TraitDef {
span,
path: path_std!(clone::TrivialClone),
skip_path_as_bound: false,
needs_copy_as_bound_if_packed: true,
additional_bounds: bounds.clone(),
supports_unions: true,
methods: Vec::new(),
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Unsafe(DUMMY_SP),
// `TrivialClone` is not part of an API guarantee, so it shouldn't
// appear in rustdoc output.
document: false,
};
trivial_def.expand_ext(cx, mitem, item, push, true);
}
let trait_def = TraitDef {
span,
path: path_std!(clone::Clone),
@@ -88,6 +111,8 @@ pub(crate) fn expand_deriving_clone(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
document: true,
};
trait_def.expand_ext(cx, mitem, item, push, is_simple)
@@ -1,4 +1,4 @@
use rustc_ast::{self as ast, MetaItem};
use rustc_ast::{self as ast, MetaItem, Safety};
use rustc_data_structures::fx::FxHashSet;
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::{Span, sym};
@@ -44,6 +44,8 @@ pub(crate) fn expand_deriving_eq(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
document: true,
};
trait_def.expand_ext(cx, mitem, item, push, true)
}
@@ -1,4 +1,4 @@
use rustc_ast::MetaItem;
use rustc_ast::{MetaItem, Safety};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::{Ident, Span, sym};
use thin_vec::thin_vec;
@@ -35,6 +35,8 @@ pub(crate) fn expand_deriving_ord(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
document: true,
};
trait_def.expand(cx, mitem, item, push)
@@ -1,4 +1,4 @@
use rustc_ast::{BinOpKind, BorrowKind, Expr, ExprKind, MetaItem, Mutability};
use rustc_ast::{BinOpKind, BorrowKind, Expr, ExprKind, MetaItem, Mutability, Safety};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::{Span, sym};
use thin_vec::thin_vec;
@@ -30,6 +30,8 @@ pub(crate) fn expand_deriving_partial_eq(
associated_types: Vec::new(),
is_const: false,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
document: true,
};
structural_trait_def.expand(cx, mitem, item, push);
@@ -59,6 +61,8 @@ pub(crate) fn expand_deriving_partial_eq(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
document: true,
};
trait_def.expand(cx, mitem, item, push)
}
@@ -1,4 +1,4 @@
use rustc_ast::{ExprKind, ItemKind, MetaItem, PatKind};
use rustc_ast::{ExprKind, ItemKind, MetaItem, PatKind, Safety};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::{Ident, Span, sym};
use thin_vec::thin_vec;
@@ -65,6 +65,8 @@ pub(crate) fn expand_deriving_partial_ord(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
document: true,
};
trait_def.expand(cx, mitem, item, push)
}
@@ -1,4 +1,4 @@
use rustc_ast::{self as ast, EnumDef, MetaItem};
use rustc_ast::{self as ast, EnumDef, MetaItem, Safety};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_session::config::FmtDebug;
use rustc_span::{Ident, Span, Symbol, sym};
@@ -42,6 +42,8 @@ pub(crate) fn expand_deriving_debug(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
document: true,
};
trait_def.expand(cx, mitem, item, push)
}
@@ -1,8 +1,7 @@
use core::ops::ControlFlow;
use rustc_ast as ast;
use rustc_ast::visit::visit_opt;
use rustc_ast::{EnumDef, VariantData, attr};
use rustc_ast::{self as ast, EnumDef, Safety, VariantData, attr};
use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};
use smallvec::SmallVec;
@@ -52,6 +51,8 @@ pub(crate) fn expand_deriving_default(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
document: true,
};
trait_def.expand(cx, mitem, item, push)
}
@@ -1,5 +1,5 @@
use rustc_ast as ast;
use rustc_ast::{ItemKind, VariantData};
use rustc_ast::{ItemKind, Safety, VariantData};
use rustc_errors::MultiSpan;
use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
use rustc_span::{Ident, Span, kw, sym};
@@ -127,6 +127,8 @@ pub(crate) fn expand_deriving_from(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
document: true,
};
from_trait_def.expand(cx, mitem, annotatable, push);
@@ -225,6 +225,12 @@ pub(crate) struct TraitDef<'a> {
pub is_const: bool,
pub is_staged_api_crate: bool,
/// The safety of the `impl`.
pub safety: Safety,
/// Whether the added `impl` should appear in rustdoc output.
pub document: bool,
}
pub(crate) struct MethodDef<'a> {
@@ -826,13 +832,17 @@ fn create_derived_impl(
)
}
if !self.document {
attrs.push(cx.attr_nested_word(sym::doc, sym::hidden, self.span));
}
cx.item(
self.span,
attrs,
ast::ItemKind::Impl(ast::Impl {
generics: trait_generics,
of_trait: Some(Box::new(ast::TraitImplHeader {
safety: ast::Safety::Default,
safety: self.safety,
polarity: ast::ImplPolarity::Positive,
defaultness: ast::Defaultness::Final,
constness: if self.is_const {
@@ -1,4 +1,4 @@
use rustc_ast::{MetaItem, Mutability};
use rustc_ast::{MetaItem, Mutability, Safety};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::{Span, sym};
use thin_vec::thin_vec;
@@ -42,6 +42,8 @@ pub(crate) fn expand_deriving_hash(
associated_types: Vec::new(),
is_const,
is_staged_api_crate: cx.ecfg.features.staged_api(),
safety: Safety::Default,
document: true,
};
hash_trait_def.expand(cx, mitem, item, push);
@@ -916,8 +916,8 @@ pub(crate) fn codegen_call_with_unwind_action(
pub(crate) fn lib_call_arg_param(tcx: TyCtxt<'_>, ty: Type, is_signed: bool) -> AbiParam {
let param = AbiParam::new(ty);
if ty.is_int() && u64::from(ty.bits()) < tcx.data_layout.pointer_size().bits() {
match (&tcx.sess.target.arch, tcx.sess.target.vendor.as_ref()) {
(Arch::X86_64, _) | (Arch::AArch64, "apple") => match (ty, is_signed) {
match (&tcx.sess.target.arch, tcx.sess.target.is_like_darwin) {
(Arch::X86_64, _) | (Arch::AArch64, true) => match (ty, is_signed) {
(types::I8 | types::I16, true) => param.sext(),
(types::I8 | types::I16, false) => param.uext(),
_ => param,
@@ -5,7 +5,7 @@
pub(crate) fn f16_to_f32(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value {
let (value, arg_ty) =
if fx.tcx.sess.target.vendor == "apple" && fx.tcx.sess.target.arch == Arch::X86_64 {
if fx.tcx.sess.target.is_like_darwin && fx.tcx.sess.target.arch == Arch::X86_64 {
(
fx.bcx.ins().bitcast(types::I16, MemFlags::new(), value),
lib_call_arg_param(fx.tcx, types::I16, false),
@@ -22,8 +22,7 @@ fn f16_to_f64(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value {
}
pub(crate) fn f32_to_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value {
let ret_ty = if fx.tcx.sess.target.vendor == "apple" && fx.tcx.sess.target.arch == Arch::X86_64
{
let ret_ty = if fx.tcx.sess.target.is_like_darwin && fx.tcx.sess.target.arch == Arch::X86_64 {
types::I16
} else {
types::F16
@@ -38,8 +37,7 @@ pub(crate) fn f32_to_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value
}
fn f64_to_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value {
let ret_ty = if fx.tcx.sess.target.vendor == "apple" && fx.tcx.sess.target.arch == Arch::X86_64
{
let ret_ty = if fx.tcx.sess.target.is_like_darwin && fx.tcx.sess.target.arch == Arch::X86_64 {
types::I16
} else {
types::F16
+8 -8
View File
@@ -49,7 +49,7 @@
use rustc_session::Session;
use rustc_session::config::OutputFilenames;
use rustc_span::{Symbol, sym};
use rustc_target::spec::Arch;
use rustc_target::spec::{Abi, Arch, Env, Os};
pub use crate::config::*;
use crate::prelude::*;
@@ -163,15 +163,15 @@ fn init(&self, sess: &Session) {
fn target_config(&self, sess: &Session) -> TargetConfig {
// FIXME return the actually used target features. this is necessary for #[cfg(target_feature)]
let target_features = match sess.target.arch {
Arch::X86_64 if sess.target.os != "none" => {
Arch::X86_64 if sess.target.os != Os::None => {
// x86_64 mandates SSE2 support and rustc requires the x87 feature to be enabled
vec![sym::fxsr, sym::sse, sym::sse2, Symbol::intern("x87")]
}
Arch::AArch64 => match &*sess.target.os {
"none" => vec![],
Arch::AArch64 => match &sess.target.os {
Os::None => vec![],
// On macOS the aes, sha2 and sha3 features are enabled by default and ring
// fails to compile on macOS when they are not present.
"macos" => vec![sym::neon, sym::aes, sym::sha2, sym::sha3],
Os::MacOs => vec![sym::neon, sym::aes, sym::sha2, sym::sha3],
// AArch64 mandates Neon support
_ => vec![sym::neon],
},
@@ -184,9 +184,9 @@ fn target_config(&self, sess: &Session) -> TargetConfig {
// targets due to GCC using a different ABI than LLVM. Therefore `f16` and `f128`
// won't be available when using a LLVM-built sysroot.
let has_reliable_f16_f128 = !(sess.target.arch == Arch::X86_64
&& sess.target.os == "windows"
&& sess.target.env == "gnu"
&& sess.target.abi != "llvm");
&& sess.target.os == Os::Windows
&& sess.target.env == Env::Gnu
&& sess.target.abi != Abi::Llvm);
TargetConfig {
target_features,
+19 -9
View File
@@ -62,7 +62,7 @@ jobs:
- name: Build
run: |
./y.sh prepare --only-libcore
EMBED_LTO_BITCODE=1 ./y.sh build --sysroot --release --release-sysroot
./y.sh build --sysroot --release --release-sysroot
./y.sh test --cargo-tests
./y.sh clean all
@@ -72,19 +72,14 @@ jobs:
git config --global user.name "User"
./y.sh prepare
- name: Add more failing tests because of undefined symbol errors (FIXME)
run: cat tests/failing-lto-tests.txt >> tests/failing-ui-tests.txt
- name: Run tests
run: |
# FIXME(antoyo): we cannot enable LTO for stdarch tests currently because of some failing LTO tests using proc-macros.
# 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 }}
CG_RUSTFLAGS="-Cembed-bitcode=yes" ./y.sh test --release --clean --release-sysroot --build-sysroot --keep-lto-tests ${{ matrix.commands }}
- name: Run y.sh cargo build
- name: LTO test
run: |
EMBED_LTO_BITCODE=1 CHANNEL="release" ./y.sh cargo build --release --manifest-path tests/hello-world/Cargo.toml
CHANNEL="release" ./y.sh cargo build --release --manifest-path tests/hello-world/Cargo.toml
call_found=$(objdump -dj .text tests/hello-world/target/release/hello_world | grep -c "call .*mylib.*my_func" ) ||:
if [ $call_found -gt 0 ]; then
echo "ERROR: call my_func found in asm"
@@ -92,6 +87,21 @@ jobs:
exit 1
fi
- name: Cross-language LTO test
run: |
pushd tests/cross_lang_lto
gcc -c -flto add.c -masm=intel -fPIC -O3
ar rcs libadd.a add.o
popd
CHANNEL="release" CG_RUSTFLAGS="-L native=. -Clinker-plugin-lto -Clinker=gcc" ./y.sh cargo build --release --manifest-path tests/cross_lang_lto/Cargo.toml
call_found=$(objdump -dj .text tests/cross_lang_lto/target/release/cross_lang_lto | grep -c "call .*my_add" ) ||:
if [ $call_found -gt 0 ]; then
echo "ERROR: call my_add found in asm"
echo "Test is done with cross-language LTO enabled, hence inlining should occur across object files"
exit 1
fi
# Summary job for the merge queue.
# ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
success_release:
+1 -1
View File
@@ -41,7 +41,7 @@ jobs:
# TODO: remove when we have binutils version 2.43 in the repo.
- name: Install more recent binutils
run: |
echo "deb http://archive.ubuntu.com/ubuntu oracular main universe" | sudo tee /etc/apt/sources.list.d/oracular-copies.list
echo "deb http://archive.ubuntu.com/ubuntu plucky main universe" | sudo tee /etc/apt/sources.list.d/plucky-copies.list
sudo apt-get update
sudo apt-get install binutils
+4 -4
View File
@@ -56,18 +56,18 @@ dependencies = [
[[package]]
name = "gccjit"
version = "2.9.0"
version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a0e310ef75f396cd11b2443b353d55376656ca92c13cba36f92b7aff346ac1a"
checksum = "60362e038e71e4bdc1a5b23fb45e1aba587b5947fe0db58f4871d95608f89eca"
dependencies = [
"gccjit_sys",
]
[[package]]
name = "gccjit_sys"
version = "0.8.2"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95ed7572b30cd32430294dde6fb70822d58e67c6846a548647e8739776a0125b"
checksum = "ddd542c8414e122217551c6af6b7d33acf51a227aee85276f218c087525e01bb"
dependencies = [
"libc",
]
+1 -1
View File
@@ -24,7 +24,7 @@ default = ["master"]
[dependencies]
object = { version = "0.37.0", default-features = false, features = ["std", "read"] }
tempfile = "3.20"
gccjit = "2.8"
gccjit = "2.10"
#gccjit = { git = "https://github.com/rust-lang/gccjit.rs" }
# Local copy.
+7 -11
View File
@@ -70,11 +70,17 @@ $ ../gcc/configure \
$ make -j4 # You can replace `4` with another number depending on how many cores you have.
```
If you want to run libgccjit tests, you will need to also enable the C++ language in the `configure`:
If you want to run libgccjit tests, you will need to
* Enable the C++ language in the `configure` step:
```bash
--enable-languages=jit,c++
```
* Install [dejagnu](https://www.gnu.org/software/dejagnu/#downloading) to run the tests:
```bash
$ sudo apt install dejagnu
```
Then to run libgccjit tests:
@@ -135,16 +141,6 @@ $ CHANNEL="release" $CG_GCCJIT_DIR/y.sh cargo run
If you compiled cg_gccjit in debug mode (aka you didn't pass `--release` to `./y.sh test`) you should use `CHANNEL="debug"` instead or omit `CHANNEL="release"` completely.
### LTO
To use LTO, you need to set the variable `EMBED_LTO_BITCODE=1` in addition to setting `lto = "fat"` in the `Cargo.toml`.
Failing to set `EMBED_LTO_BITCODE` will give you the following error:
```
error: failed to copy bitcode to object file: No such file or directory (os error 2)
```
### Rustc
If you want to run `rustc` directly, you can do so with:
@@ -149,6 +149,9 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
// Copy files to sysroot
let sysroot_path = start_dir.join(format!("sysroot/lib/rustlib/{}/lib/", config.target_triple));
// To avoid errors like "multiple candidates for `rmeta` dependency `core` found", we clean the
// sysroot directory before copying the sysroot build artifacts.
let _ = fs::remove_dir_all(&sysroot_path);
create_dir(&sysroot_path)?;
let mut copier = |dir_to_copy: &Path| {
// FIXME: should not use shell command!
@@ -69,8 +69,13 @@ fn clean_all() -> Result<(), String> {
}
fn clean_ui_tests() -> Result<(), String> {
let path = Path::new(crate::BUILD_DIR).join("rust/build/x86_64-unknown-linux-gnu/test/ui/");
run_command(&[&"find", &path, &"-name", &"stamp", &"-delete"], None)?;
let directories = ["run-make", "run-make-cargo", "ui"];
for directory in directories {
let path = Path::new(crate::BUILD_DIR)
.join("rust/build/x86_64-unknown-linux-gnu/test/")
.join(directory);
run_command(&[&"find", &path, &"-name", &"stamp", &"-delete"], None)?;
}
Ok(())
}
@@ -1,5 +1,7 @@
use std::ffi::OsStr;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Output;
use crate::rustc_info::get_rustc_path;
use crate::utils::{
@@ -7,6 +9,41 @@
run_command_with_output, walk_dir,
};
// This is needed on systems where nothing is configured.
// git really needs something here, or it will fail.
// Even using --author is not enough.
const GIT_CMD: [&dyn AsRef<OsStr>; 9] = [
&"git",
&"-c",
&"user.name=None",
&"-c",
&"user.email=none@example.com",
&"-c",
&"core.autocrlf=false",
&"-c",
&"commit.gpgSign=false",
];
fn run_git_command(
command: &dyn AsRef<OsStr>,
input: &[&dyn AsRef<OsStr>],
cwd: Option<&Path>,
) -> Result<Output, String> {
let git_cmd =
&GIT_CMD.into_iter().chain([command]).chain(input.iter().cloned()).collect::<Vec<_>>()[..];
run_command(git_cmd, cwd)
}
fn run_git_command_with_output(
command: &dyn AsRef<OsStr>,
input: &[&dyn AsRef<OsStr>],
cwd: Option<&Path>,
) -> Result<(), String> {
let git_cmd =
&GIT_CMD.into_iter().chain([command]).chain(input.iter().cloned()).collect::<Vec<_>>()[..];
run_command_with_output(git_cmd, cwd)
}
fn prepare_libcore(
sysroot_path: &Path,
libgccjit12_patches: bool,
@@ -55,19 +92,12 @@ fn prepare_libcore(
run_command(&[&"cp", &"-r", &rustlib_dir.join("library"), &sysroot_dir], None)?;
println!("[GIT] init (cwd): `{}`", sysroot_dir.display());
run_command(&[&"git", &"init"], Some(&sysroot_dir))?;
run_git_command(&"init", &[], Some(&sysroot_dir))?;
println!("[GIT] add (cwd): `{}`", sysroot_dir.display());
run_command(&[&"git", &"add", &"."], Some(&sysroot_dir))?;
run_git_command(&"add", &[&"."], Some(&sysroot_dir))?;
println!("[GIT] commit (cwd): `{}`", sysroot_dir.display());
// This is needed on systems where nothing is configured.
// git really needs something here, or it will fail.
// Even using --author is not enough.
run_command(&[&"git", &"config", &"user.email", &"none@example.com"], Some(&sysroot_dir))?;
run_command(&[&"git", &"config", &"user.name", &"None"], Some(&sysroot_dir))?;
run_command(&[&"git", &"config", &"core.autocrlf", &"false"], Some(&sysroot_dir))?;
run_command(&[&"git", &"config", &"commit.gpgSign", &"false"], Some(&sysroot_dir))?;
run_command(&[&"git", &"commit", &"-m", &"Initial commit", &"-q"], Some(&sysroot_dir))?;
run_git_command(&"commit", &[&"-m", &"Initial commit", &"-q"], Some(&sysroot_dir))?;
let mut patches = Vec::new();
walk_dir(
@@ -105,10 +135,11 @@ fn prepare_libcore(
for file_path in patches {
println!("[GIT] apply `{}`", file_path.display());
let path = Path::new("../../..").join(file_path);
run_command_with_output(&[&"git", &"apply", &path], Some(&sysroot_dir))?;
run_command_with_output(&[&"git", &"add", &"-A"], Some(&sysroot_dir))?;
run_command_with_output(
&[&"git", &"commit", &"--no-gpg-sign", &"-m", &format!("Patch {}", path.display())],
run_git_command_with_output(&"apply", &[&path], Some(&sysroot_dir))?;
run_git_command_with_output(&"add", &[&"-A"], Some(&sysroot_dir))?;
run_git_command_with_output(
&"commit",
&[&"-m", &format!("Patch {}", path.display())],
Some(&sysroot_dir),
)?;
}
@@ -124,10 +155,11 @@ fn prepare_rand() -> Result<(), String> {
let rand_dir = Path::new("build/rand");
println!("[GIT] apply `{file_path}`");
let path = Path::new("../..").join(file_path);
run_command_with_output(&[&"git", &"apply", &path], Some(rand_dir))?;
run_command_with_output(&[&"git", &"add", &"-A"], Some(rand_dir))?;
run_command_with_output(
&[&"git", &"commit", &"--no-gpg-sign", &"-m", &format!("Patch {}", path.display())],
run_git_command_with_output(&"apply", &[&path], Some(rand_dir))?;
run_git_command_with_output(&"add", &[&"-A"], Some(rand_dir))?;
run_git_command_with_output(
&"commit",
&[&"-m", &format!("Patch {}", path.display())],
Some(rand_dir),
)?;
@@ -154,8 +186,8 @@ fn clone_and_setup<F>(repo_url: &str, checkout_commit: &str, extra: Option<F>) -
println!("`{}` has already been cloned", clone_result.repo_name);
}
let repo_path = Path::new(crate::BUILD_DIR).join(&clone_result.repo_name);
run_command(&[&"git", &"checkout", &"--", &"."], Some(&repo_path))?;
run_command(&[&"git", &"checkout", &checkout_commit], Some(&repo_path))?;
run_git_command(&"checkout", &[&"--", &"."], Some(&repo_path))?;
run_git_command(&"checkout", &[&checkout_commit], Some(&repo_path))?;
if let Some(extra) = extra {
extra(&repo_path)?;
}
@@ -910,6 +910,7 @@ fn test_rustc_inner<F>(
prepare_files_callback: F,
run_error_pattern_test: bool,
test_type: &str,
run_ignored_tests: bool,
) -> Result<(), String>
where
F: Fn(&Path) -> Result<bool, String>,
@@ -944,17 +945,7 @@ fn test_rustc_inner<F>(
rust_path.join("tests/ui"),
&mut |dir| {
let dir_name = dir.file_name().and_then(|name| name.to_str()).unwrap_or("");
if [
"abi",
"extern",
"unsized-locals",
"proc-macro",
"threads-sendsync",
"borrowck",
"test-attrs",
]
.contains(&dir_name)
{
if ["abi", "extern", "proc-macro", "threads-sendsync"].contains(&dir_name) {
remove_dir_all(dir).map_err(|error| {
format!("Failed to remove folder `{}`: {:?}", dir.display(), error)
})?;
@@ -1061,30 +1052,34 @@ fn file_handling(keep_lto_tests: bool) -> impl Fn(&Path) -> Result<(), String> {
env.get_mut("RUSTFLAGS").unwrap().clear();
run_command_with_output_and_env(
&[
&"./x.py",
&"test",
&"--run",
&"always",
&"--stage",
&"0",
&"--set",
&"build.compiletest-allow-stage0=true",
&format!("tests/{test_type}"),
&"--compiletest-rustc-args",
&rustc_args,
],
Some(&rust_path),
Some(&env),
)?;
let test_dir = format!("tests/{test_type}");
let mut command: Vec<&dyn AsRef<OsStr>> = vec![
&"./x.py",
&"test",
&"--run",
&"always",
&"--stage",
&"0",
&"--set",
&"build.compiletest-allow-stage0=true",
&test_dir,
&"--compiletest-rustc-args",
&rustc_args,
];
if run_ignored_tests {
command.push(&"--");
command.push(&"--ignored");
}
run_command_with_output_and_env(&command, Some(&rust_path), Some(&env))?;
Ok(())
}
fn test_rustc(env: &Env, args: &TestArg) -> Result<(), String> {
test_rustc_inner(env, args, |_| Ok(false), false, "run-make")?;
test_rustc_inner(env, args, |_| Ok(false), false, "run-make-cargo")?;
test_rustc_inner(env, args, |_| Ok(false), false, "ui")
test_rustc_inner(env, args, |_| Ok(false), false, "run-make", false)?;
test_rustc_inner(env, args, |_| Ok(false), false, "run-make-cargo", false)?;
test_rustc_inner(env, args, |_| Ok(false), false, "ui", false)
}
fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> {
@@ -1094,6 +1089,7 @@ fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> {
retain_files_callback("tests/failing-run-make-tests.txt", "run-make"),
false,
"run-make",
true,
);
let run_make_cargo_result = test_rustc_inner(
@@ -1102,6 +1098,7 @@ fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> {
retain_files_callback("tests/failing-run-make-tests.txt", "run-make-cargo"),
false,
"run-make",
true,
);
let ui_result = test_rustc_inner(
@@ -1110,6 +1107,7 @@ fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> {
retain_files_callback("tests/failing-ui-tests.txt", "ui"),
false,
"ui",
true,
);
run_make_result.and(run_make_cargo_result).and(ui_result)
@@ -1122,6 +1120,7 @@ fn test_successful_rustc(env: &Env, args: &TestArg) -> Result<(), String> {
remove_files_callback("tests/failing-ui-tests.txt", "ui"),
false,
"ui",
false,
)?;
test_rustc_inner(
env,
@@ -1129,6 +1128,7 @@ fn test_successful_rustc(env: &Env, args: &TestArg) -> Result<(), String> {
remove_files_callback("tests/failing-run-make-tests.txt", "run-make"),
false,
"run-make",
false,
)?;
test_rustc_inner(
env,
@@ -1136,6 +1136,7 @@ fn test_successful_rustc(env: &Env, args: &TestArg) -> Result<(), String> {
remove_files_callback("tests/failing-run-make-tests.txt", "run-make-cargo"),
false,
"run-make-cargo",
false,
)
}
@@ -1146,6 +1147,7 @@ fn test_failing_ui_pattern_tests(env: &Env, args: &TestArg) -> Result<(), String
remove_files_callback("tests/failing-ice-tests.txt", "ui"),
true,
"ui",
false,
)
}
@@ -112,8 +112,7 @@ pub fn run_command_with_output(
cwd: Option<&Path>,
) -> Result<(), String> {
let exit_status = exec_command(input, cwd, None)?;
check_exit_status(input, cwd, exit_status, None, true)?;
Ok(())
check_exit_status(input, cwd, exit_status, None, true)
}
pub fn run_command_with_output_and_env(
@@ -122,8 +121,7 @@ pub fn run_command_with_output_and_env(
env: Option<&HashMap<String, String>>,
) -> Result<(), String> {
let exit_status = exec_command(input, cwd, env)?;
check_exit_status(input, cwd, exit_status, None, true)?;
Ok(())
check_exit_status(input, cwd, exit_status, None, true)
}
#[cfg(not(unix))]
@@ -133,8 +131,7 @@ pub fn run_command_with_output_and_env_no_err(
env: Option<&HashMap<String, String>>,
) -> Result<(), String> {
let exit_status = exec_command(input, cwd, env)?;
check_exit_status(input, cwd, exit_status, None, false)?;
Ok(())
check_exit_status(input, cwd, exit_status, None, false)
}
pub fn cargo_install(to_install: &str) -> Result<(), String> {
@@ -603,7 +603,7 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> fo
impl<T> Box<T> {
pub fn new(val: T) -> Box<T> {
unsafe {
let size = intrinsics::size_of::<T>();
let size = size_of::<T>();
let ptr = libc::malloc(size);
intrinsics::copy(&val as *const T as *const u8, ptr, size);
Box(Unique { pointer: NonNull(ptr as *const T), _marker: PhantomData }, Global)
@@ -657,11 +657,11 @@ pub mod intrinsics {
#[rustc_intrinsic]
pub fn abort() -> !;
#[rustc_intrinsic]
pub fn size_of<T>() -> usize;
pub const fn size_of<T>() -> usize;
#[rustc_intrinsic]
pub unsafe fn size_of_val<T: ?::Sized>(val: *const T) -> usize;
#[rustc_intrinsic]
pub fn align_of<T>() -> usize;
pub const fn align_of<T>() -> usize;
#[rustc_intrinsic]
pub unsafe fn align_of_val<T: ?::Sized>(val: *const T) -> usize;
#[rustc_intrinsic]
@@ -671,7 +671,7 @@ pub mod intrinsics {
#[rustc_intrinsic]
pub unsafe fn ctlz_nonzero<T>(x: T) -> u32;
#[rustc_intrinsic]
pub fn needs_drop<T: ?::Sized>() -> bool;
pub const fn needs_drop<T: ?::Sized>() -> bool;
#[rustc_intrinsic]
pub fn bitreverse<T>(x: T) -> T;
#[rustc_intrinsic]
@@ -699,6 +699,24 @@ pub mod libc {
}
}
pub const fn size_of<T>() -> usize {
<T as SizedTypeProperties>::SIZE
}
pub const fn align_of<T>() -> usize {
<T as SizedTypeProperties>::ALIGN
}
trait SizedTypeProperties: Sized {
#[lang = "mem_size_const"]
const SIZE: usize = intrinsics::size_of::<Self>();
#[lang = "mem_align_const"]
const ALIGN: usize = intrinsics::align_of::<Self>();
}
impl<T> SizedTypeProperties for T {}
#[lang = "index"]
pub trait Index<Idx: ?Sized> {
type Output: ?Sized;
@@ -90,8 +90,8 @@ fn start<T: Termination + 'static>(
) -> isize {
if argc == 3 {
unsafe { puts(*argv); }
unsafe { puts(*((argv as usize + intrinsics::size_of::<*const u8>()) as *const *const u8)); }
unsafe { puts(*((argv as usize + 2 * intrinsics::size_of::<*const u8>()) as *const *const u8)); }
unsafe { puts(*((argv as usize + size_of::<*const u8>()) as *const *const u8)); }
unsafe { puts(*((argv as usize + 2 * size_of::<*const u8>()) as *const *const u8)); }
}
main().report();
@@ -154,7 +154,7 @@ fn main() {
let slice = &[0, 1] as &[i32];
let slice_ptr = slice as *const [i32] as *const i32;
let align = intrinsics::align_of::<*const i32>();
let align = align_of::<*const i32>();
assert_eq!(slice_ptr as usize % align, 0);
//return;
@@ -195,11 +195,9 @@ fn main() {
assert_eq!(intrinsics::size_of_val(a) as u8, 8);
assert_eq!(intrinsics::size_of_val(&0u32) as u8, 4);
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_eq!(align_of::<u16>() as u8, 2);
assert_eq!(intrinsics::align_of_val(&a) as u8, align_of::<&str>() as u8);
/*
* 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]>() };
@@ -208,7 +206,6 @@ fn main() {
assert!(noisy_drop);
let noisy_unsized_drop = const { intrinsics::needs_drop::<NoisyDropUnsized>() };
assert!(noisy_unsized_drop);
*/
Unique {
pointer: 0 as *const &str,
+1 -1
View File
@@ -1 +1 @@
4e995bd73c4490edfe5080ec6014d63aa9abed5f
28b84db392ac0a572f1a2a2a1317aa5f2bc742cb
+1 -1
View File
@@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2025-08-25"
channel = "nightly-2025-11-04"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
+1 -1
View File
@@ -90,7 +90,7 @@ fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, '_>) -> Type<'gcc> {
64 => cx.type_f64(),
_ => bug!("unsupported float: {:?}", self),
},
RegKind::Vector => unimplemented!(), //cx.type_vector(cx.type_i8(), self.size.bytes()),
RegKind::Vector => cx.type_vector(cx.type_i8(), self.size.bytes()),
}
}
}
+8 -5
View File
@@ -21,6 +21,7 @@
use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::sync::atomic::Ordering;
use gccjit::{Context, OutputKind};
use object::read::archive::ArchiveFile;
@@ -39,7 +40,7 @@
use crate::back::write::save_temp_bitcode;
use crate::errors::LtoBitcodeFromRlib;
use crate::{GccCodegenBackend, GccContext, SyncContext, to_gcc_opt_level};
use crate::{GccCodegenBackend, GccContext, LTO_SUPPORTED, LtoMode, SyncContext, to_gcc_opt_level};
struct LtoData {
// TODO(antoyo): use symbols_below_threshold.
@@ -229,7 +230,7 @@ fn fat_lto(
info!("linking {:?}", name);
match bc_decoded {
SerializedModule::Local(ref module_buffer) => {
module.module_llvm.should_combine_object_files = true;
module.module_llvm.lto_mode = LtoMode::Fat;
module
.module_llvm
.context
@@ -534,7 +535,7 @@ pub fn optimize_thin_module(
// that LLVM Context and Module.
//let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
//let llmod_raw = parse_module(llcx, module_name, thin_module.data(), &dcx)? as *const _;
let mut should_combine_object_files = false;
let mut lto_mode = LtoMode::None;
let context = match thin_module.shared.thin_buffers.get(thin_module.idx) {
Some(thin_buffer) => Arc::clone(&thin_buffer.context),
None => {
@@ -545,7 +546,7 @@ pub fn optimize_thin_module(
SerializedModule::Local(ref module_buffer) => {
let path = module_buffer.0.to_str().expect("path");
context.add_driver_option(path);
should_combine_object_files = true;
lto_mode = LtoMode::Thin;
/*module.module_llvm.should_combine_object_files = true;
module
.module_llvm
@@ -560,11 +561,13 @@ pub fn optimize_thin_module(
Arc::new(SyncContext::new(context))
}
};
let lto_supported = LTO_SUPPORTED.load(Ordering::SeqCst);
let module = ModuleCodegen::new_regular(
thin_module.name().to_string(),
GccContext {
context,
should_combine_object_files,
lto_mode,
lto_supported,
// TODO(antoyo): use the correct relocation model here.
relocation_model: RelocModel::Pic,
temp_dir: None,
+34 -69
View File
@@ -11,7 +11,7 @@
use crate::base::add_pic_option;
use crate::errors::CopyBitcode;
use crate::{GccCodegenBackend, GccContext};
use crate::{GccCodegenBackend, GccContext, LtoMode};
pub(crate) fn codegen(
cgcx: &CodegenContext<GccCodegenBackend>,
@@ -25,12 +25,8 @@ pub(crate) fn codegen(
{
let context = &module.module_llvm.context;
let should_combine_object_files = module.module_llvm.should_combine_object_files;
// NOTE: Only generate object files with GIMPLE when this environment variable is set for
// now because this requires a particular setup (same gcc/lto1/lto-wrapper commit as libgccjit).
// TODO(antoyo): remove this environment variable.
let fat_lto = env::var("EMBED_LTO_BITCODE").as_deref() == Ok("1");
let lto_mode = module.module_llvm.lto_mode;
let lto_supported = module.module_llvm.lto_supported;
let bc_out = cgcx.output_filenames.temp_path_for_cgu(
OutputType::Bitcode,
@@ -44,80 +40,46 @@ pub(crate) fn codegen(
);
if config.bitcode_needed() {
if fat_lto {
let _timer = cgcx
.prof
.generic_activity_with_arg("GCC_module_codegen_make_bitcode", &*module.name);
// TODO(antoyo)
/*if let Some(bitcode_filename) = bc_out.file_name() {
cgcx.prof.artifact_size(
"llvm_bitcode",
bitcode_filename.to_string_lossy(),
data.len() as u64,
);
}*/
if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
let _timer = cgcx
.prof
.generic_activity_with_arg("GCC_module_codegen_make_bitcode", &*module.name);
// TODO(antoyo)
/*if let Some(bitcode_filename) = bc_out.file_name() {
cgcx.prof.artifact_size(
"llvm_bitcode",
bitcode_filename.to_string_lossy(),
data.len() as u64,
);
}*/
if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
let _timer = cgcx.prof.generic_activity_with_arg(
"GCC_module_codegen_emit_bitcode",
&*module.name,
);
.generic_activity_with_arg("GCC_module_codegen_emit_bitcode", &*module.name);
if lto_supported {
context.add_command_line_option("-flto=auto");
context.add_command_line_option("-flto-partition=one");
// TODO(antoyo): remove since we don't want fat objects when it is for Bitcode only.
context.add_command_line_option("-ffat-lto-objects");
context.compile_to_file(
OutputKind::ObjectFile,
bc_out.to_str().expect("path to str"),
);
}
context
.compile_to_file(OutputKind::ObjectFile, bc_out.to_str().expect("path to str"));
}
if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) {
let _timer = cgcx.prof.generic_activity_with_arg(
"GCC_module_codegen_embed_bitcode",
&*module.name,
);
if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) {
let _timer = cgcx
.prof
.generic_activity_with_arg("GCC_module_codegen_embed_bitcode", &*module.name);
if lto_supported {
// TODO(antoyo): maybe we should call embed_bitcode to have the proper iOS fixes?
//embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data);
context.add_command_line_option("-flto=auto");
context.add_command_line_option("-flto-partition=one");
context.add_command_line_option("-ffat-lto-objects");
// TODO(antoyo): Send -plugin/usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/liblto_plugin.so to linker (this should be done when specifying the appropriate rustc cli argument).
context.compile_to_file(
OutputKind::ObjectFile,
bc_out.to_str().expect("path to str"),
);
}
} else {
if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
let _timer = cgcx.prof.generic_activity_with_arg(
"GCC_module_codegen_emit_bitcode",
&*module.name,
);
context.compile_to_file(
OutputKind::ObjectFile,
bc_out.to_str().expect("path to str"),
);
}
if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) {
// TODO(antoyo): we might want to emit to emit an error here, saying to set the
// environment variable EMBED_LTO_BITCODE.
let _timer = cgcx.prof.generic_activity_with_arg(
"GCC_module_codegen_embed_bitcode",
&*module.name,
);
// TODO(antoyo): maybe we should call embed_bitcode to have the proper iOS fixes?
//embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data);
// TODO(antoyo): Send -plugin/usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/liblto_plugin.so to linker (this should be done when specifying the appropriate rustc cli argument).
context.compile_to_file(
OutputKind::ObjectFile,
bc_out.to_str().expect("path to str"),
);
}
// TODO(antoyo): Send -plugin/usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/liblto_plugin.so to linker (this should be done when specifying the appropriate rustc cli argument).
context
.compile_to_file(OutputKind::ObjectFile, bc_out.to_str().expect("path to str"));
}
}
@@ -166,7 +128,10 @@ pub(crate) fn codegen(
context.set_debug_info(true);
context.dump_to_file(path, true);
}
if should_combine_object_files {
if lto_mode != LtoMode::None {
let fat_lto = lto_mode == LtoMode::Fat;
// We need to check if we're doing LTO since this code is also used for the
// dummy ThinLTO implementation to combine the object files.
if fat_lto {
context.add_command_line_option("-flto=auto");
context.add_command_line_option("-flto-partition=one");
+6 -4
View File
@@ -21,7 +21,7 @@
use crate::builder::Builder;
use crate::context::CodegenCx;
use crate::{GccContext, LockedTargetInfo, SyncContext, gcc_util, new_context};
use crate::{GccContext, LockedTargetInfo, LtoMode, SyncContext, gcc_util, new_context};
#[cfg(feature = "master")]
pub fn visibility_to_gcc(visibility: Visibility) -> gccjit::Visibility {
@@ -74,6 +74,7 @@ pub fn compile_codegen_unit(
tcx: TyCtxt<'_>,
cgu_name: Symbol,
target_info: LockedTargetInfo,
lto_supported: bool,
) -> (ModuleCodegen<GccContext>, u64) {
let prof_timer = tcx.prof.generic_activity("codegen_module");
let start_time = Instant::now();
@@ -82,7 +83,7 @@ pub fn compile_codegen_unit(
let (module, _) = tcx.dep_graph.with_task(
dep_node,
tcx,
(cgu_name, target_info),
(cgu_name, target_info, lto_supported),
module_codegen,
Some(dep_graph::hash_result),
);
@@ -95,7 +96,7 @@ pub fn compile_codegen_unit(
fn module_codegen(
tcx: TyCtxt<'_>,
(cgu_name, target_info): (Symbol, LockedTargetInfo),
(cgu_name, target_info, lto_supported): (Symbol, LockedTargetInfo, bool),
) -> ModuleCodegen<GccContext> {
let cgu = tcx.codegen_unit(cgu_name);
// Instantiate monomorphizations without filling out definitions yet...
@@ -247,7 +248,8 @@ fn module_codegen(
GccContext {
context: Arc::new(SyncContext::new(context)),
relocation_model: tcx.sess.relocation_model(),
should_combine_object_files: false,
lto_supported,
lto_mode: LtoMode::None,
temp_dir: None,
},
)
+40 -21
View File
@@ -668,32 +668,38 @@ fn unreachable(&mut self) {
}
fn add(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
self.gcc_add(a, b)
self.assign_to_var(self.gcc_add(a, b))
}
fn fadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
a + b
self.assign_to_var(a + b)
}
// TODO(antoyo): should we also override the `unchecked_` versions?
fn sub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
self.gcc_sub(a, b)
self.assign_to_var(self.gcc_sub(a, b))
}
fn fsub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
a - b
self.assign_to_var(a - b)
}
fn mul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
self.gcc_mul(a, b)
self.assign_to_var(self.gcc_mul(a, b))
}
fn fmul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
self.cx.context.new_binary_op(self.location, BinaryOp::Mult, a.get_type(), a, b)
self.assign_to_var(self.cx.context.new_binary_op(
self.location,
BinaryOp::Mult,
a.get_type(),
a,
b,
))
}
fn udiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
self.gcc_udiv(a, b)
self.assign_to_var(self.gcc_udiv(a, b))
}
fn exactudiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
@@ -702,11 +708,11 @@ fn exactudiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
let a = self.gcc_int_cast(a, a_type);
let b_type = b.get_type().to_unsigned(self);
let b = self.gcc_int_cast(b, b_type);
self.gcc_udiv(a, b)
self.assign_to_var(self.gcc_udiv(a, b))
}
fn sdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
self.gcc_sdiv(a, b)
self.assign_to_var(self.gcc_sdiv(a, b))
}
fn exactsdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
@@ -715,19 +721,19 @@ fn exactsdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
// should be the same.
let typ = a.get_type().to_signed(self);
let b = self.gcc_int_cast(b, typ);
self.gcc_sdiv(a, b)
self.assign_to_var(self.gcc_sdiv(a, b))
}
fn fdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
a / b
self.assign_to_var(a / b)
}
fn urem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
self.gcc_urem(a, b)
self.assign_to_var(self.gcc_urem(a, b))
}
fn srem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
self.gcc_srem(a, b)
self.assign_to_var(self.gcc_srem(a, b))
}
fn frem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
@@ -865,22 +871,26 @@ fn not(&mut self, a: RValue<'gcc>) -> RValue<'gcc> {
fn fadd_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
// NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
set_rvalue_location(self, lhs + rhs)
let result = set_rvalue_location(self, lhs + rhs);
self.assign_to_var(result)
}
fn fsub_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
// NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
set_rvalue_location(self, lhs - rhs)
let result = set_rvalue_location(self, lhs - rhs);
self.assign_to_var(result)
}
fn fmul_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
// NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
set_rvalue_location(self, lhs * rhs)
let result = set_rvalue_location(self, lhs * rhs);
self.assign_to_var(result)
}
fn fdiv_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
// NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
set_rvalue_location(self, lhs / rhs)
let result = set_rvalue_location(self, lhs / rhs);
self.assign_to_var(result)
}
fn frem_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
@@ -892,22 +902,22 @@ fn frem_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
fn fadd_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
// NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
lhs + rhs
self.assign_to_var(lhs + rhs)
}
fn fsub_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
// NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
lhs - rhs
self.assign_to_var(lhs - rhs)
}
fn fmul_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
// NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
lhs * rhs
self.assign_to_var(lhs * rhs)
}
fn fdiv_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
// NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
lhs / rhs
self.assign_to_var(lhs / rhs)
}
fn frem_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
@@ -2409,6 +2419,15 @@ pub fn vector_select(
let res = then_vals | else_vals;
self.bitcast_if_needed(res, result_type)
}
// GCC doesn't like deeply nested expressions.
// By assigning intermediate expressions to a variable, this allow us to avoid deeply nested
// expressions and GCC will use much less RAM.
fn assign_to_var(&self, value: RValue<'gcc>) -> RValue<'gcc> {
let var = self.current_func().new_local(self.location, value.get_type(), "opResult");
self.llbb().add_assignment(self.location, var, value);
var.to_rvalue()
}
}
fn difference_or_zero<'gcc>(
+7 -10
View File
@@ -83,12 +83,11 @@ pub fn gcc_lshr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
let a_size = a_type.get_size();
let b_size = b_type.get_size();
match a_size.cmp(&b_size) {
std::cmp::Ordering::Less => {
let a = self.context.new_cast(self.location, a, b_type);
a >> b
}
std::cmp::Ordering::Equal => a >> b,
std::cmp::Ordering::Greater => {
_ => {
// NOTE: it is OK to cast even if b has a type bigger than a because b has
// been masked by codegen_ssa before calling Builder::lshr or
// Builder::ashr.
let b = self.context.new_cast(self.location, b, a_type);
a >> b
}
@@ -692,12 +691,10 @@ pub fn gcc_shl(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
let a_size = a_type.get_size();
let b_size = b_type.get_size();
match a_size.cmp(&b_size) {
std::cmp::Ordering::Less => {
let a = self.context.new_cast(self.location, a, b_type);
a << b
}
std::cmp::Ordering::Equal => a << b,
std::cmp::Ordering::Greater => {
_ => {
// NOTE: it is OK to cast even if b has a type bigger than a because b has
// been masked by codegen_ssa before calling Builder::shl.
let b = self.context.new_cast(self.location, b, a_type);
a << b
}
@@ -85,12 +85,41 @@ fn aarch64(name: &str, full_name: &str) -> &'static str {
fn amdgcn(name: &str, full_name: &str) -> &'static str {
match name {
// amdgcn
"add.max.i32" => "__builtin_amdgcn_add_max_i32",
"add.max.u32" => "__builtin_amdgcn_add_max_u32",
"add.min.i32" => "__builtin_amdgcn_add_min_i32",
"add.min.u32" => "__builtin_amdgcn_add_min_u32",
"alignbyte" => "__builtin_amdgcn_alignbyte",
"ashr.pk.i8.i32" => "__builtin_amdgcn_ashr_pk_i8_i32",
"ashr.pk.u8.i32" => "__builtin_amdgcn_ashr_pk_u8_i32",
"buffer.wbinvl1" => "__builtin_amdgcn_buffer_wbinvl1",
"buffer.wbinvl1.sc" => "__builtin_amdgcn_buffer_wbinvl1_sc",
"buffer.wbinvl1.vol" => "__builtin_amdgcn_buffer_wbinvl1_vol",
"cluster.id.x" => "__builtin_amdgcn_cluster_id_x",
"cluster.id.y" => "__builtin_amdgcn_cluster_id_y",
"cluster.id.z" => "__builtin_amdgcn_cluster_id_z",
"cluster.load.async.to.lds.b128" => {
"__builtin_amdgcn_cluster_load_async_to_lds_b128"
}
"cluster.load.async.to.lds.b32" => {
"__builtin_amdgcn_cluster_load_async_to_lds_b32"
}
"cluster.load.async.to.lds.b64" => {
"__builtin_amdgcn_cluster_load_async_to_lds_b64"
}
"cluster.load.async.to.lds.b8" => {
"__builtin_amdgcn_cluster_load_async_to_lds_b8"
}
"cluster.workgroup.flat.id" => "__builtin_amdgcn_cluster_workgroup_flat_id",
"cluster.workgroup.id.x" => "__builtin_amdgcn_cluster_workgroup_id_x",
"cluster.workgroup.id.y" => "__builtin_amdgcn_cluster_workgroup_id_y",
"cluster.workgroup.id.z" => "__builtin_amdgcn_cluster_workgroup_id_z",
"cluster.workgroup.max.flat.id" => {
"__builtin_amdgcn_cluster_workgroup_max_flat_id"
}
"cluster.workgroup.max.id.x" => "__builtin_amdgcn_cluster_workgroup_max_id_x",
"cluster.workgroup.max.id.y" => "__builtin_amdgcn_cluster_workgroup_max_id_y",
"cluster.workgroup.max.id.z" => "__builtin_amdgcn_cluster_workgroup_max_id_z",
"cubeid" => "__builtin_amdgcn_cubeid",
"cubema" => "__builtin_amdgcn_cubema",
"cubesc" => "__builtin_amdgcn_cubesc",
@@ -101,18 +130,36 @@ fn amdgcn(name: &str, full_name: &str) -> &'static str {
"cvt.f32.fp8" => "__builtin_amdgcn_cvt_f32_fp8",
"cvt.f32.fp8.e5m3" => "__builtin_amdgcn_cvt_f32_fp8_e5m3",
"cvt.off.f32.i4" => "__builtin_amdgcn_cvt_off_f32_i4",
"cvt.pk.bf8.f16" => "__builtin_amdgcn_cvt_pk_bf8_f16",
"cvt.pk.bf8.f32" => "__builtin_amdgcn_cvt_pk_bf8_f32",
"cvt.pk.f16.bf8" => "__builtin_amdgcn_cvt_pk_f16_bf8",
"cvt.pk.f16.fp8" => "__builtin_amdgcn_cvt_pk_f16_fp8",
"cvt.pk.f32.bf8" => "__builtin_amdgcn_cvt_pk_f32_bf8",
"cvt.pk.f32.fp8" => "__builtin_amdgcn_cvt_pk_f32_fp8",
"cvt.pk.fp8.f16" => "__builtin_amdgcn_cvt_pk_fp8_f16",
"cvt.pk.fp8.f32" => "__builtin_amdgcn_cvt_pk_fp8_f32",
"cvt.pk.fp8.f32.e5m3" => "__builtin_amdgcn_cvt_pk_fp8_f32_e5m3",
"cvt.pk.i16" => "__builtin_amdgcn_cvt_pk_i16",
"cvt.pk.u16" => "__builtin_amdgcn_cvt_pk_u16",
"cvt.pk.u8.f32" => "__builtin_amdgcn_cvt_pk_u8_f32",
"cvt.pknorm.i16" => "__builtin_amdgcn_cvt_pknorm_i16",
"cvt.pknorm.u16" => "__builtin_amdgcn_cvt_pknorm_u16",
"cvt.pkrtz" => "__builtin_amdgcn_cvt_pkrtz",
"cvt.scale.pk16.bf16.bf6" => "__builtin_amdgcn_cvt_scale_pk16_bf16_bf6",
"cvt.scale.pk16.bf16.fp6" => "__builtin_amdgcn_cvt_scale_pk16_bf16_fp6",
"cvt.scale.pk16.f16.bf6" => "__builtin_amdgcn_cvt_scale_pk16_f16_bf6",
"cvt.scale.pk16.f16.fp6" => "__builtin_amdgcn_cvt_scale_pk16_f16_fp6",
"cvt.scale.pk16.f32.bf6" => "__builtin_amdgcn_cvt_scale_pk16_f32_bf6",
"cvt.scale.pk16.f32.fp6" => "__builtin_amdgcn_cvt_scale_pk16_f32_fp6",
"cvt.scale.pk8.bf16.bf8" => "__builtin_amdgcn_cvt_scale_pk8_bf16_bf8",
"cvt.scale.pk8.bf16.fp4" => "__builtin_amdgcn_cvt_scale_pk8_bf16_fp4",
"cvt.scale.pk8.bf16.fp8" => "__builtin_amdgcn_cvt_scale_pk8_bf16_fp8",
"cvt.scale.pk8.f16.bf8" => "__builtin_amdgcn_cvt_scale_pk8_f16_bf8",
"cvt.scale.pk8.f16.fp4" => "__builtin_amdgcn_cvt_scale_pk8_f16_fp4",
"cvt.scale.pk8.f16.fp8" => "__builtin_amdgcn_cvt_scale_pk8_f16_fp8",
"cvt.scale.pk8.f32.bf8" => "__builtin_amdgcn_cvt_scale_pk8_f32_bf8",
"cvt.scale.pk8.f32.fp4" => "__builtin_amdgcn_cvt_scale_pk8_f32_fp4",
"cvt.scale.pk8.f32.fp8" => "__builtin_amdgcn_cvt_scale_pk8_f32_fp8",
"cvt.scalef32.2xpk16.bf6.f32" => "__builtin_amdgcn_cvt_scalef32_2xpk16_bf6_f32",
"cvt.scalef32.2xpk16.fp6.f32" => "__builtin_amdgcn_cvt_scalef32_2xpk16_fp6_f32",
"cvt.scalef32.f16.bf8" => "__builtin_amdgcn_cvt_scalef32_f16_bf8",
@@ -137,6 +184,12 @@ fn amdgcn(name: &str, full_name: &str) -> &'static str {
"cvt.scalef32.pk.fp8.bf16" => "__builtin_amdgcn_cvt_scalef32_pk_fp8_bf16",
"cvt.scalef32.pk.fp8.f16" => "__builtin_amdgcn_cvt_scalef32_pk_fp8_f16",
"cvt.scalef32.pk.fp8.f32" => "__builtin_amdgcn_cvt_scalef32_pk_fp8_f32",
"cvt.scalef32.pk16.bf6.bf16" => "__builtin_amdgcn_cvt_scalef32_pk16_bf6_bf16",
"cvt.scalef32.pk16.bf6.f16" => "__builtin_amdgcn_cvt_scalef32_pk16_bf6_f16",
"cvt.scalef32.pk16.bf6.f32" => "__builtin_amdgcn_cvt_scalef32_pk16_bf6_f32",
"cvt.scalef32.pk16.fp6.bf16" => "__builtin_amdgcn_cvt_scalef32_pk16_fp6_bf16",
"cvt.scalef32.pk16.fp6.f16" => "__builtin_amdgcn_cvt_scalef32_pk16_fp6_f16",
"cvt.scalef32.pk16.fp6.f32" => "__builtin_amdgcn_cvt_scalef32_pk16_fp6_f32",
"cvt.scalef32.pk32.bf16.bf6" => "__builtin_amdgcn_cvt_scalef32_pk32_bf16_bf6",
"cvt.scalef32.pk32.bf16.fp6" => "__builtin_amdgcn_cvt_scalef32_pk32_bf16_fp6",
"cvt.scalef32.pk32.bf6.bf16" => "__builtin_amdgcn_cvt_scalef32_pk32_bf6_bf16",
@@ -147,6 +200,15 @@ fn amdgcn(name: &str, full_name: &str) -> &'static str {
"cvt.scalef32.pk32.f32.fp6" => "__builtin_amdgcn_cvt_scalef32_pk32_f32_fp6",
"cvt.scalef32.pk32.fp6.bf16" => "__builtin_amdgcn_cvt_scalef32_pk32_fp6_bf16",
"cvt.scalef32.pk32.fp6.f16" => "__builtin_amdgcn_cvt_scalef32_pk32_fp6_f16",
"cvt.scalef32.pk8.bf8.bf16" => "__builtin_amdgcn_cvt_scalef32_pk8_bf8_bf16",
"cvt.scalef32.pk8.bf8.f16" => "__builtin_amdgcn_cvt_scalef32_pk8_bf8_f16",
"cvt.scalef32.pk8.bf8.f32" => "__builtin_amdgcn_cvt_scalef32_pk8_bf8_f32",
"cvt.scalef32.pk8.fp4.bf16" => "__builtin_amdgcn_cvt_scalef32_pk8_fp4_bf16",
"cvt.scalef32.pk8.fp4.f16" => "__builtin_amdgcn_cvt_scalef32_pk8_fp4_f16",
"cvt.scalef32.pk8.fp4.f32" => "__builtin_amdgcn_cvt_scalef32_pk8_fp4_f32",
"cvt.scalef32.pk8.fp8.bf16" => "__builtin_amdgcn_cvt_scalef32_pk8_fp8_bf16",
"cvt.scalef32.pk8.fp8.f16" => "__builtin_amdgcn_cvt_scalef32_pk8_fp8_f16",
"cvt.scalef32.pk8.fp8.f32" => "__builtin_amdgcn_cvt_scalef32_pk8_fp8_f32",
"cvt.scalef32.sr.bf8.bf16" => "__builtin_amdgcn_cvt_scalef32_sr_bf8_bf16",
"cvt.scalef32.sr.bf8.f16" => "__builtin_amdgcn_cvt_scalef32_sr_bf8_f16",
"cvt.scalef32.sr.bf8.f32" => "__builtin_amdgcn_cvt_scalef32_sr_bf8_f32",
@@ -156,6 +218,24 @@ fn amdgcn(name: &str, full_name: &str) -> &'static str {
"cvt.scalef32.sr.pk.fp4.bf16" => "__builtin_amdgcn_cvt_scalef32_sr_pk_fp4_bf16",
"cvt.scalef32.sr.pk.fp4.f16" => "__builtin_amdgcn_cvt_scalef32_sr_pk_fp4_f16",
"cvt.scalef32.sr.pk.fp4.f32" => "__builtin_amdgcn_cvt_scalef32_sr_pk_fp4_f32",
"cvt.scalef32.sr.pk16.bf6.bf16" => {
"__builtin_amdgcn_cvt_scalef32_sr_pk16_bf6_bf16"
}
"cvt.scalef32.sr.pk16.bf6.f16" => {
"__builtin_amdgcn_cvt_scalef32_sr_pk16_bf6_f16"
}
"cvt.scalef32.sr.pk16.bf6.f32" => {
"__builtin_amdgcn_cvt_scalef32_sr_pk16_bf6_f32"
}
"cvt.scalef32.sr.pk16.fp6.bf16" => {
"__builtin_amdgcn_cvt_scalef32_sr_pk16_fp6_bf16"
}
"cvt.scalef32.sr.pk16.fp6.f16" => {
"__builtin_amdgcn_cvt_scalef32_sr_pk16_fp6_f16"
}
"cvt.scalef32.sr.pk16.fp6.f32" => {
"__builtin_amdgcn_cvt_scalef32_sr_pk16_fp6_f32"
}
"cvt.scalef32.sr.pk32.bf6.bf16" => {
"__builtin_amdgcn_cvt_scalef32_sr_pk32_bf6_bf16"
}
@@ -174,10 +254,30 @@ fn amdgcn(name: &str, full_name: &str) -> &'static str {
"cvt.scalef32.sr.pk32.fp6.f32" => {
"__builtin_amdgcn_cvt_scalef32_sr_pk32_fp6_f32"
}
"cvt.scalef32.sr.pk8.bf8.bf16" => {
"__builtin_amdgcn_cvt_scalef32_sr_pk8_bf8_bf16"
}
"cvt.scalef32.sr.pk8.bf8.f16" => "__builtin_amdgcn_cvt_scalef32_sr_pk8_bf8_f16",
"cvt.scalef32.sr.pk8.bf8.f32" => "__builtin_amdgcn_cvt_scalef32_sr_pk8_bf8_f32",
"cvt.scalef32.sr.pk8.fp4.bf16" => {
"__builtin_amdgcn_cvt_scalef32_sr_pk8_fp4_bf16"
}
"cvt.scalef32.sr.pk8.fp4.f16" => "__builtin_amdgcn_cvt_scalef32_sr_pk8_fp4_f16",
"cvt.scalef32.sr.pk8.fp4.f32" => "__builtin_amdgcn_cvt_scalef32_sr_pk8_fp4_f32",
"cvt.scalef32.sr.pk8.fp8.bf16" => {
"__builtin_amdgcn_cvt_scalef32_sr_pk8_fp8_bf16"
}
"cvt.scalef32.sr.pk8.fp8.f16" => "__builtin_amdgcn_cvt_scalef32_sr_pk8_fp8_f16",
"cvt.scalef32.sr.pk8.fp8.f32" => "__builtin_amdgcn_cvt_scalef32_sr_pk8_fp8_f32",
"cvt.sr.bf16.f32" => "__builtin_amdgcn_cvt_sr_bf16_f32",
"cvt.sr.bf8.f16" => "__builtin_amdgcn_cvt_sr_bf8_f16",
"cvt.sr.bf8.f32" => "__builtin_amdgcn_cvt_sr_bf8_f32",
"cvt.sr.f16.f32" => "__builtin_amdgcn_cvt_sr_f16_f32",
"cvt.sr.fp8.f16" => "__builtin_amdgcn_cvt_sr_fp8_f16",
"cvt.sr.fp8.f32" => "__builtin_amdgcn_cvt_sr_fp8_f32",
"cvt.sr.fp8.f32.e5m3" => "__builtin_amdgcn_cvt_sr_fp8_f32_e5m3",
"cvt.sr.pk.bf16.f32" => "__builtin_amdgcn_cvt_sr_pk_bf16_f32",
"cvt.sr.pk.f16.f32" => "__builtin_amdgcn_cvt_sr_pk_f16_f32",
"dispatch.id" => "__builtin_amdgcn_dispatch_id",
"dot4.f32.bf8.bf8" => "__builtin_amdgcn_dot4_f32_bf8_bf8",
"dot4.f32.bf8.fp8" => "__builtin_amdgcn_dot4_f32_bf8_fp8",
@@ -297,8 +397,20 @@ fn amdgcn(name: &str, full_name: &str) -> &'static str {
"mqsad.u32.u8" => "__builtin_amdgcn_mqsad_u32_u8",
"msad.u8" => "__builtin_amdgcn_msad_u8",
"perm" => "__builtin_amdgcn_perm",
"perm.pk16.b4.u4" => "__builtin_amdgcn_perm_pk16_b4_u4",
"perm.pk16.b6.u4" => "__builtin_amdgcn_perm_pk16_b6_u4",
"perm.pk16.b8.u4" => "__builtin_amdgcn_perm_pk16_b8_u4",
"permlane.bcast" => "__builtin_amdgcn_permlane_bcast",
"permlane.down" => "__builtin_amdgcn_permlane_down",
"permlane.idx.gen" => "__builtin_amdgcn_permlane_idx_gen",
"permlane.up" => "__builtin_amdgcn_permlane_up",
"permlane.xor" => "__builtin_amdgcn_permlane_xor",
"permlane16.var" => "__builtin_amdgcn_permlane16_var",
"permlanex16.var" => "__builtin_amdgcn_permlanex16_var",
"pk.add.max.i16" => "__builtin_amdgcn_pk_add_max_i16",
"pk.add.max.u16" => "__builtin_amdgcn_pk_add_max_u16",
"pk.add.min.i16" => "__builtin_amdgcn_pk_add_min_i16",
"pk.add.min.u16" => "__builtin_amdgcn_pk_add_min_u16",
"prng.b32" => "__builtin_amdgcn_prng_b32",
"qsad.pk.u16.u8" => "__builtin_amdgcn_qsad_pk_u16_u8",
"queue.ptr" => "__builtin_amdgcn_queue_ptr",
@@ -306,11 +418,15 @@ fn amdgcn(name: &str, full_name: &str) -> &'static str {
"rcp.legacy" => "__builtin_amdgcn_rcp_legacy",
"rsq.legacy" => "__builtin_amdgcn_rsq_legacy",
"s.barrier" => "__builtin_amdgcn_s_barrier",
"s.barrier.init" => "__builtin_amdgcn_s_barrier_init",
"s.barrier.join" => "__builtin_amdgcn_s_barrier_join",
"s.barrier.leave" => "__builtin_amdgcn_s_barrier_leave",
"s.barrier.signal" => "__builtin_amdgcn_s_barrier_signal",
"s.barrier.signal.isfirst" => "__builtin_amdgcn_s_barrier_signal_isfirst",
"s.barrier.signal.var" => "__builtin_amdgcn_s_barrier_signal_var",
"s.barrier.wait" => "__builtin_amdgcn_s_barrier_wait",
"s.buffer.prefetch.data" => "__builtin_amdgcn_s_buffer_prefetch_data",
"s.cluster.barrier" => "__builtin_amdgcn_s_cluster_barrier",
"s.dcache.inv" => "__builtin_amdgcn_s_dcache_inv",
"s.dcache.inv.vol" => "__builtin_amdgcn_s_dcache_inv_vol",
"s.dcache.wb" => "__builtin_amdgcn_s_dcache_wb",
@@ -1900,6 +2016,8 @@ fn hexagon(name: &str, full_name: &str) -> &'static str {
"V6.vfneg.hf.128B" => "__builtin_HEXAGON_V6_vfneg_hf_128B",
"V6.vfneg.sf" => "__builtin_HEXAGON_V6_vfneg_sf",
"V6.vfneg.sf.128B" => "__builtin_HEXAGON_V6_vfneg_sf_128B",
"V6.vgather.vscattermh" => "__builtin_HEXAGON_V6_vgather_vscattermh",
"V6.vgather.vscattermh.128B" => "__builtin_HEXAGON_V6_vgather_vscattermh_128B",
"V6.vgathermh" => "__builtin_HEXAGON_V6_vgathermh",
"V6.vgathermh.128B" => "__builtin_HEXAGON_V6_vgathermh_128B",
"V6.vgathermhq" => "__builtin_HEXAGON_V6_vgathermhq",
@@ -2382,6 +2500,8 @@ fn hexagon(name: &str, full_name: &str) -> &'static str {
"V6.vsub.hf.f8.128B" => "__builtin_HEXAGON_V6_vsub_hf_f8_128B",
"V6.vsub.hf.hf" => "__builtin_HEXAGON_V6_vsub_hf_hf",
"V6.vsub.hf.hf.128B" => "__builtin_HEXAGON_V6_vsub_hf_hf_128B",
"V6.vsub.hf.mix" => "__builtin_HEXAGON_V6_vsub_hf_mix",
"V6.vsub.hf.mix.128B" => "__builtin_HEXAGON_V6_vsub_hf_mix_128B",
"V6.vsub.qf16" => "__builtin_HEXAGON_V6_vsub_qf16",
"V6.vsub.qf16.128B" => "__builtin_HEXAGON_V6_vsub_qf16_128B",
"V6.vsub.qf16.mix" => "__builtin_HEXAGON_V6_vsub_qf16_mix",
@@ -2396,6 +2516,8 @@ fn hexagon(name: &str, full_name: &str) -> &'static str {
"V6.vsub.sf.bf.128B" => "__builtin_HEXAGON_V6_vsub_sf_bf_128B",
"V6.vsub.sf.hf" => "__builtin_HEXAGON_V6_vsub_sf_hf",
"V6.vsub.sf.hf.128B" => "__builtin_HEXAGON_V6_vsub_sf_hf_128B",
"V6.vsub.sf.mix" => "__builtin_HEXAGON_V6_vsub_sf_mix",
"V6.vsub.sf.mix.128B" => "__builtin_HEXAGON_V6_vsub_sf_mix_128B",
"V6.vsub.sf.sf" => "__builtin_HEXAGON_V6_vsub_sf_sf",
"V6.vsub.sf.sf.128B" => "__builtin_HEXAGON_V6_vsub_sf_sf_128B",
"V6.vsubb" => "__builtin_HEXAGON_V6_vsubb",
@@ -4883,6 +5005,26 @@ fn nvvm(name: &str, full_name: &str) -> &'static str {
"f2ull.rp.ftz" => "__nvvm_f2ull_rp_ftz",
"f2ull.rz" => "__nvvm_f2ull_rz",
"f2ull.rz.ftz" => "__nvvm_f2ull_rz_ftz",
"f32x4.to.e2m1x4.rs.relu.satfinite" => {
"__nvvm_f32x4_to_e2m1x4_rs_relu_satfinite"
}
"f32x4.to.e2m1x4.rs.satfinite" => "__nvvm_f32x4_to_e2m1x4_rs_satfinite",
"f32x4.to.e2m3x4.rs.relu.satfinite" => {
"__nvvm_f32x4_to_e2m3x4_rs_relu_satfinite"
}
"f32x4.to.e2m3x4.rs.satfinite" => "__nvvm_f32x4_to_e2m3x4_rs_satfinite",
"f32x4.to.e3m2x4.rs.relu.satfinite" => {
"__nvvm_f32x4_to_e3m2x4_rs_relu_satfinite"
}
"f32x4.to.e3m2x4.rs.satfinite" => "__nvvm_f32x4_to_e3m2x4_rs_satfinite",
"f32x4.to.e4m3x4.rs.relu.satfinite" => {
"__nvvm_f32x4_to_e4m3x4_rs_relu_satfinite"
}
"f32x4.to.e4m3x4.rs.satfinite" => "__nvvm_f32x4_to_e4m3x4_rs_satfinite",
"f32x4.to.e5m2x4.rs.relu.satfinite" => {
"__nvvm_f32x4_to_e5m2x4_rs_relu_satfinite"
}
"f32x4.to.e5m2x4.rs.satfinite" => "__nvvm_f32x4_to_e5m2x4_rs_satfinite",
"fabs.d" => "__nvvm_fabs_d",
"fabs.f" => "__nvvm_fabs_f",
"fabs.ftz.f" => "__nvvm_fabs_ftz_f",
@@ -4902,10 +5044,18 @@ fn nvvm(name: &str, full_name: &str) -> &'static str {
"ff.to.ue8m0x2.rz.satfinite" => "__nvvm_ff_to_ue8m0x2_rz_satfinite",
"ff2bf16x2.rn" => "__nvvm_ff2bf16x2_rn",
"ff2bf16x2.rn.relu" => "__nvvm_ff2bf16x2_rn_relu",
"ff2bf16x2.rs" => "__nvvm_ff2bf16x2_rs",
"ff2bf16x2.rs.relu" => "__nvvm_ff2bf16x2_rs_relu",
"ff2bf16x2.rs.relu.satfinite" => "__nvvm_ff2bf16x2_rs_relu_satfinite",
"ff2bf16x2.rs.satfinite" => "__nvvm_ff2bf16x2_rs_satfinite",
"ff2bf16x2.rz" => "__nvvm_ff2bf16x2_rz",
"ff2bf16x2.rz.relu" => "__nvvm_ff2bf16x2_rz_relu",
"ff2f16x2.rn" => "__nvvm_ff2f16x2_rn",
"ff2f16x2.rn.relu" => "__nvvm_ff2f16x2_rn_relu",
"ff2f16x2.rs" => "__nvvm_ff2f16x2_rs",
"ff2f16x2.rs.relu" => "__nvvm_ff2f16x2_rs_relu",
"ff2f16x2.rs.relu.satfinite" => "__nvvm_ff2f16x2_rs_relu_satfinite",
"ff2f16x2.rs.satfinite" => "__nvvm_ff2f16x2_rs_satfinite",
"ff2f16x2.rz" => "__nvvm_ff2f16x2_rz",
"ff2f16x2.rz.relu" => "__nvvm_ff2f16x2_rz_relu",
"floor.d" => "__nvvm_floor_d",
@@ -5129,6 +5279,7 @@ fn nvvm(name: &str, full_name: &str) -> &'static str {
"read.ptx.sreg.envreg8" => "__nvvm_read_ptx_sreg_envreg8",
"read.ptx.sreg.envreg9" => "__nvvm_read_ptx_sreg_envreg9",
"read.ptx.sreg.globaltimer" => "__nvvm_read_ptx_sreg_globaltimer",
"read.ptx.sreg.globaltimer.lo" => "__nvvm_read_ptx_sreg_globaltimer_lo",
"read.ptx.sreg.gridid" => "__nvvm_read_ptx_sreg_gridid",
// [DUPLICATE]: "read.ptx.sreg.gridid" => "__nvvm_read_ptx_sreg_",
"read.ptx.sreg.laneid" => "__nvvm_read_ptx_sreg_laneid",
@@ -5803,6 +5954,8 @@ fn ppc(name: &str, full_name: &str) -> &'static str {
"altivec.vupklsw" => "__builtin_altivec_vupklsw",
"bcdadd" => "__builtin_ppc_bcdadd",
"bcdadd.p" => "__builtin_ppc_bcdadd_p",
"bcdcopysign" => "__builtin_ppc_bcdcopysign",
"bcdsetsign" => "__builtin_ppc_bcdsetsign",
"bcdsub" => "__builtin_ppc_bcdsub",
"bcdsub.p" => "__builtin_ppc_bcdsub_p",
"bpermd" => "__builtin_bpermd",
@@ -6160,6 +6313,9 @@ fn riscv(name: &str, full_name: &str) -> &'static str {
"aes64im" => "__builtin_riscv_aes64im",
"aes64ks1i" => "__builtin_riscv_aes64ks1i",
"aes64ks2" => "__builtin_riscv_aes64ks2",
"mips.ehb" => "__builtin_riscv_mips_ehb",
"mips.ihb" => "__builtin_riscv_mips_ihb",
"mips.pause" => "__builtin_riscv_mips_pause",
"sha512sig0" => "__builtin_riscv_sha512sig0",
"sha512sig0h" => "__builtin_riscv_sha512sig0h",
"sha512sig0l" => "__builtin_riscv_sha512sig0l",
@@ -308,10 +308,6 @@ fn codegen_intrinsic_call(
.or_else(|| get_simple_function_f128(self, name))
.or_else(|| get_simple_function_f128_2args(self, name));
// FIXME(tempdragon): Re-enable `clippy::suspicious_else_formatting` if the following issue is solved:
// https://github.com/rust-lang/rust-clippy/issues/12497
// and leave `else if use_integer_compare` to be placed "as is".
#[allow(clippy::suspicious_else_formatting)]
let value = match name {
_ if simple.is_some() => {
let func = simple.expect("simple intrinsic function");
+33 -9
View File
@@ -72,10 +72,7 @@
use std::fmt::Debug;
use std::ops::Deref;
use std::path::PathBuf;
#[cfg(not(feature = "master"))]
use std::sync::atomic::AtomicBool;
#[cfg(not(feature = "master"))]
use std::sync::atomic::Ordering;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use back::lto::{ThinBuffer, ThinData};
@@ -167,8 +164,11 @@ fn supports_target_dependent_type(&self, typ: CType) -> bool {
#[derive(Clone)]
pub struct GccCodegenBackend {
target_info: LockedTargetInfo,
lto_supported: Arc<AtomicBool>,
}
static LTO_SUPPORTED: AtomicBool = AtomicBool::new(false);
impl CodegenBackend for GccCodegenBackend {
fn locale_resource(&self) -> &'static str {
crate::DEFAULT_LOCALE_RESOURCE
@@ -193,7 +193,13 @@ fn init(&self, _sess: &Session) {
}
#[cfg(feature = "master")]
gccjit::set_global_personality_function_name(b"rust_eh_personality\0");
{
let lto_supported = gccjit::is_lto_supported();
LTO_SUPPORTED.store(lto_supported, Ordering::SeqCst);
self.lto_supported.store(lto_supported, Ordering::SeqCst);
gccjit::set_global_personality_function_name(b"rust_eh_personality\0");
}
#[cfg(not(feature = "master"))]
{
@@ -276,10 +282,12 @@ fn codegen_allocator(
module_name: &str,
methods: &[AllocatorMethod],
) -> Self::Module {
let lto_supported = self.lto_supported.load(Ordering::SeqCst);
let mut mods = GccContext {
context: Arc::new(SyncContext::new(new_context(tcx))),
relocation_model: tcx.sess.relocation_model(),
should_combine_object_files: false,
lto_mode: LtoMode::None,
lto_supported,
temp_dir: None,
};
@@ -294,7 +302,12 @@ fn compile_codegen_unit(
tcx: TyCtxt<'_>,
cgu_name: Symbol,
) -> (ModuleCodegen<Self::Module>, u64) {
base::compile_codegen_unit(tcx, cgu_name, self.target_info.clone())
base::compile_codegen_unit(
tcx,
cgu_name,
self.target_info.clone(),
self.lto_supported.load(Ordering::SeqCst),
)
}
fn target_machine_factory(
@@ -308,12 +321,20 @@ fn target_machine_factory(
}
}
#[derive(Clone, Copy, PartialEq)]
pub enum LtoMode {
None,
Thin,
Fat,
}
pub struct GccContext {
context: Arc<SyncContext>,
/// This field is needed in order to be able to set the flag -fPIC when necessary when doing
/// LTO.
relocation_model: RelocModel,
should_combine_object_files: bool,
lto_mode: LtoMode,
lto_supported: bool,
// Temporary directory used by LTO. We keep it here so that it's not removed before linking.
temp_dir: Option<TempDir>,
}
@@ -425,7 +446,10 @@ pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
supports_128bit_integers: AtomicBool::new(false),
})));
Box::new(GccCodegenBackend { target_info: LockedTargetInfo { info } })
Box::new(GccCodegenBackend {
lto_supported: Arc::new(AtomicBool::new(false)),
target_info: LockedTargetInfo { info },
})
}
fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "cross_lang_lto"
version = "0.1.0"
@@ -0,0 +1,6 @@
[package]
name = "cross_lang_lto"
version = "0.1.0"
edition = "2024"
[dependencies]
@@ -0,0 +1,5 @@
#include <stdint.h>
uint32_t my_add(uint32_t a, uint32_t b) {
return a + b;
}
@@ -0,0 +1,18 @@
/*
* Compile the C code with:
* gcc -c -flto add.c -ffat-lto-objects
* ar rcs libadd.a add.o
*
* Compile the Rust code with:
* CG_RUSTFLAGS="-L native=. -Clinker-plugin-lto -Clinker=gcc" y cargo run --release
*/
#[link(name="add")]
unsafe extern "C" {
fn my_add(a: u32, b: u32) -> u32;
}
fn main() {
let res = unsafe { my_add(30, 12) };
println!("{}", res);
}
@@ -1,33 +0,0 @@
tests/ui/lint/unsafe_code/forge_unsafe_block.rs
tests/ui/lint/unused-qualification-in-derive-expansion.rs
tests/ui/macros/macro-quote-test.rs
tests/ui/macros/proc_macro.rs
tests/ui/panic-runtime/lto-unwind.rs
tests/ui/resolve/derive-macro-1.rs
tests/ui/resolve/derive-macro-2.rs
tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-pretty.rs
tests/ui/rfcs/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs
tests/ui/rfcs/rfc-3348-c-string-literals/edition-spans.rs
tests/ui/rust-2018/suggestions-not-always-applicable.rs
tests/ui/rust-2021/reserved-prefixes-via-macro.rs
tests/ui/underscore-imports/duplicate.rs
tests/ui/async-await/issues/issue-60674.rs
tests/ui/attributes/main-removed-2/main.rs
tests/ui/cfg/assume-incomplete-release/assume-incomplete.rs
tests/ui/crate-loading/cross-compiled-proc-macro.rs
tests/ui/derives/derive-marker-tricky.rs
tests/ui/diagnostic_namespace/existing_proc_macros.rs
tests/ui/fmt/format-args-capture-issue-106408.rs
tests/ui/fmt/indoc-issue-106408.rs
tests/ui/hygiene/issue-77523-def-site-async-await.rs
tests/ui/inherent-impls-overlap-check/no-overlap.rs
tests/ui/enum-discriminant/issue-46519.rs
tests/ui/issues/issue-45731.rs
tests/ui/lint/test-allow-dead-extern-static-no-warning.rs
tests/ui/macros/macro-comma-behavior-rpass.rs
tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs
tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs
tests/ui/macros/stringify.rs
tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test.rs
tests/ui/binding/fn-arg-incomplete-pattern-drop-order.rs
tests/ui/lto/debuginfo-lto-alloc.rs
@@ -1,35 +1,11 @@
tests/run-make/a-b-a-linker-guard/
tests/run-make/CURRENT_RUSTC_VERSION/
tests/run-make/cross-lang-lto/
tests/run-make/cross-lang-lto-upstream-rlibs/
tests/run-make/doctests-keep-binaries/
tests/run-make/doctests-runtool/
tests/run-make/emit-shared-files/
tests/run-make/exit-code/
tests/run-make/llvm-ident/
tests/run-make/native-link-modifier-bundle/
tests/run-make/remap-path-prefix-dwarf/
tests/run-make/repr128-dwarf/
tests/run-make/rlib-format-packed-bundled-libs/
tests/run-make/rlib-format-packed-bundled-libs-2/
tests/run-make/rustdoc-determinism/
tests/run-make/rustdoc-error-lines/
tests/run-make/rustdoc-map-file/
tests/run-make/rustdoc-output-path/
tests/run-make/rustdoc-scrape-examples-invalid-expr/
tests/run-make/rustdoc-scrape-examples-multiple/
tests/run-make/rustdoc-scrape-examples-ordering/
tests/run-make/rustdoc-scrape-examples-remap/
tests/run-make/rustdoc-scrape-examples-test/
tests/run-make/rustdoc-scrape-examples-whitespace/
tests/run-make/rustdoc-scrape-examples-macros/
tests/run-make/rustdoc-with-out-dir-option/
tests/run-make/rustdoc-verify-output-files/
tests/run-make/rustdoc-themes/
tests/run-make/rustdoc-with-short-out-dir-option/
tests/run-make/rustdoc-with-output-option/
tests/run-make/arguments-non-c-like-enum/
tests/run-make/c-link-to-rust-staticlib/
tests/run-make/foreign-double-unwind/
tests/run-make/foreign-exceptions/
tests/run-make/glibc-staticlib-args/
@@ -1,5 +1,3 @@
tests/ui/allocator/no_std-alloc-error-handler-custom.rs
tests/ui/allocator/no_std-alloc-error-handler-default.rs
tests/ui/asm/may_unwind.rs
tests/ui/asm/x86_64/may_unwind.rs
tests/ui/drop/dynamic-drop-async.rs
@@ -17,7 +15,6 @@ tests/ui/panic-runtime/link-to-abort.rs
tests/ui/parser/unclosed-delimiter-in-dep.rs
tests/ui/consts/missing_span_in_backtrace.rs
tests/ui/drop/dynamic-drop.rs
tests/ui/rfcs/rfc-2091-track-caller/std-panic-locations.rs
tests/ui/simd/issue-17170.rs
tests/ui/simd/issue-39720.rs
tests/ui/drop/panic-during-drop-14875.rs
@@ -31,11 +28,9 @@ tests/ui/coroutine/resume-after-return.rs
tests/ui/simd/masked-load-store.rs
tests/ui/simd/repr_packed.rs
tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs
tests/ui/consts/try-operator.rs
tests/ui/coroutine/unwind-abort-mix.rs
tests/ui/consts/issue-miri-1910.rs
tests/ui/consts/const_cmp_type_id.rs
tests/ui/consts/issue-73976-monomorphic.rs
tests/ui/consts/issue-94675.rs
tests/ui/traits/const-traits/const-drop-fail.rs
tests/ui/runtime/on-broken-pipe/child-processes.rs
@@ -53,7 +48,6 @@ tests/ui/sanitizer/cfi/virtual-auto.rs
tests/ui/sanitizer/cfi/sized-associated-ty.rs
tests/ui/sanitizer/cfi/can-reveal-opaques.rs
tests/ui/sanitizer/kcfi-mangling.rs
tests/ui/statics/const_generics.rs
tests/ui/backtrace/dylib-dep.rs
tests/ui/delegation/fn-header.rs
tests/ui/consts/const-eval/parse_ints.rs
@@ -74,13 +68,7 @@ tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs
tests/ui/simd/simd-bitmask-notpow2.rs
tests/ui/codegen/StackColoring-not-blowup-stack-issue-40883.rs
tests/ui/numbers-arithmetic/u128-as-f32.rs
tests/ui/lto/all-crates.rs
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
tests/ui/linking/no-gc-encapsulation-symbols.rs
tests/ui/panics/unwind-force-no-unwind-tables.rs
tests/ui/attributes/fn-align-dyn.rs
@@ -88,3 +76,4 @@ tests/ui/linkage-attr/raw-dylib/elf/glibc-x86_64.rs
tests/ui/explicit-tail-calls/recursion-etc.rs
tests/ui/explicit-tail-calls/indexer.rs
tests/ui/explicit-tail-calls/drop-order.rs
tests/ui/c-variadic/valid.rs
@@ -683,7 +683,7 @@ fn handle_offload<'ll>(cx: &'ll SimpleCx<'_>, old_fn: &llvm::Value) {
// Here we map the old arguments to the new arguments, with an offset of 1 to make sure
// that we don't use the newly added `%dyn_ptr`.
unsafe {
llvm::LLVMRustOffloadMapper(cx.llmod(), old_fn, new_fn);
llvm::LLVMRustOffloadMapper(old_fn, new_fn);
}
llvm::set_linkage(new_fn, llvm::get_linkage(old_fn));
+84 -24
View File
@@ -760,30 +760,18 @@ fn write_operand_repeatedly(
count: u64,
dest: PlaceRef<'tcx, &'ll Value>,
) {
let zero = self.const_usize(0);
let count = self.const_usize(count);
let header_bb = self.append_sibling_block("repeat_loop_header");
let body_bb = self.append_sibling_block("repeat_loop_body");
let next_bb = self.append_sibling_block("repeat_loop_next");
self.br(header_bb);
let mut header_bx = Self::build(self.cx, header_bb);
let i = header_bx.phi(self.val_ty(zero), &[zero], &[self.llbb()]);
let keep_going = header_bx.icmp(IntPredicate::IntULT, i, count);
header_bx.cond_br(keep_going, body_bb, next_bb);
let mut body_bx = Self::build(self.cx, body_bb);
let dest_elem = dest.project_index(&mut body_bx, i);
cg_elem.val.store(&mut body_bx, dest_elem);
let next = body_bx.unchecked_uadd(i, self.const_usize(1));
body_bx.br(header_bb);
header_bx.add_incoming_to_phi(i, next, body_bb);
*self = Self::build(self.cx, next_bb);
if self.cx.sess().opts.optimize == OptLevel::No {
// To let debuggers single-step over lines like
//
// let foo = ["bar"; 42];
//
// we need the debugger-friendly LLVM IR that `_unoptimized()`
// provides. The `_optimized()` version generates trickier LLVM IR.
// See PR #148058 for a failed attempt at handling that.
self.write_operand_repeatedly_unoptimized(cg_elem, count, dest);
} else {
self.write_operand_repeatedly_optimized(cg_elem, count, dest);
}
}
fn range_metadata(&mut self, load: &'ll Value, range: WrappingRange) {
@@ -1514,6 +1502,78 @@ pub(crate) fn set_unpredictable(&mut self, inst: &'ll Value) {
self.set_metadata_node(inst, llvm::MD_unpredictable, &[]);
}
fn write_operand_repeatedly_optimized(
&mut self,
cg_elem: OperandRef<'tcx, &'ll Value>,
count: u64,
dest: PlaceRef<'tcx, &'ll Value>,
) {
let zero = self.const_usize(0);
let count = self.const_usize(count);
let header_bb = self.append_sibling_block("repeat_loop_header");
let body_bb = self.append_sibling_block("repeat_loop_body");
let next_bb = self.append_sibling_block("repeat_loop_next");
self.br(header_bb);
let mut header_bx = Self::build(self.cx, header_bb);
let i = header_bx.phi(self.val_ty(zero), &[zero], &[self.llbb()]);
let keep_going = header_bx.icmp(IntPredicate::IntULT, i, count);
header_bx.cond_br(keep_going, body_bb, next_bb);
let mut body_bx = Self::build(self.cx, body_bb);
let dest_elem = dest.project_index(&mut body_bx, i);
cg_elem.val.store(&mut body_bx, dest_elem);
let next = body_bx.unchecked_uadd(i, self.const_usize(1));
body_bx.br(header_bb);
header_bx.add_incoming_to_phi(i, next, body_bb);
*self = Self::build(self.cx, next_bb);
}
fn write_operand_repeatedly_unoptimized(
&mut self,
cg_elem: OperandRef<'tcx, &'ll Value>,
count: u64,
dest: PlaceRef<'tcx, &'ll Value>,
) {
let zero = self.const_usize(0);
let count = self.const_usize(count);
let start = dest.project_index(self, zero).val.llval;
let end = dest.project_index(self, count).val.llval;
let header_bb = self.append_sibling_block("repeat_loop_header");
let body_bb = self.append_sibling_block("repeat_loop_body");
let next_bb = self.append_sibling_block("repeat_loop_next");
self.br(header_bb);
let mut header_bx = Self::build(self.cx, header_bb);
let current = header_bx.phi(self.val_ty(start), &[start], &[self.llbb()]);
let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end);
header_bx.cond_br(keep_going, body_bb, next_bb);
let mut body_bx = Self::build(self.cx, body_bb);
let align = dest.val.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size);
cg_elem
.val
.store(&mut body_bx, PlaceRef::new_sized_aligned(current, cg_elem.layout, align));
let next = body_bx.inbounds_gep(
self.backend_type(cg_elem.layout),
current,
&[self.const_usize(1)],
);
body_bx.br(header_bb);
header_bx.add_incoming_to_phi(current, next, body_bb);
*self = Self::build(self.cx, next_bb);
}
pub(crate) fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.call_intrinsic("llvm.minnum", &[self.val_ty(lhs)], &[lhs, rhs])
}
+2 -2
View File
@@ -7,7 +7,7 @@
use rustc_codegen_ssa::common;
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv};
use rustc_middle::ty::{self, Instance, TypeVisitableExt};
use rustc_target::spec::Arch;
use rustc_target::spec::{Arch, Env};
use tracing::debug;
use crate::context::CodegenCx;
@@ -145,7 +145,7 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
if cx.use_dll_storage_attrs
&& let Some(library) = tcx.native_library(instance_def_id)
&& library.kind.is_dllimport()
&& !matches!(tcx.sess.target.env.as_ref(), "gnu" | "uclibc")
&& !matches!(tcx.sess.target.env, Env::Gnu | Env::Uclibc)
{
llvm::set_dllimport_storage_class(llfn);
}
+7 -7
View File
@@ -29,7 +29,7 @@
use rustc_span::{DUMMY_SP, Span, Symbol};
use rustc_symbol_mangling::mangle_internal_symbol;
use rustc_target::spec::{
Arch, HasTargetSpec, RelocModel, SmallDataThresholdSupport, Target, TlsModel,
Abi, Arch, Env, HasTargetSpec, Os, RelocModel, SmallDataThresholdSupport, Target, TlsModel,
};
use smallvec::SmallVec;
@@ -335,9 +335,9 @@ pub(crate) unsafe fn create_module<'ll>(
// Control Flow Guard is currently only supported by MSVC and LLVM on Windows.
if sess.target.is_like_msvc
|| (sess.target.options.os == "windows"
&& sess.target.options.env == "gnu"
&& sess.target.options.abi == "llvm")
|| (sess.target.options.os == Os::Windows
&& sess.target.options.env == Env::Gnu
&& sess.target.options.abi == Abi::Llvm)
{
match sess.opts.cg.control_flow_guard {
CFGuard::Disabled => {}
@@ -669,7 +669,7 @@ pub(crate) fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'
/// This corresponds to the `-fobjc-abi-version=` flag in Clang / GCC.
pub(crate) fn objc_abi_version(&self) -> u32 {
assert!(self.tcx.sess.target.is_like_darwin);
if self.tcx.sess.target.arch == Arch::X86 && self.tcx.sess.target.os == "macos" {
if self.tcx.sess.target.arch == Arch::X86 && self.tcx.sess.target.os == Os::MacOs {
// 32-bit x86 macOS uses ABI version 1 (a.k.a. the "fragile ABI").
1
} else {
@@ -710,7 +710,7 @@ pub(crate) fn add_objc_module_flags(&self) {
},
);
if self.tcx.sess.target.env == "sim" {
if self.tcx.sess.target.env == Env::Sim {
llvm::add_module_flag_u32(
self.llmod,
llvm::ModuleFlagMergeBehavior::Error,
@@ -963,7 +963,7 @@ pub(crate) fn eh_catch_typeinfo(&self) -> &'ll Value {
return eh_catch_typeinfo;
}
let tcx = self.tcx;
assert!(self.sess().target.os == "emscripten");
assert!(self.sess().target.os == Os::Emscripten);
let eh_catch_typeinfo = match tcx.lang_items().eh_catch_typeinfo() {
Some(def_id) => self.get_static(def_id),
_ => {
+2 -1
View File
@@ -18,6 +18,7 @@
use rustc_span::{Span, Symbol, sym};
use rustc_symbol_mangling::{mangle_internal_symbol, symbol_name_for_instance_in_crate};
use rustc_target::callconv::PassMode;
use rustc_target::spec::Os;
use tracing::debug;
use crate::abi::FnAbiLlvmExt;
@@ -681,7 +682,7 @@ fn catch_unwind_intrinsic<'ll, 'tcx>(
codegen_msvc_try(bx, try_func, data, catch_func, dest);
} else if wants_wasm_eh(bx.sess()) {
codegen_wasm_try(bx, try_func, data, catch_func, dest);
} else if bx.sess().target.os == "emscripten" {
} else if bx.sess().target.os == Os::Emscripten {
codegen_emcc_try(bx, try_func, data, catch_func, dest);
} else {
codegen_gnu_try(bx, try_func, data, catch_func, dest);
+1 -1
View File
@@ -2025,7 +2025,7 @@ pub(crate) fn LLVMRustCreateRangeAttribute(
) -> &Attribute;
// Operations on functions
pub(crate) fn LLVMRustOffloadMapper<'a>(M: &'a Module, Fn: &'a Value, Fn: &'a Value);
pub(crate) fn LLVMRustOffloadMapper<'a>(Fn: &'a Value, Fn: &'a Value);
pub(crate) fn LLVMRustGetOrInsertFunction<'a>(
M: &'a Module,
Name: *const c_char,
+11 -9
View File
@@ -15,7 +15,9 @@
use rustc_middle::bug;
use rustc_session::Session;
use rustc_session::config::{PrintKind, PrintRequest};
use rustc_target::spec::{Arch, MergeFunctions, PanicStrategy, SmallDataThresholdSupport};
use rustc_target::spec::{
Abi, Arch, Env, MergeFunctions, Os, PanicStrategy, SmallDataThresholdSupport,
};
use smallvec::{SmallVec, smallvec};
use crate::back::write::create_informational_target_machine;
@@ -104,7 +106,7 @@ fn llvm_arg_to_arg_name(full_arg: &str) -> &str {
add("-wasm-enable-eh", false);
}
if sess.target.os == "emscripten"
if sess.target.os == Os::Emscripten
&& !sess.opts.unstable_opts.emscripten_wasm_eh
&& sess.panic_strategy().unwinds()
{
@@ -351,9 +353,9 @@ pub(crate) fn target_config(sess: &Session) -> TargetConfig {
/// Determine whether or not experimental float types are reliable based on known bugs.
fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) {
let target_arch = &sess.target.arch;
let target_os = sess.target.options.os.as_ref();
let target_env = sess.target.options.env.as_ref();
let target_abi = sess.target.options.abi.as_ref();
let target_os = &sess.target.options.os;
let target_env = &sess.target.options.env;
let target_abi = &sess.target.options.abi;
let target_pointer_width = sess.target.pointer_width;
let version = get_version();
let lt_20_1_1 = version < (20, 1, 1);
@@ -371,7 +373,7 @@ fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) {
// Selection failure <https://github.com/llvm/llvm-project/issues/50374> (fixed in llvm21)
(Arch::S390x, _) if lt_21_0_0 => false,
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
(Arch::X86_64, "windows") if target_env == "gnu" && target_abi != "llvm" => false,
(Arch::X86_64, Os::Windows) if *target_env == Env::Gnu && *target_abi != Abi::Llvm => false,
// Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
(Arch::CSky, _) => false,
(Arch::Hexagon, _) if lt_21_0_0 => false, // (fixed in llvm21)
@@ -403,7 +405,7 @@ fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) {
// not fail if our compiler-builtins is linked. (fixed in llvm21)
(Arch::X86, _) if lt_21_0_0 => false,
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
(Arch::X86_64, "windows") if target_env == "gnu" && target_abi != "llvm" => false,
(Arch::X86_64, Os::Windows) if *target_env == Env::Gnu && *target_abi != Abi::Llvm => false,
// There are no known problems on other platforms, so the only requirement is that symbols
// are available. `compiler-builtins` provides all symbols required for core `f128`
// support, so this should work for everything else.
@@ -424,9 +426,9 @@ fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) {
// (ld is 80-bit extended precision).
//
// musl does not implement the symbols required for f128 math at all.
_ if target_env == "musl" => false,
_ if *target_env == Env::Musl => false,
(Arch::X86_64, _) => false,
(_, "linux") if target_pointer_width == 64 => true,
(_, Os::Linux) if target_pointer_width == 64 => true,
_ => false,
} && cfg.has_reliable_f128;
}
+2 -2
View File
@@ -7,7 +7,7 @@
};
use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
use rustc_target::spec::Arch;
use rustc_target::spec::{Abi, Arch};
use crate::builder::Builder;
use crate::llvm::{Type, Value};
@@ -270,7 +270,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>(
// Rust does not currently support any powerpc softfloat targets.
let target = &bx.cx.tcx.sess.target;
let is_soft_float_abi = target.abi == "softfloat";
let is_soft_float_abi = target.abi == Abi::SoftFloat;
assert!(!is_soft_float_abi);
// All instances of VaArgSafe are passed directly.
+24 -24
View File
@@ -6,7 +6,7 @@
use rustc_middle::middle::exported_symbols::SymbolExportKind;
use rustc_session::Session;
pub(super) use rustc_target::spec::apple::OSVersion;
use rustc_target::spec::{Arch, Target};
use rustc_target::spec::{Arch, Env, Os, Target};
use tracing::debug;
use crate::errors::{XcrunError, XcrunSdkPathWarning};
@@ -17,35 +17,35 @@
/// The canonical name of the desired SDK for a given target.
pub(super) fn sdk_name(target: &Target) -> &'static str {
match (&*target.os, &*target.env) {
("macos", "") => "MacOSX",
("ios", "") => "iPhoneOS",
("ios", "sim") => "iPhoneSimulator",
match (&target.os, &target.env) {
(Os::MacOs, Env::Unspecified) => "MacOSX",
(Os::IOs, Env::Unspecified) => "iPhoneOS",
(Os::IOs, Env::Sim) => "iPhoneSimulator",
// Mac Catalyst uses the macOS SDK
("ios", "macabi") => "MacOSX",
("tvos", "") => "AppleTVOS",
("tvos", "sim") => "AppleTVSimulator",
("visionos", "") => "XROS",
("visionos", "sim") => "XRSimulator",
("watchos", "") => "WatchOS",
("watchos", "sim") => "WatchSimulator",
(Os::IOs, Env::MacAbi) => "MacOSX",
(Os::TvOs, Env::Unspecified) => "AppleTVOS",
(Os::TvOs, Env::Sim) => "AppleTVSimulator",
(Os::VisionOs, Env::Unspecified) => "XROS",
(Os::VisionOs, Env::Sim) => "XRSimulator",
(Os::WatchOs, Env::Unspecified) => "WatchOS",
(Os::WatchOs, Env::Sim) => "WatchSimulator",
(os, abi) => unreachable!("invalid os '{os}' / abi '{abi}' combination for Apple target"),
}
}
pub(super) fn macho_platform(target: &Target) -> u32 {
match (&*target.os, &*target.env) {
("macos", _) => object::macho::PLATFORM_MACOS,
("ios", "macabi") => object::macho::PLATFORM_MACCATALYST,
("ios", "sim") => object::macho::PLATFORM_IOSSIMULATOR,
("ios", _) => object::macho::PLATFORM_IOS,
("watchos", "sim") => object::macho::PLATFORM_WATCHOSSIMULATOR,
("watchos", _) => object::macho::PLATFORM_WATCHOS,
("tvos", "sim") => object::macho::PLATFORM_TVOSSIMULATOR,
("tvos", _) => object::macho::PLATFORM_TVOS,
("visionos", "sim") => object::macho::PLATFORM_XROSSIMULATOR,
("visionos", _) => object::macho::PLATFORM_XROS,
_ => unreachable!("tried to get Mach-O platform for non-Apple target"),
match (&target.os, &target.env) {
(Os::MacOs, _) => object::macho::PLATFORM_MACOS,
(Os::IOs, Env::MacAbi) => object::macho::PLATFORM_MACCATALYST,
(Os::IOs, Env::Sim) => object::macho::PLATFORM_IOSSIMULATOR,
(Os::IOs, _) => object::macho::PLATFORM_IOS,
(Os::WatchOs, Env::Sim) => object::macho::PLATFORM_WATCHOSSIMULATOR,
(Os::WatchOs, _) => object::macho::PLATFORM_WATCHOS,
(Os::TvOs, Env::Sim) => object::macho::PLATFORM_TVOSSIMULATOR,
(Os::TvOs, _) => object::macho::PLATFORM_TVOS,
(Os::VisionOs, Env::Sim) => object::macho::PLATFORM_XROSSIMULATOR,
(Os::VisionOs, _) => object::macho::PLATFORM_XROS,
(os, env) => unreachable!("invalid os '{os}' / env '{env}' combination for Apple target"),
}
}
+19 -21
View File
@@ -46,9 +46,9 @@
use rustc_span::Symbol;
use rustc_target::spec::crt_objects::CrtObjects;
use rustc_target::spec::{
BinaryFormat, Cc, LinkOutputKind, LinkSelfContainedComponents, LinkSelfContainedDefault,
LinkerFeatures, LinkerFlavor, LinkerFlavorCli, Lld, RelocModel, RelroLevel, SanitizerSet,
SplitDebuginfo,
Abi, BinaryFormat, Cc, Env, LinkOutputKind, LinkSelfContainedComponents,
LinkSelfContainedDefault, LinkerFeatures, LinkerFlavor, LinkerFlavorCli, Lld, Os, RelocModel,
RelroLevel, SanitizerSet, SplitDebuginfo,
};
use tracing::{debug, info, warn};
@@ -1407,11 +1407,9 @@ fn adjust_flavor_to_features(
Some(LinkerFlavorCli::Llbc) => Some(LinkerFlavor::Llbc),
Some(LinkerFlavorCli::Ptx) => Some(LinkerFlavor::Ptx),
// The linker flavors that corresponds to targets needs logic that keeps the base LinkerFlavor
_ => sess
.opts
.cg
.linker_flavor
.map(|flavor| sess.target.linker_flavor.with_cli_hints(flavor)),
linker_flavor => {
linker_flavor.map(|flavor| sess.target.linker_flavor.with_cli_hints(flavor))
}
};
if let Some(ret) = infer_from(sess, sess.opts.cg.linker.clone(), linker_flavor, features) {
return ret;
@@ -1819,7 +1817,7 @@ fn self_contained_components(
LinkSelfContainedDefault::InferredForMusl => sess.crt_static(Some(crate_type)),
LinkSelfContainedDefault::InferredForMingw => {
sess.host == sess.target
&& sess.target.vendor != "uwp"
&& sess.target.abi != Abi::Uwp
&& detect_self_contained_mingw(sess, linker)
}
}
@@ -1845,7 +1843,7 @@ fn add_pre_link_objects(
let empty = Default::default();
let objects = if self_contained {
&opts.pre_link_objects_self_contained
} else if !(sess.target.os == "fuchsia" && matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))) {
} else if !(sess.target.os == Os::Fuchsia && matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))) {
&opts.pre_link_objects
} else {
&empty
@@ -2496,7 +2494,7 @@ fn add_order_independent_options(
let apple_sdk_root = add_apple_sdk(cmd, sess, flavor);
if sess.target.os == "fuchsia"
if sess.target.os == Os::Fuchsia
&& crate_type == CrateType::Executable
&& !matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))
{
@@ -2515,7 +2513,7 @@ fn add_order_independent_options(
cmd.no_crt_objects();
}
if sess.target.os == "emscripten" {
if sess.target.os == Os::Emscripten {
cmd.cc_arg(if sess.opts.unstable_opts.emscripten_wasm_eh {
"-fwasm-exceptions"
} else if sess.panic_strategy().unwinds() {
@@ -3070,8 +3068,8 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo
// `sess.target.arch` (`target_arch`) is not detailed enough.
let llvm_arch = sess.target.llvm_target.split_once('-').expect("LLVM target must have arch").0;
let target_os = &*sess.target.os;
let target_env = &*sess.target.env;
let target_os = &sess.target.os;
let target_env = &sess.target.env;
// The architecture name to forward to the linker.
//
@@ -3123,12 +3121,12 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo
// > - xros-simulator
// > - driverkit
let platform_name = match (target_os, target_env) {
(os, "") => os,
("ios", "macabi") => "mac-catalyst",
("ios", "sim") => "ios-simulator",
("tvos", "sim") => "tvos-simulator",
("watchos", "sim") => "watchos-simulator",
("visionos", "sim") => "visionos-simulator",
(os, Env::Unspecified) => os.desc(),
(Os::IOs, Env::MacAbi) => "mac-catalyst",
(Os::IOs, Env::Sim) => "ios-simulator",
(Os::TvOs, Env::Sim) => "tvos-simulator",
(Os::WatchOs, Env::Sim) => "watchos-simulator",
(Os::VisionOs, Env::Sim) => "visionos-simulator",
_ => bug!("invalid OS/env combination for Apple target: {target_os}, {target_env}"),
};
@@ -3192,7 +3190,7 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo
// fairly safely use `-target`. See also the following, where it is
// made explicit that the recommendation by LLVM developers is to use
// `-target`: <https://github.com/llvm/llvm-project/issues/88271>
if target_os == "macos" {
if *target_os == Os::MacOs {
// `-arch` communicates the architecture.
//
// CC forwards the `-arch` to the linker, so we use the same value
@@ -17,7 +17,7 @@
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
use rustc_target::spec::{Arch, Cc, LinkOutputKind, LinkerFlavor, Lld};
use rustc_target::spec::{Abi, Arch, Cc, LinkOutputKind, LinkerFlavor, Lld, Os};
use tracing::{debug, warn};
use super::command::Command;
@@ -83,7 +83,7 @@ pub(crate) fn get_linker<'a>(
// To comply with the Windows App Certification Kit,
// MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc).
let t = &sess.target;
if matches!(flavor, LinkerFlavor::Msvc(..)) && t.vendor == "uwp" {
if matches!(flavor, LinkerFlavor::Msvc(..)) && t.abi == Abi::Uwp {
if let Some(ref tool) = msvc_tool {
let original_path = tool.path();
if let Some(root_lib_path) = original_path.ancestors().nth(4) {
@@ -134,12 +134,12 @@ pub(crate) fn get_linker<'a>(
// FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction
// to the linker args construction.
assert!(cmd.get_args().is_empty() || sess.target.vendor == "uwp");
assert!(cmd.get_args().is_empty() || sess.target.abi == Abi::Uwp);
match flavor {
LinkerFlavor::Unix(Cc::No) if sess.target.os == "l4re" => {
LinkerFlavor::Unix(Cc::No) if sess.target.os == Os::L4Re => {
Box::new(L4Bender::new(cmd, sess)) as Box<dyn Linker>
}
LinkerFlavor::Unix(Cc::No) if sess.target.os == "aix" => {
LinkerFlavor::Unix(Cc::No) if sess.target.os == Os::Aix => {
Box::new(AixLinker::new(cmd, sess)) as Box<dyn Linker>
}
LinkerFlavor::WasmLld(Cc::No) => Box::new(WasmLd::new(cmd, sess)) as Box<dyn Linker>,
@@ -573,7 +573,7 @@ fn set_output_kind(
// any `#[link]` attributes in the `libc` crate, see #72782 for details.
// FIXME: Switch to using `#[link]` attributes in the `libc` crate
// similarly to other targets.
if self.sess.target.os == "vxworks"
if self.sess.target.os == Os::VxWorks
&& matches!(
output_kind,
LinkOutputKind::StaticNoPicExe
@@ -595,7 +595,7 @@ fn set_output_kind(
}
fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, as_needed: bool) {
if self.sess.target.os == "illumos" && name == "c" {
if self.sess.target.os == Os::Illumos && name == "c" {
// libc will be added via late_link_args on illumos so that it will
// appear last in the library search order.
// FIXME: This should be replaced by a more complete and generic
@@ -1439,7 +1439,7 @@ fn export_symbols(
// symbols explicitly passed via the `--export` flags above and hides all
// others. Various bits and pieces of wasm32-unknown-unknown tooling use
// this, so be sure these symbols make their way out of the linker as well.
if self.sess.target.os == "unknown" || self.sess.target.os == "none" {
if matches!(self.sess.target.os, Os::Unknown | Os::None) {
self.link_args(&["--export=__heap_base", "--export=__data_end"]);
}
}
+10 -10
View File
@@ -20,7 +20,7 @@
use rustc_middle::bug;
use rustc_session::Session;
use rustc_span::sym;
use rustc_target::spec::{RelocModel, Target, ef_avr_arch};
use rustc_target::spec::{Abi, Os, RelocModel, Target, ef_avr_arch};
use tracing::debug;
use super::apple;
@@ -260,10 +260,10 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
}
pub(super) fn elf_os_abi(sess: &Session) -> u8 {
match sess.target.options.os.as_ref() {
"hermit" => elf::ELFOSABI_STANDALONE,
"freebsd" => elf::ELFOSABI_FREEBSD,
"solaris" => elf::ELFOSABI_SOLARIS,
match sess.target.options.os {
Os::Hermit => elf::ELFOSABI_STANDALONE,
Os::FreeBsd => elf::ELFOSABI_FREEBSD,
Os::Solaris => elf::ELFOSABI_SOLARIS,
_ => elf::ELFOSABI_NONE,
}
}
@@ -379,11 +379,11 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {
}
}
Architecture::Csky => {
let e_flags = match sess.target.options.abi.as_ref() {
"abiv2" => elf::EF_CSKY_ABIV2,
_ => elf::EF_CSKY_ABIV1,
};
e_flags
if matches!(sess.target.options.abi, Abi::AbiV2) {
elf::EF_CSKY_ABIV2
} else {
elf::EF_CSKY_ABIV1
}
}
Architecture::PowerPc64 => {
const EF_PPC64_ABI_UNKNOWN: u32 = 0;
@@ -17,7 +17,7 @@
use rustc_middle::util::Providers;
use rustc_session::config::{CrateType, OomStrategy};
use rustc_symbol_mangling::mangle_internal_symbol;
use rustc_target::spec::{Arch, TlsModel};
use rustc_target::spec::{Arch, Os, TlsModel};
use tracing::debug;
use crate::back::symbol_export;
@@ -711,7 +711,7 @@ pub(crate) fn extend_exported_symbols<'tcx>(
) {
let (callconv, _) = calling_convention_for_symbol(tcx, symbol);
if callconv != CanonAbi::GpuKernel || tcx.sess.target.os != "amdhsa" {
if callconv != CanonAbi::GpuKernel || tcx.sess.target.os != Os::AmdHsa {
return;
}
+5 -5
View File
@@ -33,7 +33,7 @@
use rustc_session::config::{self, CrateType, EntryFnType};
use rustc_span::{DUMMY_SP, Symbol, sym};
use rustc_symbol_mangling::mangle_internal_symbol;
use rustc_target::spec::Arch;
use rustc_target::spec::{Arch, Os};
use rustc_trait_selection::infer::{BoundRegionConversionTime, TyCtxtInferExt};
use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
use tracing::{debug, info};
@@ -366,7 +366,7 @@ pub(crate) fn build_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
// us
pub fn wants_wasm_eh(sess: &Session) -> bool {
sess.target.is_like_wasm
&& (sess.target.os != "emscripten" || sess.opts.unstable_opts.emscripten_wasm_eh)
&& (sess.target.os != Os::Emscripten || sess.opts.unstable_opts.emscripten_wasm_eh)
}
/// Returns `true` if this session's target will use SEH-based unwinding.
@@ -500,7 +500,7 @@ fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
) -> Bx::Function {
// The entry function is either `int main(void)` or `int main(int argc, char **argv)`, or
// `usize efi_main(void *handle, void *system_table)` depending on the target.
let llfty = if cx.sess().target.os.contains("uefi") {
let llfty = if cx.sess().target.os == Os::Uefi {
cx.type_func(&[cx.type_ptr(), cx.type_ptr()], cx.type_isize())
} else if cx.sess().target.main_needs_argc_argv {
cx.type_func(&[cx.type_int(), cx.type_ptr()], cx.type_int())
@@ -562,7 +562,7 @@ fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
};
let result = bx.call(start_ty, None, None, start_fn, &args, None, instance);
if cx.sess().target.os.contains("uefi") {
if cx.sess().target.os == Os::Uefi {
bx.ret(result);
} else {
let cast = bx.intcast(result, cx.type_int(), true);
@@ -576,7 +576,7 @@ fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
/// Obtain the `argc` and `argv` values to pass to the rust start function
/// (i.e., the "start" lang item).
fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(bx: &mut Bx) -> (Bx::Value, Bx::Value) {
if bx.cx().sess().target.os.contains("uefi") {
if bx.cx().sess().target.os == Os::Uefi {
// Params for UEFI
let param_handle = bx.get_param(0);
let param_system_table = bx.get_param(1);
@@ -16,6 +16,7 @@
use rustc_session::lint;
use rustc_session::parse::feature_err;
use rustc_span::{Ident, Span, sym};
use rustc_target::spec::Os;
use crate::errors;
use crate::target_features::{
@@ -258,7 +259,7 @@ fn process_builtin_attrs(
UsedBy::Compiler => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_COMPILER,
UsedBy::Linker => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER,
UsedBy::Default => {
let used_form = if tcx.sess.target.os == "illumos" {
let used_form = if tcx.sess.target.os == Os::Illumos {
// illumos' `ld` doesn't support a section header that would represent
// `#[used(linker)]`, see
// https://github.com/rust-lang/rust/issues/146169. For that target,
@@ -468,16 +469,18 @@ fn check_result(
})
}
// warn for nonblocking async fn.
// warn for nonblocking async functions, blocks and closures.
// This doesn't behave as expected, because the executor can run blocking code without the sanitizer noticing.
if codegen_fn_attrs.sanitizers.rtsan_setting == RtsanSetting::Nonblocking
&& let Some(sanitize_span) = interesting_spans.sanitize
// async function
&& (tcx.asyncness(did).is_async() || (tcx.is_closure_like(did.into())
// async fn
&& (tcx.asyncness(did).is_async()
// async block
&& (tcx.coroutine_is_async(did.into())
// async closure
|| tcx.coroutine_is_async(tcx.coroutine_for_closure(did)))))
|| tcx.is_coroutine(did.into())
// async closure
|| (tcx.is_closure_like(did.into())
&& tcx.hir_node_by_def_id(did).expect_closure().kind
!= rustc_hir::ClosureKind::Closure))
{
let hir_id = tcx.local_def_id_to_hir_id(did);
tcx.node_span_lint(
+2 -2
View File
@@ -7,7 +7,7 @@
use rustc_middle::{bug, mir, span_bug};
use rustc_session::cstore::{DllCallingConvention, DllImport};
use rustc_span::Span;
use rustc_target::spec::Target;
use rustc_target::spec::{Abi, Env, Os, Target};
use crate::traits::*;
@@ -171,7 +171,7 @@ pub fn asm_const_to_str<'tcx>(
}
pub fn is_mingw_gnu_toolchain(target: &Target) -> bool {
target.vendor == "pc" && target.os == "windows" && target.env == "gnu" && target.abi.is_empty()
target.os == Os::Windows && target.env == Env::Gnu && target.abi == Abi::Unspecified
}
pub fn i686_decorated_name(
@@ -1498,14 +1498,10 @@ pub fn mem_copy_repeatedly(
// Prepare getting source provenance.
let src_bytes = src_alloc.get_bytes_unchecked(src_range).as_ptr(); // raw ptr, so we can also get a ptr to the destination allocation
// first copy the provenance to a temporary buffer, because
// `get_bytes_mut` will clear the provenance, which is correct,
// since we don't want to keep any provenance at the target.
// This will also error if copying partial provenance is not supported.
let provenance = src_alloc
.provenance()
.prepare_copy(src_range, self)
.map_err(|e| e.to_interp_error(src_alloc_id))?;
// First copy the provenance to a temporary buffer, because
// `get_bytes_unchecked_for_overwrite_ptr` will clear the provenance (in preparation for
// inserting the new provenance), and that can overlap with the source range.
let provenance = src_alloc.provenance_prepare_copy(src_range, self);
// Prepare a copy of the initialization mask.
let init = src_alloc.init_mask().prepare_copy(src_range);
@@ -704,6 +704,7 @@ fn write_immediate_to_mplace_no_validate(
// wrong type.
let tcx = *self.tcx;
let will_later_validate = M::enforce_validity(self, layout);
let Some(mut alloc) = self.get_place_alloc_mut(&MPlaceTy { mplace: dest, layout })? else {
// zero-sized access
return interp_ok(());
@@ -714,23 +715,31 @@ fn write_immediate_to_mplace_no_validate(
alloc.write_scalar(alloc_range(Size::ZERO, scalar.size()), scalar)?;
}
Immediate::ScalarPair(a_val, b_val) => {
let BackendRepr::ScalarPair(a, b) = layout.backend_repr else {
let BackendRepr::ScalarPair(_a, b) = layout.backend_repr else {
span_bug!(
self.cur_span(),
"write_immediate_to_mplace: invalid ScalarPair layout: {:#?}",
layout
)
};
let b_offset = a.size(&tcx).align_to(b.align(&tcx).abi);
let a_size = a_val.size();
let b_offset = a_size.align_to(b.align(&tcx).abi);
assert!(b_offset.bytes() > 0); // in `operand_field` we use the offset to tell apart the fields
// It is tempting to verify `b_offset` against `layout.fields.offset(1)`,
// but that does not work: We could be a newtype around a pair, then the
// fields do not match the `ScalarPair` components.
alloc.write_scalar(alloc_range(Size::ZERO, a_val.size()), a_val)?;
// In preparation, if we do *not* later reset the padding, we clear the entire
// destination now to ensure that no stray pointer fragments are being
// preserved (see <https://github.com/rust-lang/rust/issues/148470>).
// We can skip this if there is no padding (e.g. for wide pointers).
if !will_later_validate && a_size + b_val.size() != layout.size {
alloc.write_uninit_full();
}
alloc.write_scalar(alloc_range(Size::ZERO, a_size), a_val)?;
alloc.write_scalar(alloc_range(b_offset, b_val.size()), b_val)?;
// We don't have to reset padding here, `write_immediate` will anyway do a validation run.
}
Immediate::Uninit => alloc.write_uninit_full(),
}
+4 -4
View File
@@ -53,13 +53,13 @@ impl !DynSend for std::env::VarsOs {}
macro_rules! already_send {
($([$ty: ty])*) => {
$(unsafe impl DynSend for $ty where $ty: Send {})*
$(unsafe impl DynSend for $ty where Self: Send {})*
};
}
// These structures are already `Send`.
already_send!(
[std::backtrace::Backtrace][std::io::Stdout][std::io::Stderr][std::io::Error][std::fs::File]
[std::backtrace::Backtrace][std::io::Stdout][std::io::Stderr][std::io::Error][std::fs::File][std::panic::Location<'_>]
[rustc_arena::DroplessArena][jobserver_crate::Client][jobserver_crate::HelperThread]
[crate::memmap::Mmap][crate::profiling::SelfProfiler][crate::owned_slice::OwnedSlice]
);
@@ -127,14 +127,14 @@ impl !DynSync for std::env::VarsOs {}
macro_rules! already_sync {
($([$ty: ty])*) => {
$(unsafe impl DynSync for $ty where $ty: Sync {})*
$(unsafe impl DynSync for $ty where Self: Sync {})*
};
}
// These structures are already `Sync`.
already_sync!(
[std::sync::atomic::AtomicBool][std::sync::atomic::AtomicUsize][std::sync::atomic::AtomicU8]
[std::sync::atomic::AtomicU32][std::backtrace::Backtrace][std::io::Error][std::fs::File]
[std::sync::atomic::AtomicU32][std::backtrace::Backtrace][std::io::Error][std::fs::File][std::panic::Location<'_>]
[jobserver_crate::Client][jobserver_crate::HelperThread][crate::memmap::Mmap]
[crate::profiling::SelfProfiler][crate::owned_slice::OwnedSlice]
);
+11 -3
View File
@@ -1,5 +1,5 @@
use crate::stable_hasher::{HashStable, StableHasher};
use crate::sync::{MappedReadGuard, ReadGuard, RwLock};
use crate::sync::{MappedReadGuard, MappedWriteGuard, ReadGuard, RwLock, WriteGuard};
/// The `Steal` struct is intended to used as the value for a query.
/// Specifically, we sometimes have queries (*cough* MIR *cough*)
@@ -40,9 +40,17 @@ pub fn borrow(&self) -> MappedReadGuard<'_, T> {
ReadGuard::map(borrow, |opt| opt.as_ref().unwrap())
}
/// An escape hatch for rustc drivers to mutate `Steal` caches.
///
/// Use at your own risk. This can badly break incremental compilation
/// and anything else that relies on the immutability of query caches.
#[track_caller]
pub fn get_mut(&mut self) -> &mut T {
self.value.get_mut().as_mut().expect("attempt to read from stolen value")
pub fn risky_hack_borrow_mut(&self) -> MappedWriteGuard<'_, T> {
let borrow = self.value.borrow_mut();
if borrow.is_none() {
panic!("attempted to read from stolen value: {}", std::any::type_name::<T>());
}
WriteGuard::map(borrow, |opt| opt.as_mut().unwrap())
}
#[track_caller]
@@ -152,7 +152,8 @@ pub(super) fn install() {
libc::sigaltstack(&alt_stack, ptr::null_mut());
let mut sa: libc::sigaction = mem::zeroed();
sa.sa_sigaction = print_stack_trace as libc::sighandler_t;
sa.sa_sigaction =
print_stack_trace as unsafe extern "C" fn(libc::c_int) as libc::sighandler_t;
sa.sa_flags = libc::SA_NODEFER | libc::SA_RESETHAND | libc::SA_ONSTACK;
libc::sigemptyset(&mut sa.sa_mask);
for (signum, _signame) in KILL_SIGNALS {
+1 -1
View File
@@ -5,7 +5,7 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
annotate-snippets = "0.12.8"
annotate-snippets = "0.12.9"
anstream = "0.6.20"
anstyle = "1.0.13"
derive_setters = "0.1.6"
@@ -350,22 +350,27 @@ fn emit_messages_default(
"all spans must be disjoint",
);
let lo = subst.parts.iter().map(|part| part.span.lo()).min()?;
let lo_file = sm.lookup_source_file(lo);
let hi = subst.parts.iter().map(|part| part.span.hi()).max()?;
let hi_file = sm.lookup_source_file(hi);
// The different spans might belong to different contexts, if so ignore suggestion.
if lo_file.stable_id != hi_file.stable_id {
return None;
}
// We can't splice anything if the source is unavailable.
if !sm.ensure_source_file_source_present(&lo_file) {
return None;
}
// Account for cases where we are suggesting the same code that's already
// there. This shouldn't happen often, but in some cases for multipart
// suggestions it's much easier to handle it here than in the origin.
subst.parts.retain(|p| is_different(sm, &p.snippet, p.span));
let item_span = subst.parts.first()?;
let file = sm.lookup_source_file(item_span.span.lo());
if should_show_source_code(
&self.ignored_directories_in_source_blocks,
sm,
&file,
) {
Some(subst)
} else {
None
}
if subst.parts.is_empty() { None } else { Some(subst) }
})
.collect::<Vec<_>>();
@@ -745,14 +750,20 @@ fn shrink_file(
) -> Option<(Span, String, usize)> {
let lo_byte = spans.iter().map(|s| s.lo()).min()?;
let lo_loc = sm.lookup_char_pos(lo_byte);
let lo = lo_loc.file.line_bounds(lo_loc.line.saturating_sub(1)).start;
let hi_byte = spans.iter().map(|s| s.hi()).max()?;
let hi_loc = sm.lookup_char_pos(hi_byte);
let hi = lo_loc.file.line_bounds(hi_loc.line.saturating_sub(1)).end;
if lo_loc.file.stable_id != hi_loc.file.stable_id {
// this may happen when spans cross file boundaries due to macro expansion.
return None;
}
let lo = lo_loc.file.line_bounds(lo_loc.line.saturating_sub(1)).start;
let hi = hi_loc.file.line_bounds(hi_loc.line.saturating_sub(1)).end;
let bounding_span = Span::with_root_ctxt(lo, hi);
let source = sm.span_to_snippet(bounding_span).unwrap_or_default();
let source = sm.span_to_snippet(bounding_span).ok()?;
let offset_line = sm.doctest_offset_line(file_name, lo_loc.line);
Some((bounding_span, source, offset_line))
+9 -14
View File
@@ -1704,7 +1704,7 @@ fn emit_messages_default_inner(
}
// print out the span location and spacer before we print the annotated source
// to do this, we need to know if this span will be primary
let is_primary = primary_lo.file.name == annotated_file.file.name;
let is_primary = primary_lo.file.stable_id == annotated_file.file.stable_id;
if is_primary {
let loc = primary_lo.clone();
if !self.short_message {
@@ -2322,11 +2322,6 @@ fn emit_suggestion_default(
show_code_change
{
for part in parts {
let snippet = if let Ok(snippet) = sm.span_to_snippet(part.span) {
snippet
} else {
String::new()
};
let span_start_pos = sm.lookup_char_pos(part.span.lo()).col_display;
let span_end_pos = sm.lookup_char_pos(part.span.hi()).col_display;
@@ -2402,7 +2397,7 @@ fn emit_suggestion_default(
// LL - REMOVED <- row_num - 2 - (newlines - first_i - 1)
// LL + NEWER
// | <- row_num
let snippet = sm.span_to_snippet(part.span).unwrap_or_default();
let newlines = snippet.lines().count();
if newlines > 0 && row_num > newlines {
// Account for removals where the part being removed spans multiple
@@ -3108,7 +3103,7 @@ fn add_annotation_to_file(
) {
for slot in file_vec.iter_mut() {
// Look through each of our files for the one we're adding to
if slot.file.name == file.name {
if slot.file.stable_id == file.stable_id {
// See if we already have a line for it
for line_slot in &mut slot.lines {
if line_slot.line_index == line_index {
@@ -3471,14 +3466,9 @@ fn drop(&mut self) {
pub fn stderr_destination(color: ColorConfig) -> Destination {
let buffer_writer = std::io::stderr();
let choice = color.to_color_choice();
// We need to resolve `ColorChoice::Auto` before `Box`ing since
// `ColorChoice::Auto` on `dyn Write` will always resolve to `Never`
let choice = if matches!(choice, ColorChoice::Auto) {
AutoStream::choice(&buffer_writer)
} else {
choice
};
let choice = get_stderr_color_choice(color, &buffer_writer);
// On Windows we'll be performing global synchronization on the entire
// system for emitting rustc errors, so there's no need to buffer
// anything.
@@ -3493,6 +3483,11 @@ pub fn stderr_destination(color: ColorConfig) -> Destination {
}
}
pub fn get_stderr_color_choice(color: ColorConfig, stderr: &std::io::Stderr) -> ColorChoice {
let choice = color.to_color_choice();
if matches!(choice, ColorChoice::Auto) { AutoStream::choice(stderr) } else { choice }
}
/// On Windows, BRIGHT_BLUE is hard to read on black. Use cyan instead.
///
/// See #36178.
+3
View File
@@ -1099,6 +1099,9 @@ pub fn expn_data(
pub struct DeriveResolution {
pub path: ast::Path,
pub item: Annotatable,
// FIXME: currently this field is only used in `is_none`/`is_some` conditions. However, the
// `Arc<SyntaxExtension>` will be used if the FIXME in `MacroExpander::fully_expand_fragment`
// is completed.
pub exts: Option<Arc<SyntaxExtension>>,
pub is_const: bool,
}
-3
View File
@@ -886,9 +886,6 @@ fn expand_invoc(
}
}
} else if let SyntaxExtensionKind::NonMacroAttr = ext {
if let ast::Safety::Unsafe(span) = attr.get_normal_item().unsafety {
self.cx.dcx().span_err(span, "unnecessary `unsafe` on safe attribute");
}
// `-Zmacro-stats` ignores these because they don't do any real expansion.
self.cx.expanded_inert_attrs.mark(&attr);
item.visit_attrs(|attrs| attrs.insert(pos, attr));
@@ -749,7 +749,7 @@ fn join(&mut self, first: Self::Span, second: Self::Span) -> Option<Self::Span>
let self_loc = self.psess().source_map().lookup_char_pos(first.lo());
let other_loc = self.psess().source_map().lookup_char_pos(second.lo());
if self_loc.file.name != other_loc.file.name {
if self_loc.file.stable_id != other_loc.file.stable_id {
return None;
}
+2
View File
@@ -215,6 +215,8 @@ macro_rules! declare_features {
(accepted, extern_crate_self, "1.34.0", Some(56409)),
/// Allows access to crate names passed via `--extern` through prelude.
(accepted, extern_prelude, "1.30.0", Some(44660)),
/// Allows using `system` as a calling convention with varargs.
(accepted, extern_system_varargs, "CURRENT_RUSTC_VERSION", Some(136946)),
/// Allows using F16C intrinsics from `core::arch::{x86, x86_64}`.
(accepted, f16c_target_feature, "1.68.0", Some(44839)),
/// Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
+3 -2
View File
@@ -410,6 +410,9 @@ pub fn internal(&self, feature: Symbol) -> bool {
(unstable, avx10_target_feature, "1.88.0", Some(138843)),
/// Allows using C-variadics.
(unstable, c_variadic, "1.34.0", Some(44930)),
/// Allows defining c-variadic naked functions with any extern ABI that is allowed
/// on c-variadic foreign functions.
(unstable, c_variadic_naked_functions, "CURRENT_RUSTC_VERSION", Some(148767)),
/// Allows the use of `#[cfg(contract_checks)` to check if contract checks are enabled.
(unstable, cfg_contract_checks, "1.86.0", Some(128044)),
/// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour.
@@ -498,8 +501,6 @@ pub fn internal(&self, feature: Symbol) -> bool {
(incomplete, explicit_tail_calls, "1.72.0", Some(112788)),
/// Allows using `#[export_stable]` which indicates that an item is exportable.
(incomplete, export_stable, "1.88.0", Some(139939)),
/// Allows using `system` as a calling convention with varargs.
(unstable, extern_system_varargs, "1.86.0", Some(136946)),
/// Allows defining `extern type`s.
(unstable, extern_types, "1.23.0", Some(43467)),
/// Allow using 128-bit (quad precision) floating point numbers.

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