Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2282,9 +2282,9 @@ checksum = "803ec87c9cfb29b9d2633f20cba1f488db3fd53f2158b1024cbefb47ba05d413"

[[package]]
name = "libc"
version = "0.2.189"
version = "0.2.191"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a"

[[package]]
name = "libffi"
Expand Down Expand Up @@ -2387,9 +2387,9 @@ dependencies = [

[[package]]
name = "linux-raw-sys"
version = "0.11.0"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"

[[package]]
name = "litemap"
Expand Down Expand Up @@ -5202,9 +5202,9 @@ dependencies = [

[[package]]
name = "rustix"
version = "1.1.2"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
checksum = "891efababe418670775f199f0d233d84843c227a0949a883ce15b37c78d6629d"
dependencies = [
"bitflags",
"errno",
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1133,6 +1133,7 @@ impl fmt::Display for AlignFromBytesError {

impl Align {
pub const ONE: Align = Align { pow2: 0 };
pub const FOUR: Align = Align { pow2: 2 };
pub const EIGHT: Align = Align { pow2: 3 };
// LLVM has a maximal supported alignment of 2^29, we inherit that.
pub const MAX: Align = Align { pow2: 29 };
Expand Down
60 changes: 34 additions & 26 deletions compiler/rustc_codegen_llvm/src/va_arg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rustc_codegen_ssa::traits::{
use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
use rustc_span::bug;
use rustc_target::spec::{Arch, Env, LlvmAbi, RustcAbi};
use rustc_target::spec::{Arch, Env, LlvmAbi, RustcAbi, Target};

use crate::builder::Builder;
use crate::llvm::Value;
Expand Down Expand Up @@ -97,7 +97,13 @@ fn get_param_type_alignment<'ll, 'tcx>(
Primitive::Float(float) => match float {
Float::F16 | Float::F16B | Float::F32 => unreachable!(),
Float::F64 | Float::F128 => { /* fall through */ }
Float::PpcF128 => return Align::EIGHT,
Float::PpcF128 => {
return if is_powerpc_softfloat_abi(&bx.cx.tcx.sess.target) {
Align::FOUR
} else {
Align::EIGHT
};
}
},
Primitive::Pointer(_) => { /* fall through */ }
},
Expand Down Expand Up @@ -222,7 +228,7 @@ fn emit_aapcs_va_arg<'ll, 'tcx>(
let on_stack = bx.append_sibling_block("va_arg.on_stack");
let end = bx.append_sibling_block("va_arg.end");
let zero = bx.const_i32(0);
let offset_align = Align::from_bytes(4).unwrap();
let offset_align = Align::FOUR;

let gr_type = layout.ty.is_any_ptr() || layout.ty.is_integral();
let (reg_off, reg_top, slot_size) = if gr_type {
Expand Down Expand Up @@ -291,6 +297,19 @@ fn emit_aapcs_va_arg<'ll, 'tcx>(
val
}

fn is_powerpc_softfloat_abi(target: &Target) -> bool {
if target.arch != Arch::PowerPC {
return false;
}

match target.rustc_abi {
Some(RustcAbi::Softfloat) => bug!("there are currently no powerpc softfloat targets"),
Some(RustcAbi::PowerPcSpe) => true, // SPE is like softfloat in terms of ABI
None => false,
Some(other) => bug!("unexpected powerpc abi {other:?}"),
}
}

fn emit_powerpc_va_arg<'ll, 'tcx>(
bx: &mut Builder<'_, 'll, 'tcx>,
list: OperandRef<'tcx, &'ll Value>,
Expand All @@ -310,26 +329,19 @@ fn emit_powerpc_va_arg<'ll, 'tcx>(
// Peel off any newtype wrappers.
let layout = layout.peel_transparent_wrappers_from_non_1zst(bx.cx);

// Rust does not currently support any powerpc softfloat targets.
// FIXME: however, the SPE targets are softfloat-like, and the current
// implementation doesn't handle them correctly.
let target = &bx.cx.tcx.sess.target;
let is_soft_float_abi = target.rustc_abi == Some(RustcAbi::Softfloat);
assert!(!is_soft_float_abi);

// All instances of VaArgSafe are passed directly.
let is_indirect = false;

let (is_i64, is_int, is_f64) = match layout.layout.backend_repr() {
let is_int = match layout.layout.backend_repr() {
BackendRepr::Scalar(scalar) => match scalar.primitive() {
rustc_abi::Primitive::Int(integer, _) => (integer.size().bits() == 64, true, false),
rustc_abi::Primitive::Float(float) => (false, false, matches!(float, Float::F64)),
rustc_abi::Primitive::Pointer(_) => (false, true, false),
rustc_abi::Primitive::Int(_, _) | rustc_abi::Primitive::Pointer(_) => true,
rustc_abi::Primitive::Float(_) => false,
},
_ => unreachable!("all instances of VaArgSafe are represented as scalars"),
};

let is_passed_in_fprs = !(is_int || is_soft_float_abi);
let is_passed_in_fprs = !(is_int || is_powerpc_softfloat_abi(&bx.cx.tcx.sess.target));

let num_regs_addr = if !is_passed_in_fprs {
va_list_addr // gpr
} else {
Expand All @@ -339,7 +351,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>(
let mut num_regs = bx.load(bx.type_i8(), num_regs_addr, dl.i8_align);

// "Align" the register count when the type is passed as `i64`.
if is_i64 || (is_f64 && is_soft_float_abi) {
if layout.size.bytes() == 8 && !is_passed_in_fprs {
num_regs = bx.add(num_regs, bx.const_u8(1));
num_regs = bx.and(num_regs, bx.const_u8(0b1111_1110));
}
Expand Down Expand Up @@ -388,7 +400,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>(
bx.store(bx.const_u8(max_regs), num_regs_addr, dl.i8_align);

// Everything in the overflow area is rounded up to a size of at least 4.
let overflow_area_align = Align::from_bytes(4).unwrap();
let overflow_area_align = Align::FOUR;

let size = if !is_indirect {
layout.layout.size.align_to(overflow_area_align)
Expand Down Expand Up @@ -625,8 +637,8 @@ fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>(
let gp_offset_ptr = va_list_addr;
let fp_offset_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(unsigned_int_offset));

let gp_offset_v = bx.load(bx.type_i32(), gp_offset_ptr, Align::from_bytes(8).unwrap());
let fp_offset_v = bx.load(bx.type_i32(), fp_offset_ptr, Align::from_bytes(4).unwrap());
let gp_offset_v = bx.load(bx.type_i32(), gp_offset_ptr, Align::EIGHT);
let fp_offset_v = bx.load(bx.type_i32(), fp_offset_ptr, Align::FOUR);

let mut use_regs = bx.const_bool(false);

Expand Down Expand Up @@ -759,7 +771,7 @@ fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>(
if num_fp_registers > 0 {
let offset = bx.const_u32(num_fp_registers * 16);
let sum = bx.add(fp_offset_v, offset);
bx.store(sum, fp_offset_ptr, Align::from_bytes(4).unwrap());
bx.store(sum, fp_offset_ptr, Align::FOUR);
}

bx.br(end);
Expand Down Expand Up @@ -872,11 +884,7 @@ fn emit_hexagon_va_arg_musl<'ll, 'tcx>(
// Align current pointer based on argument type size (following LLVM's implementation)
// Arguments <= 32 bits (4 bytes) use 4-byte alignment, > 32 bits use 8-byte alignment
let type_size_bits = layout.size.bits();
let arg_align = if type_size_bits > 32 {
Align::from_bytes(8).unwrap()
} else {
Align::from_bytes(4).unwrap()
};
let arg_align = if type_size_bits > 32 { Align::EIGHT } else { Align::FOUR };
let aligned_current = round_pointer_up_to_alignment(bx, current_ptr, arg_align);

// Calculate next pointer position (following LLVM's logic)
Expand Down Expand Up @@ -991,7 +999,7 @@ fn emit_xtensa_va_arg<'ll, 'tcx>(
let offset = bx.load(bx.type_i32(), offset_ptr, bx.tcx().data_layout.i32_align);
let offset = round_up_to_alignment(bx, offset, layout.align.abi);

let slot_size = layout.size.align_to(Align::from_bytes(4).unwrap()).bytes() as i32;
let slot_size = layout.size.align_to(Align::FOUR).bytes() as i32;

// Update the offset in va_list, by adding the slot's size.
let offset_next = bx.add(offset, bx.const_i32(slot_size));
Expand Down
48 changes: 48 additions & 0 deletions library/core/src/bool.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! impl bool {}

use crate::intrinsics;
use crate::marker::Destruct;
use crate::ub_checks::assert_unsafe_precondition;

impl bool {
/// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html),
Expand Down Expand Up @@ -157,4 +159,50 @@ impl bool {
pub const fn toggle(&mut self) {
*self = !*self;
}

/// Disjoint, bitwise or. Computes `self | rhs`, assuming at most one, true value.
///
/// Practically, this requires that `self | rhs` and `self ^ rhs` both yield the
/// same result, allowing for any of the two to be emitted in codegen -- depending
/// on whichever is cheapest.
///
/// # Examples
///
/// ```
/// #![feature(disjoint_bitor)]
///
/// assert_eq!(
/// // SAFETY: Only one, true value is passed.
/// unsafe { false.unchecked_disjoint_bitor(true) },
/// true,
/// );
///
/// assert_eq!(
/// // SAFETY: No true values are passed.
/// unsafe { false.unchecked_disjoint_bitor(false) },
/// false,
/// );
/// ```
///
/// # Safety
///
/// This results in undefined behaviour if both `self` and `rhs` are true.
#[unstable(feature = "disjoint_bitor", issue = "135758")]
#[rustc_const_unstable(feature = "disjoint_bitor", issue = "135758")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const unsafe fn unchecked_disjoint_bitor(self, rhs: Self) -> Self {
assert_unsafe_precondition!(
check_language_ub,
"bool::unchecked_disjoint_bitor cannot bitor two truths",
(
lhs: bool = self,
rhs: bool = rhs,
) => !(lhs & rhs),
);

// SAFETY: Same precondition.
unsafe { intrinsics::disjoint_bitor(self, rhs) }
}
}
4 changes: 2 additions & 2 deletions library/core/src/macros/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -802,7 +802,7 @@ macro_rules! unreachable {
#[rustc_diagnostic_opaque]
macro_rules! unimplemented {
() => {
$crate::panicking::panic("not implemented")
$crate::panicking::unimplemented_default_msg()
};
($($arg:tt)+) => {
$crate::panic!("not implemented: {}", $crate::format_args!($($arg)+))
Expand Down Expand Up @@ -883,7 +883,7 @@ macro_rules! unimplemented {
#[rustc_diagnostic_opaque]
macro_rules! todo {
() => {
$crate::panicking::panic("not yet implemented")
$crate::panicking::todo_default_msg()
};
($($arg:tt)+) => {
$crate::panic!("not yet implemented: {}", $crate::format_args!($($arg)+))
Expand Down
47 changes: 43 additions & 4 deletions library/core/src/num/int_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1325,6 +1325,49 @@ macro_rules! int_impl {
if b { imp::overflow_panic::rem() } else { a }
}

/// Disjoint, bitwise or. Computes `self | rhs`, assuming no overlapping one bits.
///
/// Practically, this requires that `self | rhs`, `self ^ rhs`, and `self + rhs` all
/// yield the same result, allowing for any of the three to be emitted in codegen --
/// depending on whichever is cheapest.
///
/// # Examples
///
/// ```
/// #![feature(disjoint_bitor)]
///
/// assert_eq!(
/// // SAFETY: `1` and `-2` have no ones in common.
#[doc = concat!(" unsafe { 1_", stringify!($SelfT), ".unchecked_disjoint_bitor(-2) },")]
/// -1,
/// );
/// ```
///
/// # Safety
///
/// This results in undefined behaviour if `self` and `rhs` have any overlapping one
/// bits, i.e. `lhs & rhs` must be zero.
///
/// Notably, this prevents both values from being negative.
#[unstable(feature = "disjoint_bitor", issue = "135758")]
#[rustc_const_unstable(feature = "disjoint_bitor", issue = "135758")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const unsafe fn unchecked_disjoint_bitor(self, rhs: Self) -> Self {
assert_unsafe_precondition!(
check_language_ub,
concat!(stringify!($SelfT), "::unchecked_disjoint_bitor cannot bitor overlapping ones"),
(
lhs: $SelfT = self,
rhs: $SelfT = rhs,
) => (lhs & rhs) == 0,
);

// SAFETY: Same precondition.
unsafe { intrinsics::disjoint_bitor(self, rhs) }
}

/// Checked negation. Computes `-self`, returning `None` if `self == MIN`.
///
/// # Examples
Expand Down Expand Up @@ -2929,7 +2972,6 @@ macro_rules! int_impl {
}
}


/// Overflowing Euclidean remainder. Calculates `self.rem_euclid(rhs)`.
///
/// Returns a tuple of the remainder after dividing along with a boolean indicating whether an
Expand Down Expand Up @@ -2959,7 +3001,6 @@ macro_rules! int_impl {
}
}


/// Negates self, overflowing if this is equal to the minimum value.
///
/// Returns a tuple of the negated version of self along with a boolean indicating whether an overflow
Expand Down Expand Up @@ -3217,7 +3258,6 @@ macro_rules! int_impl {
q
}


/// Calculates the least nonnegative remainder of `self` when
/// divided by `rhs`.
///
Expand Down Expand Up @@ -4061,7 +4101,6 @@ macro_rules! int_impl {
traits::WidenTarget::internal_widen(self)
}


/// Converts `self` to the target integer type, saturating at the numeric
/// bounds instead of overflowing.
///
Expand Down
Loading
Loading