From 0899efe363292f786e67c978ec77439c437d0e74 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Mon, 4 Dec 2023 15:52:26 +0000 Subject: [PATCH 01/15] [DO NOT MERGE] update target feature following LLVM API change LLVM commit https://github.com/llvm/llvm-project/commit/e81796671890b59c110f8e41adc7ca26f8484d20 renamed the `unaligned-scalar-mem` target feature to `fast-unaligned-access`. --- compiler/rustc_codegen_ssa/src/target_features.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index d802816bb7561..c3b8859c77968 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -291,9 +291,9 @@ const RISCV_ALLOWED_FEATURES: &[(&str, Stability)] = &[ ("d", Unstable(sym::riscv_target_feature)), ("e", Unstable(sym::riscv_target_feature)), ("f", Unstable(sym::riscv_target_feature)), + ("fast-unaligned-access", Unstable(sym::riscv_target_feature)), ("m", Stable), ("relax", Unstable(sym::riscv_target_feature)), - ("unaligned-scalar-mem", Unstable(sym::riscv_target_feature)), ("v", Unstable(sym::riscv_target_feature)), ("zba", Stable), ("zbb", Stable), From 43baf5dc1fa6758c0268e30530d821d8b36fee07 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Mon, 4 Dec 2023 15:52:26 +0000 Subject: [PATCH 02/15] [DO NOT MERGE] update target feature following LLVM API change LLVM commit https://github.com/llvm/llvm-project/commit/e81796671890b59c110f8e41adc7ca26f8484d20 renamed the `unaligned-scalar-mem` target feature to `fast-unaligned-access`. --- tests/ui/abi/riscv-discoverability-guidance.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/abi/riscv-discoverability-guidance.rs b/tests/ui/abi/riscv-discoverability-guidance.rs index f57fcd6044ffa..361ed8f3d9106 100644 --- a/tests/ui/abi/riscv-discoverability-guidance.rs +++ b/tests/ui/abi/riscv-discoverability-guidance.rs @@ -2,9 +2,9 @@ // revisions: riscv32 riscv64 // // [riscv32] needs-llvm-components: riscv -// [riscv32] compile-flags: --target=riscv32i-unknown-none-elf -C target-feature=-unaligned-scalar-mem --crate-type=rlib +// [riscv32] compile-flags: --target=riscv32i-unknown-none-elf -C target-feature=-fast-unaligned-access --crate-type=rlib // [riscv64] needs-llvm-components: riscv -// [riscv64] compile-flags: --target=riscv64gc-unknown-none-elf -C target-feature=-unaligned-scalar-mem --crate-type=rlib +// [riscv64] compile-flags: --target=riscv64gc-unknown-none-elf -C target-feature=-fast-unaligned-access --crate-type=rlib #![no_core] #![feature( no_core, From 4ac32747ba280faa5cea05ad3f54a31c03257171 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Wed, 6 Dec 2023 12:43:46 +0000 Subject: [PATCH 03/15] adapt llvm_util for the rename --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index eb69efb0d5952..db9a774ac5f6a 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -263,6 +263,10 @@ pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> LLVMFeature<'a> { "sve2-bitperm", TargetFeatureFoldStrength::EnableOnly("neon"), ), + // The unaligned-scalar-mem feature was renamed to fast-unaligned-access. + ("riscv32" | "riscv64", "fast-unaligned-access") if get_version().0 <= 18 => { + LLVMFeature::new("unaligned-scalar-mem") + } (_, s) => LLVMFeature::new(s), } } From 01046205f3970e7ce111c9a0d63ed512c5a354d5 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Wed, 6 Dec 2023 17:30:27 +0000 Subject: [PATCH 04/15] update llvm version --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index db9a774ac5f6a..93cb7327a017e 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -264,7 +264,7 @@ pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> LLVMFeature<'a> { TargetFeatureFoldStrength::EnableOnly("neon"), ), // The unaligned-scalar-mem feature was renamed to fast-unaligned-access. - ("riscv32" | "riscv64", "fast-unaligned-access") if get_version().0 <= 18 => { + ("riscv32" | "riscv64", "fast-unaligned-access") if get_version().0 <= 17 => { LLVMFeature::new("unaligned-scalar-mem") } (_, s) => LLVMFeature::new(s), From 5d3a294b46896d0b0c7c2cb3cf6ce4085a1e64fe Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 6 Dec 2023 20:22:33 +0000 Subject: [PATCH 05/15] Only check principal trait ref for object safety --- compiler/rustc_trait_selection/src/traits/wf.rs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 3a890d70d79b3..0f8d9c6bf4bdb 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -761,18 +761,15 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let defer_to_coercion = self.tcx().features().object_safe_for_dispatch; if !defer_to_coercion { - let cause = self.cause(traits::WellFormed(None)); - let component_traits = data.auto_traits().chain(data.principal_def_id()); - let tcx = self.tcx(); - self.out.extend(component_traits.map(|did| { - traits::Obligation::with_depth( - tcx, - cause.clone(), + if let Some(principal) = data.principal_def_id() { + self.out.push(traits::Obligation::with_depth( + self.tcx(), + self.cause(traits::WellFormed(None)), depth, param_env, - ty::Binder::dummy(ty::PredicateKind::ObjectSafe(did)), - ) - })); + ty::Binder::dummy(ty::PredicateKind::ObjectSafe(principal)), + )); + } } } From 281b65aad94cb81b56b2e03359d19d90200fa3ee Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Wed, 6 Dec 2023 13:45:07 -0800 Subject: [PATCH 06/15] Add method to get type of an Rvalue in StableMIR --- compiler/rustc_smir/src/rustc_smir/context.rs | 14 +++ compiler/stable_mir/src/compiler_interface.rs | 6 ++ compiler/stable_mir/src/mir/body.rs | 94 +++++++++++++++++++ compiler/stable_mir/src/mir/mono.rs | 15 +++ compiler/stable_mir/src/ty.rs | 48 ++++++++++ 5 files changed, 177 insertions(+) diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index 93d49038fc1c7..8bad2f3528a89 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -250,6 +250,13 @@ impl<'tcx> Context for TablesWrapper<'tcx> { tables.tcx.mk_ty_from_kind(internal_kind).stable(&mut *tables) } + #[allow(rustc::usage_of_qualified_ty)] + fn new_box_ty(&self, ty: stable_mir::ty::Ty) -> stable_mir::ty::Ty { + let mut tables = self.0.borrow_mut(); + let inner = ty.internal(&mut *tables); + ty::Ty::new_box(tables.tcx, inner).stable(&mut *tables) + } + fn def_ty(&self, item: stable_mir::DefId) -> stable_mir::ty::Ty { let mut tables = self.0.borrow_mut(); tables.tcx.type_of(item.internal(&mut *tables)).instantiate_identity().stable(&mut *tables) @@ -276,6 +283,13 @@ impl<'tcx> Context for TablesWrapper<'tcx> { tables.types[ty].kind().stable(&mut *tables) } + fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> stable_mir::ty::Ty { + let mut tables = self.0.borrow_mut(); + let internal_kind = ty.internal(&mut *tables); + let internal_ty = tables.tcx.mk_ty_from_kind(internal_kind); + internal_ty.discriminant_ty(tables.tcx).stable(&mut *tables) + } + fn instance_body(&self, def: InstanceDef) -> Option { let mut tables = self.0.borrow_mut(); let instance = tables.instances[def]; diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs index d8a3d4eda4be3..228ad5621671d 100644 --- a/compiler/stable_mir/src/compiler_interface.rs +++ b/compiler/stable_mir/src/compiler_interface.rs @@ -87,6 +87,9 @@ pub trait Context { /// Create a new type from the given kind. fn new_rigid_ty(&self, kind: RigidTy) -> Ty; + /// Create a new box type, `Box`, for the given inner type `T`. + fn new_box_ty(&self, ty: Ty) -> Ty; + /// Returns the type of given crate item. fn def_ty(&self, item: DefId) -> Ty; @@ -102,6 +105,9 @@ pub trait Context { /// Obtain the representation of a type. fn ty_kind(&self, ty: Ty) -> TyKind; + // Get the discriminant Ty for this Ty if there's one. + fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> Ty; + /// Get the body of an Instance which is already monomorphized. fn instance_body(&self, instance: InstanceDef) -> Option; diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 6f131cc4f0334..cbd9de33b6e24 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -274,6 +274,32 @@ pub enum BinOp { Offset, } +impl BinOp { + /// Return the type of this operation for the given input Ty. + /// This function does not perform type checking, and it currently doesn't handle SIMD. + pub fn ty(&self, lhs_ty: Ty, _rhs_ty: Ty) -> Ty { + match self { + BinOp::Add + | BinOp::AddUnchecked + | BinOp::Sub + | BinOp::SubUnchecked + | BinOp::Mul + | BinOp::MulUnchecked + | BinOp::Div + | BinOp::Rem + | BinOp::BitXor + | BinOp::BitAnd + | BinOp::BitOr + | BinOp::Shl + | BinOp::ShlUnchecked + | BinOp::Shr + | BinOp::ShrUnchecked + | BinOp::Offset => lhs_ty, + BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt => Ty::bool_ty(), + } + } +} + #[derive(Clone, Debug, Eq, PartialEq)] pub enum UnOp { Not, @@ -475,6 +501,63 @@ pub enum Rvalue { Use(Operand), } +impl Rvalue { + pub fn ty(&self, locals: &[LocalDecl]) -> Result { + match self { + Rvalue::Use(operand) => operand.ty(locals), + Rvalue::Repeat(operand, count) => { + Ok(Ty::new_array_with_const_len(operand.ty(locals)?, count.clone())) + } + Rvalue::ThreadLocalRef(did) => Ok(did.ty()), + Rvalue::Ref(reg, bk, place) => { + let place_ty = place.ty(locals)?; + Ok(Ty::new_ref(reg.clone(), place_ty, bk.to_mutable_lossy())) + } + Rvalue::AddressOf(mutability, place) => { + let place_ty = place.ty(locals)?; + Ok(Ty::new_ptr(place_ty, *mutability)) + } + Rvalue::Len(..) => Ok(Ty::usize_ty()), + Rvalue::Cast(.., ty) => Ok(*ty), + Rvalue::BinaryOp(op, lhs, rhs) => { + let lhs_ty = lhs.ty(locals)?; + let rhs_ty = rhs.ty(locals)?; + Ok(op.ty(lhs_ty, rhs_ty)) + } + Rvalue::CheckedBinaryOp(op, lhs, rhs) => { + let lhs_ty = lhs.ty(locals)?; + let rhs_ty = rhs.ty(locals)?; + let ty = op.ty(lhs_ty, rhs_ty); + Ok(Ty::new_tuple(&[ty, Ty::bool_ty()])) + } + Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, operand) => operand.ty(locals), + Rvalue::Discriminant(place) => { + let place_ty = place.ty(locals)?; + place_ty + .kind() + .discriminant_ty() + .ok_or_else(|| error!("Expected a `RigidTy` but found: {place_ty:?}")) + } + Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => { + Ok(Ty::usize_ty()) + } + Rvalue::Aggregate(ak, ops) => match *ak { + AggregateKind::Array(ty) => Ty::try_new_array(ty, ops.len() as u64), + AggregateKind::Tuple => Ok(Ty::new_tuple( + &ops.iter().map(|op| op.ty(locals)).collect::, _>>()?, + )), + AggregateKind::Adt(def, _, ref args, _, _) => Ok(def.ty_with_args(args)), + AggregateKind::Closure(def, ref args) => Ok(Ty::new_closure(def, args.clone())), + AggregateKind::Coroutine(def, ref args, mov) => { + Ok(Ty::new_coroutine(def, args.clone(), mov)) + } + }, + Rvalue::ShallowInitBox(_, ty) => Ok(Ty::new_box(*ty)), + Rvalue::CopyForDeref(place) => place.ty(locals), + } + } +} + #[derive(Clone, Debug, Eq, PartialEq)] pub enum AggregateKind { Array(Ty), @@ -725,6 +808,17 @@ pub enum BorrowKind { }, } +impl BorrowKind { + pub fn to_mutable_lossy(self) -> Mutability { + match self { + BorrowKind::Mut { .. } => Mutability::Mut, + BorrowKind::Shared => Mutability::Not, + // There's no type corresponding to a shallow borrow, so use `&` as an approximation. + BorrowKind::Fake => Mutability::Not, + } + } +} + #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum MutBorrowKind { Default, diff --git a/compiler/stable_mir/src/mir/mono.rs b/compiler/stable_mir/src/mir/mono.rs index 10270c82e6323..09683a7213b36 100644 --- a/compiler/stable_mir/src/mir/mono.rs +++ b/compiler/stable_mir/src/mir/mono.rs @@ -212,6 +212,21 @@ impl TryFrom for StaticDef { } } +impl TryFrom for StaticDef { + type Error = crate::Error; + + fn try_from(value: Instance) -> Result { + StaticDef::try_from(CrateItem::try_from(value)?) + } +} + +impl From for Instance { + fn from(value: StaticDef) -> Self { + // A static definition should always be convertible to an instance. + Instance::try_from(CrateItem::from(value)).unwrap() + } +} + impl StaticDef { /// Return the type of this static definition. pub fn ty(&self) -> Ty { diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index f64b1f5f5a355..c7405c7f58230 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -31,15 +31,50 @@ impl Ty { Ok(Ty::from_rigid_kind(RigidTy::Array(elem_ty, Const::try_from_target_usize(size)?))) } + /// Create a new array type from Const length. + pub fn new_array_with_const_len(elem_ty: Ty, len: Const) -> Ty { + Ty::from_rigid_kind(RigidTy::Array(elem_ty, len)) + } + /// Create a new pointer type. pub fn new_ptr(pointee_ty: Ty, mutability: Mutability) -> Ty { Ty::from_rigid_kind(RigidTy::RawPtr(pointee_ty, mutability)) } + /// Create a new reference type. + pub fn new_ref(reg: Region, pointee_ty: Ty, mutability: Mutability) -> Ty { + Ty::from_rigid_kind(RigidTy::Ref(reg, pointee_ty, mutability)) + } + + /// Create a new pointer type. + pub fn new_tuple(tys: &[Ty]) -> Ty { + Ty::from_rigid_kind(RigidTy::Tuple(Vec::from(tys))) + } + + /// Create a new closure type. + pub fn new_closure(def: ClosureDef, args: GenericArgs) -> Ty { + Ty::from_rigid_kind(RigidTy::Closure(def, args)) + } + + /// Create a new coroutine type. + pub fn new_coroutine(def: CoroutineDef, args: GenericArgs, mov: Movability) -> Ty { + Ty::from_rigid_kind(RigidTy::Coroutine(def, args, mov)) + } + + /// Create a new box type that represents `Box`, for the given inner type `T`. + pub fn new_box(inner_ty: Ty) -> Ty { + with(|cx| cx.new_box_ty(inner_ty)) + } + /// Create a type representing `usize`. pub fn usize_ty() -> Ty { Ty::from_rigid_kind(RigidTy::Uint(UintTy::Usize)) } + + /// Create a type representing `bool`. + pub fn bool_ty() -> Ty { + Ty::from_rigid_kind(RigidTy::Bool) + } } impl Ty { @@ -251,6 +286,7 @@ impl TyKind { } /// Get the function signature for function like types (Fn, FnPtr, Closure, Coroutine) + /// FIXME(closure) pub fn fn_sig(&self) -> Option { match self { TyKind::RigidTy(RigidTy::FnDef(def, args)) => Some(with(|cx| cx.fn_sig(*def, args))), @@ -258,6 +294,11 @@ impl TyKind { _ => None, } } + + /// Get the discriminant type for this type. + pub fn discriminant_ty(&self) -> Option { + self.rigid().map(|ty| with(|cx| cx.rigid_ty_discriminant_ty(ty))) + } } pub struct TypeAndMut { @@ -289,6 +330,13 @@ pub enum RigidTy { CoroutineWitness(CoroutineWitnessDef, GenericArgs), } +impl RigidTy { + /// Get the discriminant type for this type. + pub fn discriminant_ty(&self) -> Ty { + with(|cx| cx.rigid_ty_discriminant_ty(self)) + } +} + impl From for TyKind { fn from(value: RigidTy) -> Self { TyKind::RigidTy(value) From e16ebdbb069e2901b0a1241b9122ce61ab7d4dd1 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Wed, 6 Dec 2023 15:08:08 -0800 Subject: [PATCH 07/15] Simplify StaticDef to Instance conversion --- compiler/rustc_smir/src/rustc_smir/context.rs | 4 ++-- compiler/stable_mir/src/compiler_interface.rs | 2 +- compiler/stable_mir/src/mir/mono.rs | 7 ++++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index 8bad2f3528a89..50aada58bacd3 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -322,9 +322,9 @@ impl<'tcx> Context for TablesWrapper<'tcx> { matches!(instance.def, ty::InstanceDef::DropGlue(_, None)) } - fn mono_instance(&self, item: stable_mir::CrateItem) -> stable_mir::mir::mono::Instance { + fn mono_instance(&self, def_id: stable_mir::DefId) -> stable_mir::mir::mono::Instance { let mut tables = self.0.borrow_mut(); - let def_id = tables[item.0]; + let def_id = tables[def_id]; Instance::mono(tables.tcx, def_id).stable(&mut *tables) } diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs index 228ad5621671d..edf88216d42c4 100644 --- a/compiler/stable_mir/src/compiler_interface.rs +++ b/compiler/stable_mir/src/compiler_interface.rs @@ -125,7 +125,7 @@ pub trait Context { /// Convert a non-generic crate item into an instance. /// This function will panic if the item is generic. - fn mono_instance(&self, item: CrateItem) -> Instance; + fn mono_instance(&self, def_id: DefId) -> Instance; /// Item requires monomorphization. fn requires_monomorphization(&self, def_id: DefId) -> bool; diff --git a/compiler/stable_mir/src/mir/mono.rs b/compiler/stable_mir/src/mir/mono.rs index 09683a7213b36..06f78eb245a45 100644 --- a/compiler/stable_mir/src/mir/mono.rs +++ b/compiler/stable_mir/src/mir/mono.rs @@ -143,8 +143,9 @@ impl TryFrom for Instance { fn try_from(item: CrateItem) -> Result { with(|context| { - if !context.requires_monomorphization(item.0) { - Ok(context.mono_instance(item)) + let def_id = item.def_id(); + if !context.requires_monomorphization(def_id) { + Ok(context.mono_instance(def_id)) } else { Err(Error::new("Item requires monomorphization".to_string())) } @@ -223,7 +224,7 @@ impl TryFrom for StaticDef { impl From for Instance { fn from(value: StaticDef) -> Self { // A static definition should always be convertible to an instance. - Instance::try_from(CrateItem::from(value)).unwrap() + with(|cx| cx.mono_instance(value.def_id())) } } From 77d7e44573c8208e7b629c3d78a81cfae146732f Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Wed, 6 Dec 2023 17:48:38 -0800 Subject: [PATCH 08/15] Update compiler/stable_mir/src/mir/body.rs Co-authored-by: Michael Goulet --- compiler/stable_mir/src/mir/body.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index cbd9de33b6e24..abc9769ea9d62 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -813,7 +813,7 @@ impl BorrowKind { match self { BorrowKind::Mut { .. } => Mutability::Mut, BorrowKind::Shared => Mutability::Not, - // There's no type corresponding to a shallow borrow, so use `&` as an approximation. + // FIXME: There's no type corresponding to a shallow borrow, so use `&` as an approximation. BorrowKind::Fake => Mutability::Not, } } From 4616b9fd1d99e3f6d26858f32f835e60ddc3aaa3 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Wed, 6 Dec 2023 22:13:07 -0800 Subject: [PATCH 09/15] Add sanity check to `BinOp::ty()` --- compiler/stable_mir/src/mir/body.rs | 22 ++++++++++++++-------- compiler/stable_mir/src/ty.rs | 13 +++++++++++++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index abc9769ea9d62..90bd7aa7d1872 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -277,7 +277,9 @@ pub enum BinOp { impl BinOp { /// Return the type of this operation for the given input Ty. /// This function does not perform type checking, and it currently doesn't handle SIMD. - pub fn ty(&self, lhs_ty: Ty, _rhs_ty: Ty) -> Ty { + pub fn ty(&self, lhs_ty: Ty, rhs_ty: Ty) -> Ty { + assert!(lhs_ty.kind().is_primitive()); + assert!(rhs_ty.kind().is_primitive()); match self { BinOp::Add | BinOp::AddUnchecked @@ -289,13 +291,17 @@ impl BinOp { | BinOp::Rem | BinOp::BitXor | BinOp::BitAnd - | BinOp::BitOr - | BinOp::Shl - | BinOp::ShlUnchecked - | BinOp::Shr - | BinOp::ShrUnchecked - | BinOp::Offset => lhs_ty, - BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt => Ty::bool_ty(), + | BinOp::BitOr => { + assert_eq!(lhs_ty, rhs_ty); + lhs_ty + } + BinOp::Shl | BinOp::ShlUnchecked | BinOp::Shr | BinOp::ShrUnchecked | BinOp::Offset => { + lhs_ty + } + BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt => { + assert_eq!(lhs_ty, rhs_ty); + Ty::bool_ty() + } } } } diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index c7405c7f58230..c922264f8a365 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -244,6 +244,19 @@ impl TyKind { matches!(self, TyKind::RigidTy(RigidTy::FnPtr(..))) } + pub fn is_primitive(&self) -> bool { + matches!( + self, + TyKind::RigidTy( + RigidTy::Bool + | RigidTy::Char + | RigidTy::Int(_) + | RigidTy::Uint(_) + | RigidTy::Float(_) + ) + ) + } + pub fn trait_principal(&self) -> Option> { if let TyKind::RigidTy(RigidTy::Dynamic(predicates, _, _)) = self { if let Some(Binder { value: ExistentialPredicate::Trait(trait_ref), bound_vars }) = From ec0110be0961846b1c69d7208f07c740564e0d8a Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 7 Dec 2023 14:04:10 +1100 Subject: [PATCH 10/15] coverage: Merge refined spans in a separate final pass This makes `push_refined_span` trivial, which will let us inline it and benefit from partial borrows of `refined_spans`. --- .../rustc_mir_transform/src/coverage/spans.rs | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 4db0a1db1665d..cce2910244bc6 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -89,10 +89,10 @@ impl CoverageSpan { } } - pub fn merge_from(&mut self, mut other: CoverageSpan) { - debug_assert!(self.is_mergeable(&other)); + pub fn merge_from(&mut self, other: &Self) { + debug_assert!(self.is_mergeable(other)); self.span = self.span.to(other.span); - self.merged_spans.append(&mut other.merged_spans); + self.merged_spans.extend_from_slice(&other.merged_spans); } pub fn cutoff_statements_at(&mut self, cutoff_pos: BytePos) { @@ -267,7 +267,7 @@ impl<'a> CoverageSpansGenerator<'a> { if curr.is_mergeable(prev) { debug!(" same bcb (and neither is a closure), merge with prev={prev:?}"); let prev = self.take_prev(); - self.curr_mut().merge_from(prev); + self.curr_mut().merge_from(&prev); self.maybe_push_macro_name_span(); // Note that curr.span may now differ from curr_original_span } else if prev.span.hi() <= curr.span.lo() { @@ -346,6 +346,17 @@ impl<'a> CoverageSpansGenerator<'a> { self.push_refined_span(prev); } + // Do one last merge pass, to simplify the output. + self.refined_spans.dedup_by(|b, a| { + if a.is_mergeable(b) { + debug!(?a, ?b, "merging list-adjacent refined spans"); + a.merge_from(b); + true + } else { + false + } + }); + // Remove `CoverageSpan`s derived from closures, originally added to ensure the coverage // regions for the current function leave room for the closure's own coverage regions // (injected separately, from the closure's own MIR). @@ -354,15 +365,7 @@ impl<'a> CoverageSpansGenerator<'a> { } fn push_refined_span(&mut self, covspan: CoverageSpan) { - if let Some(last) = self.refined_spans.last_mut() - && last.is_mergeable(&covspan) - { - // Instead of pushing the new span, merge it with the last refined span. - debug!(?last, ?covspan, "merging new refined span with last refined span"); - last.merge_from(covspan); - } else { - self.refined_spans.push(covspan); - } + self.refined_spans.push(covspan); } /// If `curr` is part of a new macro expansion, carve out and push a separate From 9089d287801f93150845202066ac1a093f343e1a Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 7 Dec 2023 16:08:46 +1100 Subject: [PATCH 11/15] coverage: Inline `push_refined_span` --- .../rustc_mir_transform/src/coverage/spans.rs | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index cce2910244bc6..df26ff3699817 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -275,7 +275,7 @@ impl<'a> CoverageSpansGenerator<'a> { " different bcbs and disjoint spans, so keep curr for next iter, and add prev={prev:?}", ); let prev = self.take_prev(); - self.push_refined_span(prev); + self.refined_spans.push(prev); self.maybe_push_macro_name_span(); } else if prev.is_closure { // drop any equal or overlapping span (`curr`) and keep `prev` to test again in the @@ -326,7 +326,7 @@ impl<'a> CoverageSpansGenerator<'a> { // It is never used as a field after this point. for dup in std::mem::take(&mut self.pending_dups) { debug!(" ...adding at least one pending dup={:?}", dup); - self.push_refined_span(dup); + self.refined_spans.push(dup); } // Async functions wrap a closure that implements the body to be executed. The enclosing @@ -343,7 +343,7 @@ impl<'a> CoverageSpansGenerator<'a> { }; if !body_ends_with_closure { - self.push_refined_span(prev); + self.refined_spans.push(prev); } // Do one last merge pass, to simplify the output. @@ -364,10 +364,6 @@ impl<'a> CoverageSpansGenerator<'a> { self.refined_spans } - fn push_refined_span(&mut self, covspan: CoverageSpan) { - self.refined_spans.push(covspan); - } - /// If `curr` is part of a new macro expansion, carve out and push a separate /// span that ends just after the macro name and its subsequent `!`. fn maybe_push_macro_name_span(&mut self) { @@ -400,7 +396,7 @@ impl<'a> CoverageSpansGenerator<'a> { " and curr starts a new macro expansion, so add a new span just for \ the macro `{visible_macro}!`, new span={macro_name_cov:?}", ); - self.push_refined_span(macro_name_cov); + self.refined_spans.push(macro_name_cov); } fn curr(&self) -> &CoverageSpan { @@ -462,7 +458,7 @@ impl<'a> CoverageSpansGenerator<'a> { let mut pending_dups = std::mem::take(&mut self.pending_dups); for dup in pending_dups.drain(..) { debug!(" ...adding at least one pending={:?}", dup); - self.push_refined_span(dup); + self.refined_spans.push(dup); } // The list of dups is now empty, but we can recycle its capacity. assert!(pending_dups.is_empty() && self.pending_dups.is_empty()); @@ -528,10 +524,10 @@ impl<'a> CoverageSpansGenerator<'a> { for mut dup in pending_dups.iter().cloned() { dup.span = dup.span.with_hi(left_cutoff); debug!(" ...and at least one pre_closure dup={:?}", dup); - self.push_refined_span(dup); + self.refined_spans.push(dup); } } - self.push_refined_span(pre_closure); + self.refined_spans.push(pre_closure); } if has_post_closure_span { @@ -545,7 +541,7 @@ impl<'a> CoverageSpansGenerator<'a> { dup.span = dup.span.with_lo(right_cutoff); } let closure_covspan = self.take_curr(); // Prevent this curr from becoming prev. - self.push_refined_span(closure_covspan); // since self.prev() was already updated + self.refined_spans.push(closure_covspan); // since self.prev() was already updated } else { pending_dups.clear(); } @@ -648,7 +644,7 @@ impl<'a> CoverageSpansGenerator<'a> { } else { debug!(" ... adding modified prev={:?}", self.prev()); let prev = self.take_prev(); - self.push_refined_span(prev); + self.refined_spans.push(prev); } } else { // with `pending_dups`, `prev` cannot have any statements that don't overlap From 9a4321518c3ed461c9033bf02dcc1fa66da96ee3 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 7 Dec 2023 14:07:25 +1100 Subject: [PATCH 12/15] coverage: Simplify code that pushes to `refined_spans` --- .../rustc_mir_transform/src/coverage/spans.rs | 40 +++++++------------ 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index df26ff3699817..c415a8329942a 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -322,9 +322,8 @@ impl<'a> CoverageSpansGenerator<'a> { let prev = self.take_prev(); debug!(" AT END, adding last prev={prev:?}"); - // Take `pending_dups` so that we can drain it while calling self methods. - // It is never used as a field after this point. - for dup in std::mem::take(&mut self.pending_dups) { + // Drain any remaining dups into the output. + for dup in self.pending_dups.drain(..) { debug!(" ...adding at least one pending dup={:?}", dup); self.refined_spans.push(dup); } @@ -453,19 +452,14 @@ impl<'a> CoverageSpansGenerator<'a> { previous iteration, or prev started a new disjoint span" ); if last_dup.span.hi() <= self.curr().span.lo() { - // Temporarily steal `pending_dups` into a local, so that we can - // drain it while calling other self methods. - let mut pending_dups = std::mem::take(&mut self.pending_dups); - for dup in pending_dups.drain(..) { + for dup in self.pending_dups.drain(..) { debug!(" ...adding at least one pending={:?}", dup); self.refined_spans.push(dup); } - // The list of dups is now empty, but we can recycle its capacity. - assert!(pending_dups.is_empty() && self.pending_dups.is_empty()); - self.pending_dups = pending_dups; } else { self.pending_dups.clear(); } + assert!(self.pending_dups.is_empty()); } /// Advance `prev` to `curr` (if any), and `curr` to the next `CoverageSpan` in sorted order. @@ -512,21 +506,17 @@ impl<'a> CoverageSpansGenerator<'a> { let has_pre_closure_span = prev.span.lo() < right_cutoff; let has_post_closure_span = prev.span.hi() > right_cutoff; - // Temporarily steal `pending_dups` into a local, so that we can - // mutate and/or drain it while calling other self methods. - let mut pending_dups = std::mem::take(&mut self.pending_dups); - if has_pre_closure_span { let mut pre_closure = self.prev().clone(); pre_closure.span = pre_closure.span.with_hi(left_cutoff); debug!(" prev overlaps a closure. Adding span for pre_closure={:?}", pre_closure); - if !pending_dups.is_empty() { - for mut dup in pending_dups.iter().cloned() { - dup.span = dup.span.with_hi(left_cutoff); - debug!(" ...and at least one pre_closure dup={:?}", dup); - self.refined_spans.push(dup); - } + + for mut dup in self.pending_dups.iter().cloned() { + dup.span = dup.span.with_hi(left_cutoff); + debug!(" ...and at least one pre_closure dup={:?}", dup); + self.refined_spans.push(dup); } + self.refined_spans.push(pre_closure); } @@ -536,19 +526,17 @@ impl<'a> CoverageSpansGenerator<'a> { // about how the `CoverageSpan`s are ordered.) self.prev_mut().span = self.prev().span.with_lo(right_cutoff); debug!(" Mutated prev.span to start after the closure. prev={:?}", self.prev()); - for dup in pending_dups.iter_mut() { + + for dup in &mut self.pending_dups { debug!(" ...and at least one overlapping dup={:?}", dup); dup.span = dup.span.with_lo(right_cutoff); } + let closure_covspan = self.take_curr(); // Prevent this curr from becoming prev. self.refined_spans.push(closure_covspan); // since self.prev() was already updated } else { - pending_dups.clear(); + self.pending_dups.clear(); } - - // Restore the modified post-closure spans, or the empty vector's capacity. - assert!(self.pending_dups.is_empty()); - self.pending_dups = pending_dups; } /// Called if `curr.span` equals `prev_original_span` (and potentially equal to all From c0be10c3d121deb1d889a58798686da68c933657 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 7 Dec 2023 15:12:06 +0100 Subject: [PATCH 13/15] Ping GuillaumeGomez for changes in rustc_codegen_gcc --- triagebot.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 24926690cfe01..775d9714c6062 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -431,7 +431,7 @@ changelog-branch = "master" cc = ["@bjorn3"] [mentions."compiler/rustc_codegen_gcc"] -cc = ["@antoyo"] +cc = ["@antoyo", "@GuillaumeGomez"] [mentions."compiler/rustc_const_eval/src/interpret"] message = "Some changes occurred to the CTFE / Miri engine" From cf1cecc3f20a8f2f3ebd2d53cc37d199781bf61d Mon Sep 17 00:00:00 2001 From: oksbsb Date: Thu, 7 Dec 2023 22:39:07 +0800 Subject: [PATCH 14/15] fix jobserver GLOBAL_CLIENT_CHECKED uninitialized before use --- .../rustc_data_structures/src/jobserver.rs | 2 +- compiler/rustc_interface/src/interface.rs | 4 ++++ compiler/rustc_interface/src/tests.rs | 2 ++ compiler/rustc_session/src/session.rs | 23 ++++++++++--------- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_data_structures/src/jobserver.rs b/compiler/rustc_data_structures/src/jobserver.rs index b777bfd4d3c94..412e33aaa6551 100644 --- a/compiler/rustc_data_structures/src/jobserver.rs +++ b/compiler/rustc_data_structures/src/jobserver.rs @@ -52,7 +52,7 @@ fn default_client() -> Client { static GLOBAL_CLIENT_CHECKED: OnceLock = OnceLock::new(); -pub fn check(report_warning: impl FnOnce(&'static str)) { +pub fn initialize_checked(report_warning: impl FnOnce(&'static str)) { let client_checked = match &*GLOBAL_CLIENT { Ok(client) => client.clone(), Err(e) => { diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 7831b251db4bf..6527e87d39627 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -316,6 +316,10 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se // Set parallel mode before thread pool creation, which will create `Lock`s. rustc_data_structures::sync::set_dyn_thread_safe_mode(config.opts.unstable_opts.threads > 1); + // Check jobserver before run_in_thread_pool_with_globals, which call jobserver::acquire_thread + let early_handler = EarlyErrorHandler::new(config.opts.error_format); + early_handler.initialize_checked_jobserver(); + util::run_in_thread_pool_with_globals( config.opts.edition, config.opts.unstable_opts.threads, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index f7b6ab331a53f..ce58b2ab06170 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -27,6 +27,8 @@ use std::sync::Arc; fn mk_session(matches: getopts::Matches) -> (Session, Cfg) { let mut early_handler = EarlyErrorHandler::new(ErrorOutputType::default()); + early_handler.initialize_checked_jobserver(); + let registry = registry::Registry::new(&[]); let sessopts = build_session_options(&mut early_handler, &matches); let temps_dir = sessopts.unstable_opts.temps_dir.as_deref().map(PathBuf::from); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 123e9c788f57c..24c7459392abe 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1474,17 +1474,6 @@ pub fn build_session( let asm_arch = if target_cfg.allow_asm { InlineAsmArch::from_str(&target_cfg.arch).ok() } else { None }; - // Check jobserver before getting `jobserver::client`. - jobserver::check(|err| { - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] - parse_sess - .span_diagnostic - .struct_warn(err) - .note("the build environment is likely misconfigured") - .emit() - }); - let sess = Session { target: target_cfg, host, @@ -1792,6 +1781,18 @@ impl EarlyErrorHandler { pub fn early_warn(&self, msg: impl Into) { self.handler.struct_warn(msg).emit() } + + pub fn initialize_checked_jobserver(&self) { + // initialize jobserver before getting `jobserver::client` and `build_session`. + jobserver::initialize_checked(|err| { + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] + self.handler + .struct_warn(err) + .note("the build environment is likely misconfigured") + .emit() + }); + } } fn mk_emitter(output: ErrorOutputType) -> Box { From 399cd6cbfd3a797b1a48d122db57501c5926bd10 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 7 Dec 2023 15:36:00 +0000 Subject: [PATCH 15/15] targets: remove not-added {i386,i486}-unknown-linux-gnu These files were added to the repository but never wired up so they could be used - and that was a few years ago without anyone noticing - so let's remove these, they can be re-added if someone wants them. Signed-off-by: David Wood --- .../src/spec/targets/i386_unknown_linux_gnu.rs | 8 -------- .../src/spec/targets/i486_unknown_linux_gnu.rs | 8 -------- 2 files changed, 16 deletions(-) delete mode 100644 compiler/rustc_target/src/spec/targets/i386_unknown_linux_gnu.rs delete mode 100644 compiler/rustc_target/src/spec/targets/i486_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/targets/i386_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i386_unknown_linux_gnu.rs deleted file mode 100644 index 801a88933994a..0000000000000 --- a/compiler/rustc_target/src/spec/targets/i386_unknown_linux_gnu.rs +++ /dev/null @@ -1,8 +0,0 @@ -use crate::spec::Target; - -pub fn target() -> Target { - let mut base = super::i686_unknown_linux_gnu::target(); - base.cpu = "i386".into(); - base.llvm_target = "i386-unknown-linux-gnu".into(); - base -} diff --git a/compiler/rustc_target/src/spec/targets/i486_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i486_unknown_linux_gnu.rs deleted file mode 100644 index a11fbecc3c354..0000000000000 --- a/compiler/rustc_target/src/spec/targets/i486_unknown_linux_gnu.rs +++ /dev/null @@ -1,8 +0,0 @@ -use crate::spec::Target; - -pub fn target() -> Target { - let mut base = super::i686_unknown_linux_gnu::target(); - base.cpu = "i486".into(); - base.llvm_target = "i486-unknown-linux-gnu".into(); - base -}