From 0879bbf7cb9434e8c66014455067526384691390 Mon Sep 17 00:00:00 2001 From: alion02 Date: Wed, 1 May 2024 06:10:53 +0200 Subject: [PATCH 1/9] Start implementation of disjoint_bitor --- compiler/rustc_hir_analysis/src/check/intrinsic.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + library/core/src/intrinsics.rs | 10 ++++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 74324c8695b80..11043c5f105ca 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -460,7 +460,7 @@ pub fn check_intrinsic_type( } sym::unchecked_shl | sym::unchecked_shr => (2, 0, vec![param(0), param(1)], param(0)), sym::rotate_left | sym::rotate_right => (1, 0, vec![param(0), tcx.types.u32], param(0)), - sym::unchecked_add | sym::unchecked_sub | sym::unchecked_mul => { + sym::unchecked_add | sym::unchecked_sub | sym::unchecked_mul | sym::disjoint_bitor => { (1, 0, vec![param(0), param(0)], param(0)) } sym::wrapping_add | sym::wrapping_sub | sym::wrapping_mul => { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8d38867ab1f99..4c66f129512c4 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -707,6 +707,7 @@ symbols! { discriminant_kind, discriminant_type, discriminant_value, + disjoint_bitor, dispatch_from_dyn, div, div_assign, diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 14b4ce39ab453..21d48bcdaacba 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2311,6 +2311,16 @@ extern "rust-intrinsic" { #[rustc_nounwind] pub fn unchecked_mul(x: T, y: T) -> T; + /// Performs an unchecked disjoint bitor operation. Equivalent to normal + /// bitor and bitxor operations, triggering undefined behavior if their + /// results differ. + /// + /// The stable counterpart of this intrinsic is `unchecked_disjoint_bitor` + /// on the various integer types, such as [`u16::unchecked_disjoint_bitor`] + /// and [`i64::disjoint_bitor`]. + #[rustc_nounwind] + pub fn disjoint_bitor(x: T, y: T) -> T; + /// Performs rotate left. /// /// Note that, unlike most intrinsics, this is safe to call; From 5380e093b037a034deeeba7844153f215696300f Mon Sep 17 00:00:00 2001 From: alion02 Date: Wed, 1 May 2024 06:27:02 +0200 Subject: [PATCH 2/9] Add necessary FFI --- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 7a34e21628dc6..0436ba87affdf 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1273,6 +1273,7 @@ extern "C" { pub fn LLVMBuildNeg<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; pub fn LLVMBuildFNeg<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; pub fn LLVMBuildNot<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; + pub fn LLVMSetIsDisjoint(Inst: &Value, IsDisjoint: Bool); // Memory pub fn LLVMBuildAlloca<'a>(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value; From 9ae986263566fd2bb1f1213a03e909cd468e3c12 Mon Sep 17 00:00:00 2001 From: alion02 Date: Thu, 2 May 2024 02:41:00 +0200 Subject: [PATCH 3/9] Add `or disjoint` to backend --- compiler/rustc_codegen_llvm/src/builder.rs | 8 ++++++++ compiler/rustc_codegen_ssa/src/traits/builder.rs | 1 + 2 files changed, 9 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 5c8f358d03a1f..4cc9417ecb644 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -303,6 +303,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { unchecked_umul(x, y) => LLVMBuildNUWMul, } + fn disjoint_or(&mut self, a: &'ll Value, b: &'ll Value) -> &'ll Value { + unsafe { + let or = llvm::LLVMBuildOr(self.llbuilder, a, b, UNNAMED); + llvm::LLVMSetIsDisjoint(or, True); + or + } + } + fn fadd_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { unsafe { let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, UNNAMED); diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 51b22bfaf2558..49c5db3d9eba7 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -122,6 +122,7 @@ pub trait BuilderMethods<'a, 'tcx>: fn and(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; fn or(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; fn xor(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; + fn disjoint_or(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; fn neg(&mut self, v: Self::Value) -> Self::Value; fn fneg(&mut self, v: Self::Value) -> Self::Value; fn not(&mut self, v: Self::Value) -> Self::Value; From fbcb3dc5d5b50eba441e8f752d70c8194b4d4d77 Mon Sep 17 00:00:00 2001 From: alion02 Date: Thu, 2 May 2024 03:13:14 +0200 Subject: [PATCH 4/9] Handle it in some of the places I can find --- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 1 + compiler/rustc_const_eval/src/interpret/operator.rs | 7 +++++++ compiler/rustc_const_eval/src/transform/validate.rs | 2 +- compiler/rustc_const_eval/src/util/mod.rs | 4 ++-- compiler/rustc_middle/src/mir/syntax.rs | 2 ++ compiler/rustc_middle/src/mir/tcx.rs | 4 +++- compiler/rustc_mir_transform/src/lower_intrinsics.rs | 1 + compiler/rustc_mir_transform/src/promote_consts.rs | 1 + compiler/rustc_smir/src/rustc_internal/internal.rs | 1 + compiler/rustc_smir/src/rustc_smir/convert/mir.rs | 1 + compiler/rustc_ty_utils/src/consts.rs | 4 ++-- compiler/stable_mir/src/mir/body.rs | 1 + 12 files changed, 23 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 4e7d251a2e928..fa1af6c64f01b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -867,6 +867,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::BinOp::BitOr => bx.or(lhs, rhs), mir::BinOp::BitAnd => bx.and(lhs, rhs), mir::BinOp::BitXor => bx.xor(lhs, rhs), + mir::BinOp::BitOrDisjoint => bx.disjoint_or(lhs, rhs), mir::BinOp::Offset => { let pointee_type = input_ty .builtin_deref(true) diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 9af755e40de87..55ae475356b51 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -308,6 +308,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { BitAnd => ImmTy::from_uint(l & r, left.layout), BitXor => ImmTy::from_uint(l ^ r, left.layout), + BitOrDisjoint => { + if l & r != 0 { + todo!(); // Can't figure out what to do here based on the surrounding code + } + ImmTy::from_uint(l | r, left.layout) + } + Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Rem | Div => { assert!(!left.layout.abi.is_signed()); let op: fn(u128, u128) -> (u128, bool) = match bin_op { diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 837c02a5b769b..46385c5ce623c 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -1046,7 +1046,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ) } } - BitAnd | BitOr | BitXor => { + BitAnd | BitOr | BitXor | BitOrDisjoint => { for x in [a, b] { check_kinds!( x, diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs index 0c3b59a0e78ec..57c107a9d77af 100644 --- a/compiler/rustc_const_eval/src/util/mod.rs +++ b/compiler/rustc_const_eval/src/util/mod.rs @@ -18,7 +18,7 @@ pub fn binop_left_homogeneous(op: mir::BinOp) -> bool { use rustc_middle::mir::BinOp::*; match op { Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor - | BitAnd | BitOr | Offset | Shl | ShlUnchecked | Shr | ShrUnchecked => true, + | BitAnd | BitOr | BitOrDisjoint | Offset | Shl | ShlUnchecked | Shr | ShrUnchecked => true, Eq | Ne | Lt | Le | Gt | Ge | Cmp => false, } } @@ -30,7 +30,7 @@ pub fn binop_right_homogeneous(op: mir::BinOp) -> bool { use rustc_middle::mir::BinOp::*; match op { Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor - | BitAnd | BitOr | Eq | Ne | Lt | Le | Gt | Ge | Cmp => true, + | BitAnd | BitOr | BitOrDisjoint | Eq | Ne | Lt | Le | Gt | Ge | Cmp => true, Offset | Shl | ShlUnchecked | Shr | ShrUnchecked => false, } } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 4278ce823d0e0..412e2c62f216b 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1478,6 +1478,8 @@ pub enum BinOp { BitAnd, /// The `|` operator (bitwise or) BitOr, + /// Like `BitOr` and `BitXor`, but UB if results don't match. + BitOrDisjoint, /// The `<<` operator (shift left) /// /// The offset is truncated to the size of the first operand and made unsigned before shifting. diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 3881723c5ec9c..608ca5da95d54 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -262,7 +262,8 @@ impl<'tcx> BinOp { | &BinOp::Rem | &BinOp::BitXor | &BinOp::BitAnd - | &BinOp::BitOr => { + | &BinOp::BitOr + | &BinOp::BitOrDisjoint => { // these should be integers or floats of the same size. assert_eq!(lhs_ty, rhs_ty); lhs_ty @@ -322,6 +323,7 @@ impl BinOp { | BinOp::AddUnchecked | BinOp::SubUnchecked | BinOp::MulUnchecked + | BinOp::BitOrDisjoint | BinOp::ShlUnchecked | BinOp::ShrUnchecked | BinOp::Offset => { diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index da63fcf23d9ee..bd0cb6e71098f 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -118,6 +118,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { sym::unchecked_rem => BinOp::Rem, sym::unchecked_shl => BinOp::ShlUnchecked, sym::unchecked_shr => BinOp::ShrUnchecked, + sym::disjoint_bitor => BinOp::BitOrDisjoint, _ => bug!("unexpected intrinsic"), }; block.statements.push(Statement { diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index 689a547689a2d..bd80921d07b90 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -545,6 +545,7 @@ impl<'tcx> Validator<'_, 'tcx> { | BinOp::BitXor | BinOp::BitAnd | BinOp::BitOr + | BinOp::BitOrDisjoint | BinOp::Shl | BinOp::ShlUnchecked | BinOp::Shr diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index 0893bc31bfacd..7a19f800ee4f2 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -567,6 +567,7 @@ impl RustcInternal for BinOp { BinOp::BitXor => rustc_middle::mir::BinOp::BitXor, BinOp::BitAnd => rustc_middle::mir::BinOp::BitAnd, BinOp::BitOr => rustc_middle::mir::BinOp::BitOr, + BinOp::BitOrDisjoint => rustc_middle::mir::BinOp::BitOrDisjoint, BinOp::Shl => rustc_middle::mir::BinOp::Shl, BinOp::ShlUnchecked => rustc_middle::mir::BinOp::ShlUnchecked, BinOp::Shr => rustc_middle::mir::BinOp::Shr, diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index 452ab04c44c54..1a7fe5e2e56cd 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -494,6 +494,7 @@ impl<'tcx> Stable<'tcx> for mir::BinOp { BinOp::BitXor => stable_mir::mir::BinOp::BitXor, BinOp::BitAnd => stable_mir::mir::BinOp::BitAnd, BinOp::BitOr => stable_mir::mir::BinOp::BitOr, + BinOp::BitOrDisjoint => stable_mir::mir::BinOp::BitOrDisjoint, BinOp::Shl => stable_mir::mir::BinOp::Shl, BinOp::ShlUnchecked => stable_mir::mir::BinOp::ShlUnchecked, BinOp::Shr => stable_mir::mir::BinOp::Shr, diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index acbcc3918b2fb..4d829ac6565ce 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -81,8 +81,8 @@ fn check_binop(op: mir::BinOp) -> bool { use mir::BinOp::*; match op { Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor - | BitAnd | BitOr | Shl | ShlUnchecked | Shr | ShrUnchecked | Eq | Lt | Le | Ne | Ge - | Gt | Cmp => true, + | BitAnd | BitOr | BitOrDisjoint | Shl | ShlUnchecked | Shr | ShrUnchecked | Eq | Lt + | Le | Ne | Ge | Gt | Cmp => true, Offset => false, } } diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index e077c58031806..311fb0acbc58a 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -320,6 +320,7 @@ pub enum BinOp { BitXor, BitAnd, BitOr, + BitOrDisjoint, Shl, ShlUnchecked, Shr, From 676d94b80b230e2e6694b5701226242e91dc8ca8 Mon Sep 17 00:00:00 2001 From: alion02 Date: Thu, 2 May 2024 03:23:41 +0200 Subject: [PATCH 5/9] Comment out the intrinsic so rustc gets to scream at me --- library/core/src/intrinsics.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 21d48bcdaacba..cf651b23109ae 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2311,15 +2311,15 @@ extern "rust-intrinsic" { #[rustc_nounwind] pub fn unchecked_mul(x: T, y: T) -> T; - /// Performs an unchecked disjoint bitor operation. Equivalent to normal - /// bitor and bitxor operations, triggering undefined behavior if their - /// results differ. - /// - /// The stable counterpart of this intrinsic is `unchecked_disjoint_bitor` - /// on the various integer types, such as [`u16::unchecked_disjoint_bitor`] - /// and [`i64::disjoint_bitor`]. - #[rustc_nounwind] - pub fn disjoint_bitor(x: T, y: T) -> T; + // /// Performs an unchecked disjoint bitor operation. Equivalent to normal + // /// bitor and bitxor operations, triggering undefined behavior if their + // /// results differ. + // /// + // /// The stable counterpart of this intrinsic is `unchecked_disjoint_bitor` + // /// on the various integer types, such as [`u16::unchecked_disjoint_bitor`] + // /// and [`i64::disjoint_bitor`]. + // #[rustc_nounwind] + // pub fn disjoint_bitor(x: T, y: T) -> T; /// Performs rotate left. /// From 49a5f89b90531d1ddf0ceb4028d17fafe7d53391 Mon Sep 17 00:00:00 2001 From: alion02 Date: Thu, 2 May 2024 03:30:25 +0200 Subject: [PATCH 6/9] Fix build --- .../rustc_codegen_cranelift/src/codegen_i128.rs | 4 ++-- compiler/rustc_codegen_cranelift/src/num.rs | 3 ++- compiler/rustc_codegen_gcc/src/builder.rs | 13 +++++++------ 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs index 4a5ef352151f3..6cc3d7824c36f 100644 --- a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs +++ b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs @@ -21,7 +21,7 @@ pub(crate) fn maybe_codegen<'tcx>( let is_signed = type_sign(lhs.layout().ty); match bin_op { - BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor => None, + BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor | BinOp::BitOrDisjoint => None, BinOp::Add | BinOp::AddUnchecked | BinOp::Sub | BinOp::SubUnchecked => None, BinOp::Mul | BinOp::MulUnchecked => { let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)]; @@ -90,7 +90,7 @@ pub(crate) fn maybe_codegen_checked<'tcx>( let is_signed = type_sign(lhs.layout().ty); match bin_op { - BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor => unreachable!(), + BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor | BinOp::BitOrDisjoint => unreachable!(), BinOp::Mul if is_signed => { let out_ty = Ty::new_tup(fx.tcx, &[lhs.layout().ty, fx.tcx.types.bool]); let oflow = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32)); diff --git a/compiler/rustc_codegen_cranelift/src/num.rs b/compiler/rustc_codegen_cranelift/src/num.rs index 714858084ec9d..14484df1d63dd 100644 --- a/compiler/rustc_codegen_cranelift/src/num.rs +++ b/compiler/rustc_codegen_cranelift/src/num.rs @@ -149,6 +149,7 @@ pub(crate) fn codegen_int_binop<'tcx>( let b = fx.bcx.ins(); // FIXME trap on overflow for the Unchecked versions + // FIXME trap on non-disjoint for BitOrDisjoint let val = match bin_op { BinOp::Add | BinOp::AddUnchecked => b.iadd(lhs, rhs), BinOp::Sub | BinOp::SubUnchecked => b.isub(lhs, rhs), @@ -169,7 +170,7 @@ pub(crate) fn codegen_int_binop<'tcx>( } BinOp::BitXor => b.bxor(lhs, rhs), BinOp::BitAnd => b.band(lhs, rhs), - BinOp::BitOr => b.bor(lhs, rhs), + BinOp::BitOr | BinOp::BitOrDisjoint => b.bor(lhs, rhs), BinOp::Shl | BinOp::ShlUnchecked => b.ishl(lhs, rhs), BinOp::Shr | BinOp::ShrUnchecked => { if signed { diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 23a5e5ff8730c..dd3f8abd7fadd 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -25,7 +25,7 @@ use rustc_middle::ty::layout::{ FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout, }; -use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, Instance}; +use rustc_middle::ty::{Instance, ParamEnv, Ty, TyCtxt}; use rustc_span::def_id::DefId; use rustc_span::Span; use rustc_target::abi::{ @@ -792,6 +792,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { self.cx.gcc_or(a, b, self.location) } + fn disjoint_or(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + // TODO: investigate gcc equivalent of this operation + self.cx.gcc_or(a, b, self.location) + } + fn xor(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { set_rvalue_location(self, self.gcc_xor(a, b)) } @@ -903,11 +908,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // TODO(antoyo): It might be better to return a LValue, but fixing the rustc API is non-trivial. self.stack_var_count.set(self.stack_var_count.get() + 1); self.current_func() - .new_local( - self.location, - ty, - &format!("stack_var_{}", self.stack_var_count.get()), - ) + .new_local(self.location, ty, &format!("stack_var_{}", self.stack_var_count.get())) .get_address(self.location) } From e1e4c17901f6d74833ebf9d8b3d3df0b9313a0fb Mon Sep 17 00:00:00 2001 From: alion02 Date: Thu, 2 May 2024 03:38:58 +0200 Subject: [PATCH 7/9] Finish adding intrinsic --- .../src/lower_intrinsics.rs | 3 ++- library/core/src/intrinsics.rs | 18 +++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index bd0cb6e71098f..9ffe457fed1bb 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -97,7 +97,8 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { | sym::unchecked_div | sym::unchecked_rem | sym::unchecked_shl - | sym::unchecked_shr => { + | sym::unchecked_shr + | sym::disjoint_bitor => { let target = target.unwrap(); let lhs; let rhs; diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index cf651b23109ae..21d48bcdaacba 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2311,15 +2311,15 @@ extern "rust-intrinsic" { #[rustc_nounwind] pub fn unchecked_mul(x: T, y: T) -> T; - // /// Performs an unchecked disjoint bitor operation. Equivalent to normal - // /// bitor and bitxor operations, triggering undefined behavior if their - // /// results differ. - // /// - // /// The stable counterpart of this intrinsic is `unchecked_disjoint_bitor` - // /// on the various integer types, such as [`u16::unchecked_disjoint_bitor`] - // /// and [`i64::disjoint_bitor`]. - // #[rustc_nounwind] - // pub fn disjoint_bitor(x: T, y: T) -> T; + /// Performs an unchecked disjoint bitor operation. Equivalent to normal + /// bitor and bitxor operations, triggering undefined behavior if their + /// results differ. + /// + /// The stable counterpart of this intrinsic is `unchecked_disjoint_bitor` + /// on the various integer types, such as [`u16::unchecked_disjoint_bitor`] + /// and [`i64::disjoint_bitor`]. + #[rustc_nounwind] + pub fn disjoint_bitor(x: T, y: T) -> T; /// Performs rotate left. /// From e62d5ce1286b4fb4a4bf6231f1987182c6afe33f Mon Sep 17 00:00:00 2001 From: alion02 Date: Thu, 2 May 2024 04:00:43 +0200 Subject: [PATCH 8/9] Fix name in docs --- library/core/src/intrinsics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 21d48bcdaacba..d02d6189830b8 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2317,7 +2317,7 @@ extern "rust-intrinsic" { /// /// The stable counterpart of this intrinsic is `unchecked_disjoint_bitor` /// on the various integer types, such as [`u16::unchecked_disjoint_bitor`] - /// and [`i64::disjoint_bitor`]. + /// and [`i64::unchecked_disjoint_bitor`]. #[rustc_nounwind] pub fn disjoint_bitor(x: T, y: T) -> T; From 018a3a7371d33cdcc6cddb74c3d1d93ea350f350 Mon Sep 17 00:00:00 2001 From: alion02 Date: Fri, 3 May 2024 03:53:00 +0200 Subject: [PATCH 9/9] Apply suggestions, fix build, clean up --- compiler/rustc_const_eval/messages.ftl | 3 +++ compiler/rustc_const_eval/src/errors.rs | 2 ++ compiler/rustc_const_eval/src/interpret/operator.rs | 2 +- compiler/rustc_middle/src/mir/interpret/error.rs | 2 ++ compiler/rustc_middle/src/mir/syntax.rs | 3 ++- library/core/src/intrinsics.rs | 9 ++++++--- 6 files changed, 16 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index b79d7441acac7..5c1527a6b9172 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -249,6 +249,9 @@ const_eval_overflow = const_eval_overflow_shift = overflowing shift by {$val} in `{$name}` +const_eval_overlapping_disjoint_bit_or = + disjoint bitor executed on overlapping operands (`lhs & rhs != 0`) + const_eval_panic = the evaluated program panicked at '{$msg}', {$file}:{$line}:{$col} diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 90d4f1168e4fd..9ab5881900cb0 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -480,6 +480,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { RemainderByZero => const_eval_remainder_by_zero, DivisionOverflow => const_eval_division_overflow, RemainderOverflow => const_eval_remainder_overflow, + OverlappingDisjointBitOr => const_eval_overlapping_disjoint_bit_or, PointerArithOverflow => const_eval_pointer_arithmetic_overflow, InvalidMeta(InvalidMetaKind::SliceTooBig) => const_eval_invalid_meta_slice, InvalidMeta(InvalidMetaKind::TooBig) => const_eval_invalid_meta, @@ -531,6 +532,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { | RemainderByZero | DivisionOverflow | RemainderOverflow + | OverlappingDisjointBitOr | PointerArithOverflow | InvalidMeta(InvalidMetaKind::SliceTooBig) | InvalidMeta(InvalidMetaKind::TooBig) diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 55ae475356b51..9f3836a2d6955 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -310,7 +310,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { BitOrDisjoint => { if l & r != 0 { - todo!(); // Can't figure out what to do here based on the surrounding code + throw_ub!(OverlappingDisjointBitOr) } ImmTy::from_uint(l | r, left.layout) } diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 383241465c3d1..547294c244782 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -307,6 +307,8 @@ pub enum UndefinedBehaviorInfo<'tcx> { DivisionOverflow, /// Signed remainder overflowed (INT_MIN % -1). RemainderOverflow, + /// Disjoint bitor operation executed on overlapping bitvectors (lhs & rhs != 0). + OverlappingDisjointBitOr, /// Overflowing inbounds pointer arithmetic. PointerArithOverflow, /// Invalid metadata in a wide pointer diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 412e2c62f216b..ce8e72ff7f056 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1478,7 +1478,8 @@ pub enum BinOp { BitAnd, /// The `|` operator (bitwise or) BitOr, - /// Like `BitOr` and `BitXor`, but UB if results don't match. + /// Equivalent to all of `BitOr`, `BitXor`, and `Add`. UB if any bit is set + /// in both operands; that is, if `lhs & rhs != 0`. BitOrDisjoint, /// The `<<` operator (shift left) /// diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index d02d6189830b8..6b1527cb86878 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2315,9 +2315,12 @@ extern "rust-intrinsic" { /// bitor and bitxor operations, triggering undefined behavior if their /// results differ. /// - /// The stable counterpart of this intrinsic is `unchecked_disjoint_bitor` - /// on the various integer types, such as [`u16::unchecked_disjoint_bitor`] - /// and [`i64::unchecked_disjoint_bitor`]. + /// This intrinsic does not have a stable counterpart. + // /// The stable counterpart of this intrinsic is `unchecked_disjoint_bitor` + // /// on the various integer types, such as [`u16::unchecked_disjoint_bitor`] + // /// and [`i64::unchecked_disjoint_bitor`]. + #[cfg(not(bootstrap))] + #[rustc_const_unstable(feature = "disjoint_bitor", issue = "none")] #[rustc_nounwind] pub fn disjoint_bitor(x: T, y: T) -> T;