atomic_load intrinsic: use const generic parameter for ordering
This commit is contained in:
parent
6f69710780
commit
4794ea176b
15 changed files with 198 additions and 74 deletions
|
|
@ -870,11 +870,12 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
|||
// FIXME use a compiler fence once Cranelift supports it
|
||||
fx.bcx.ins().fence();
|
||||
}
|
||||
_ if intrinsic.as_str().starts_with("atomic_load") => {
|
||||
sym::atomic_load => {
|
||||
intrinsic_args!(fx, args => (ptr); intrinsic);
|
||||
let ptr = ptr.load_scalar(fx);
|
||||
|
||||
let ty = generic_args.type_at(0);
|
||||
let _ord = generic_args.const_at(1).to_value(); // FIXME: forward this to cranelift once they support that
|
||||
match ty.kind() {
|
||||
ty::Uint(UintTy::U128) | ty::Int(IntTy::I128) => {
|
||||
// FIXME implement 128bit atomics
|
||||
|
|
|
|||
|
|
@ -99,6 +99,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
|
||||
let llret_ty = bx.backend_type(bx.layout_of(ret_ty));
|
||||
|
||||
let ret_llval = |bx: &mut Bx, llval| {
|
||||
if result.layout.ty.is_bool() {
|
||||
OperandRef::from_immediate_or_packed_pair(bx, llval, result.layout)
|
||||
.val
|
||||
.store(bx, result);
|
||||
} else if !result.layout.ty.is_unit() {
|
||||
bx.store_to_place(llval, result.val);
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
|
||||
let llval = match name {
|
||||
sym::abort => {
|
||||
bx.abort();
|
||||
|
|
@ -337,6 +348,53 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
use crate::common::AtomicOrdering::*;
|
||||
use crate::common::{AtomicRmwBinOp, SynchronizationScope};
|
||||
|
||||
let invalid_monomorphization = |ty| {
|
||||
bx.tcx().dcx().emit_err(InvalidMonomorphization::BasicIntegerType {
|
||||
span,
|
||||
name,
|
||||
ty,
|
||||
});
|
||||
};
|
||||
|
||||
let parse_const_generic_ordering = |ord: ty::Value<'tcx>| {
|
||||
let discr = ord.valtree.unwrap_branch()[0].unwrap_leaf();
|
||||
let ord = discr.to_atomic_ordering();
|
||||
// We have to translate from the intrinsic ordering to the backend ordering.
|
||||
use rustc_middle::ty::AtomicOrdering;
|
||||
match ord {
|
||||
AtomicOrdering::Relaxed => Relaxed,
|
||||
AtomicOrdering::Release => Release,
|
||||
AtomicOrdering::Acquire => Acquire,
|
||||
AtomicOrdering::AcqRel => AcquireRelease,
|
||||
AtomicOrdering::SeqCst => SequentiallyConsistent,
|
||||
}
|
||||
};
|
||||
|
||||
// Some intrinsics have the ordering already converted to a const generic parameter, we handle those first.
|
||||
match name {
|
||||
sym::atomic_load => {
|
||||
let ty = fn_args.type_at(0);
|
||||
let ordering = fn_args.const_at(1).to_value();
|
||||
if !(int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr()) {
|
||||
invalid_monomorphization(ty);
|
||||
return Ok(());
|
||||
}
|
||||
let layout = bx.layout_of(ty);
|
||||
let source = args[0].immediate();
|
||||
let llval = bx.atomic_load(
|
||||
bx.backend_type(layout),
|
||||
source,
|
||||
parse_const_generic_ordering(ordering),
|
||||
layout.size,
|
||||
);
|
||||
|
||||
return ret_llval(bx, llval);
|
||||
}
|
||||
|
||||
// The rest falls back to below.
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let Some((instruction, ordering)) = atomic.split_once('_') else {
|
||||
bx.sess().dcx().emit_fatal(errors::MissingMemoryOrdering);
|
||||
};
|
||||
|
|
@ -350,14 +408,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
_ => bx.sess().dcx().emit_fatal(errors::UnknownAtomicOrdering),
|
||||
};
|
||||
|
||||
let invalid_monomorphization = |ty| {
|
||||
bx.tcx().dcx().emit_err(InvalidMonomorphization::BasicIntegerType {
|
||||
span,
|
||||
name,
|
||||
ty,
|
||||
});
|
||||
};
|
||||
|
||||
match instruction {
|
||||
"cxchg" | "cxchgweak" => {
|
||||
let Some((success, failure)) = ordering.split_once('_') else {
|
||||
|
|
@ -390,24 +440,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
"load" => {
|
||||
let ty = fn_args.type_at(0);
|
||||
if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr() {
|
||||
let layout = bx.layout_of(ty);
|
||||
let size = layout.size;
|
||||
let source = args[0].immediate();
|
||||
bx.atomic_load(
|
||||
bx.backend_type(layout),
|
||||
source,
|
||||
parse_ordering(bx, ordering),
|
||||
size,
|
||||
)
|
||||
} else {
|
||||
invalid_monomorphization(ty);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
"store" => {
|
||||
let ty = fn_args.type_at(0);
|
||||
if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr() {
|
||||
|
|
@ -538,14 +570,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
};
|
||||
|
||||
if result.layout.ty.is_bool() {
|
||||
OperandRef::from_immediate_or_packed_pair(bx, llval, result.layout)
|
||||
.val
|
||||
.store(bx, result);
|
||||
} else if !result.layout.ty.is_unit() {
|
||||
bx.store_to_place(llval, result.val);
|
||||
}
|
||||
Ok(())
|
||||
ret_llval(bx, llval)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -204,24 +204,25 @@ pub(crate) fn check_intrinsic_type(
|
|||
|
||||
// Each atomic op has variants with different suffixes (`_seq_cst`, `_acquire`, etc.). Use
|
||||
// string ops to strip the suffixes, because the variants all get the same treatment here.
|
||||
let (n_tps, inputs, output) = match split[1] {
|
||||
let (n_tps, n_cts, inputs, output) = match split[1] {
|
||||
"cxchg" | "cxchgweak" => (
|
||||
1,
|
||||
0,
|
||||
vec![Ty::new_mut_ptr(tcx, param(0)), param(0), param(0)],
|
||||
Ty::new_tup(tcx, &[param(0), tcx.types.bool]),
|
||||
),
|
||||
"load" => (1, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)),
|
||||
"store" => (1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit),
|
||||
"load" => (1, 1, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)),
|
||||
"store" => (1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit),
|
||||
|
||||
"xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" | "min" | "umax"
|
||||
| "umin" => (1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], param(0)),
|
||||
"fence" | "singlethreadfence" => (0, Vec::new(), tcx.types.unit),
|
||||
| "umin" => (1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], param(0)),
|
||||
"fence" | "singlethreadfence" => (0, 0, Vec::new(), tcx.types.unit),
|
||||
op => {
|
||||
tcx.dcx().emit_err(UnrecognizedAtomicOperation { span, op });
|
||||
return;
|
||||
}
|
||||
};
|
||||
(n_tps, 0, 0, inputs, output, hir::Safety::Unsafe)
|
||||
(n_tps, 0, n_cts, inputs, output, hir::Safety::Unsafe)
|
||||
} else if intrinsic_name == sym::contract_check_ensures {
|
||||
// contract_check_ensures::<Ret, C>(Ret, C) -> Ret
|
||||
// where C: for<'a> Fn(&'a Ret) -> bool,
|
||||
|
|
|
|||
|
|
@ -26,6 +26,19 @@ impl ConstInt {
|
|||
}
|
||||
}
|
||||
|
||||
/// An enum to represent the compiler-side view of `intrinsics::AtomicOrdering`.
|
||||
/// This lives here because there's a method in this file that needs it and it is entirely unclear
|
||||
/// where else to put this...
|
||||
#[derive(Debug)]
|
||||
pub enum AtomicOrdering {
|
||||
// These values must match `intrinsics::AtomicOrdering`!
|
||||
Relaxed = 0,
|
||||
Release = 1,
|
||||
Acquire = 2,
|
||||
AcqRel = 3,
|
||||
SeqCst = 4,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for ConstInt {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { int, signed, is_ptr_sized_integral } = *self;
|
||||
|
|
@ -318,6 +331,25 @@ impl ScalarInt {
|
|||
self.to_uint(tcx.data_layout.pointer_size).try_into().unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_atomic_ordering(self) -> AtomicOrdering {
|
||||
use AtomicOrdering::*;
|
||||
let val = self.to_u32();
|
||||
if val == Relaxed as u32 {
|
||||
Relaxed
|
||||
} else if val == Release as u32 {
|
||||
Release
|
||||
} else if val == Acquire as u32 {
|
||||
Acquire
|
||||
} else if val == AcqRel as u32 {
|
||||
AcqRel
|
||||
} else if val == SeqCst as u32 {
|
||||
SeqCst
|
||||
} else {
|
||||
panic!("not a valid atomic ordering")
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts the `ScalarInt` to `bool`.
|
||||
/// Panics if the `size` of the `ScalarInt` is not equal to 1 byte.
|
||||
/// Errors if it is not a valid `bool`.
|
||||
|
|
@ -488,7 +520,7 @@ from_scalar_int_for_x_signed!(i8, i16, i32, i64, i128);
|
|||
impl From<std::cmp::Ordering> for ScalarInt {
|
||||
#[inline]
|
||||
fn from(c: std::cmp::Ordering) -> Self {
|
||||
// Here we rely on `Ordering` having the same values in host and target!
|
||||
// Here we rely on `cmp::Ordering` having the same values in host and target!
|
||||
ScalarInt::from(c as i8)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,8 +74,8 @@ pub use self::closure::{
|
|||
place_to_string_for_capture,
|
||||
};
|
||||
pub use self::consts::{
|
||||
AnonConstKind, Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst,
|
||||
ValTree, ValTreeKind, Value,
|
||||
AnonConstKind, AtomicOrdering, Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt,
|
||||
UnevaluatedConst, ValTree, ValTreeKind, Value,
|
||||
};
|
||||
pub use self::context::{
|
||||
CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt,
|
||||
|
|
|
|||
|
|
@ -515,6 +515,7 @@ symbols! {
|
|||
async_iterator_poll_next,
|
||||
async_trait_bounds,
|
||||
atomic,
|
||||
atomic_load,
|
||||
atomic_mod,
|
||||
atomics,
|
||||
att_syntax,
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
//!
|
||||
//! The atomic intrinsics provide common atomic operations on machine
|
||||
//! words, with multiple possible memory orderings. See the
|
||||
//! [atomic types][crate::sync::atomic] docs for details.
|
||||
//! [atomic types][atomic] docs for details.
|
||||
//!
|
||||
//! # Unwinding
|
||||
//!
|
||||
|
|
@ -50,7 +50,7 @@
|
|||
)]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use crate::marker::{DiscriminantKind, Tuple};
|
||||
use crate::marker::{ConstParamTy, DiscriminantKind, Tuple};
|
||||
use crate::ptr;
|
||||
|
||||
pub mod fallback;
|
||||
|
|
@ -62,6 +62,20 @@ pub mod simd;
|
|||
#[cfg(all(target_has_atomic = "8", target_has_atomic = "32", target_has_atomic = "ptr"))]
|
||||
use crate::sync::atomic::{self, AtomicBool, AtomicI32, AtomicIsize, AtomicU32, Ordering};
|
||||
|
||||
/// A type for atomic ordering parameters for intrinsics. This is a separate type from
|
||||
/// `atomic::Ordering` so that we can make it `ConstParamTy` and fix the values used here without a
|
||||
/// risk of leaking that to stable code.
|
||||
#[derive(Debug, ConstParamTy, PartialEq, Eq)]
|
||||
pub enum AtomicOrdering {
|
||||
// These values must match the compiler's `AtomicOrdering` defined in
|
||||
// `rustc_middle/src/ty/consts/int.rs`!
|
||||
Relaxed = 0,
|
||||
Release = 1,
|
||||
Acquire = 2,
|
||||
AcqRel = 3,
|
||||
SeqCst = 4,
|
||||
}
|
||||
|
||||
// N.B., these intrinsics take raw pointers because they mutate aliased
|
||||
// memory, which is not valid for either `&` or `&mut`.
|
||||
|
||||
|
|
@ -391,6 +405,15 @@ pub unsafe fn atomic_cxchgweak_seqcst_acquire<T: Copy>(dst: *mut T, old: T, src:
|
|||
#[rustc_nounwind]
|
||||
pub unsafe fn atomic_cxchgweak_seqcst_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
|
||||
|
||||
/// Loads the current value of the pointer.
|
||||
/// `T` must be an integer or pointer type.
|
||||
///
|
||||
/// The stabilized version of this intrinsic is available on the
|
||||
/// [`atomic`] types via the `load` method. For example, [`AtomicBool::load`].
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
#[cfg(not(bootstrap))]
|
||||
pub unsafe fn atomic_load<T: Copy, const ORD: AtomicOrdering>(src: *const T) -> T;
|
||||
/// Loads the current value of the pointer.
|
||||
/// `T` must be an integer or pointer type.
|
||||
///
|
||||
|
|
@ -399,6 +422,7 @@ pub unsafe fn atomic_cxchgweak_seqcst_seqcst<T: Copy>(dst: *mut T, old: T, src:
|
|||
/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::load`].
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
#[cfg(bootstrap)]
|
||||
pub unsafe fn atomic_load_seqcst<T: Copy>(src: *const T) -> T;
|
||||
/// Loads the current value of the pointer.
|
||||
/// `T` must be an integer or pointer type.
|
||||
|
|
@ -408,6 +432,7 @@ pub unsafe fn atomic_load_seqcst<T: Copy>(src: *const T) -> T;
|
|||
/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::load`].
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
#[cfg(bootstrap)]
|
||||
pub unsafe fn atomic_load_acquire<T: Copy>(src: *const T) -> T;
|
||||
/// Loads the current value of the pointer.
|
||||
/// `T` must be an integer or pointer type.
|
||||
|
|
@ -417,6 +442,7 @@ pub unsafe fn atomic_load_acquire<T: Copy>(src: *const T) -> T;
|
|||
/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::load`].
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
#[cfg(bootstrap)]
|
||||
pub unsafe fn atomic_load_relaxed<T: Copy>(src: *const T) -> T;
|
||||
|
||||
/// Stores the value at the specified memory location.
|
||||
|
|
|
|||
|
|
@ -3822,6 +3822,7 @@ unsafe fn atomic_store<T: Copy>(dst: *mut T, val: T, order: Ordering) {
|
|||
|
||||
#[inline]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
#[cfg(bootstrap)]
|
||||
unsafe fn atomic_load<T: Copy>(dst: *const T, order: Ordering) -> T {
|
||||
// SAFETY: the caller must uphold the safety contract for `atomic_load`.
|
||||
unsafe {
|
||||
|
|
@ -3835,6 +3836,23 @@ unsafe fn atomic_load<T: Copy>(dst: *const T, order: Ordering) -> T {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
#[cfg(not(bootstrap))]
|
||||
unsafe fn atomic_load<T: Copy>(dst: *const T, order: Ordering) -> T {
|
||||
use intrinsics::AtomicOrdering;
|
||||
// SAFETY: the caller must uphold the safety contract for `atomic_load`.
|
||||
unsafe {
|
||||
match order {
|
||||
Relaxed => intrinsics::atomic_load::<T, { AtomicOrdering::Relaxed }>(dst),
|
||||
Acquire => intrinsics::atomic_load::<T, { AtomicOrdering::Acquire }>(dst),
|
||||
SeqCst => intrinsics::atomic_load::<T, { AtomicOrdering::SeqCst }>(dst),
|
||||
Release => panic!("there is no such thing as a release load"),
|
||||
AcqRel => panic!("there is no such thing as an acquire-release load"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(target_has_atomic)]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use rustc_middle::mir::BinOp;
|
||||
use rustc_middle::ty::AtomicOrdering;
|
||||
use rustc_middle::{mir, ty};
|
||||
|
||||
use self::helpers::check_intrinsic_arg_count;
|
||||
|
|
@ -19,6 +20,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
fn emulate_atomic_intrinsic(
|
||||
&mut self,
|
||||
intrinsic_name: &str,
|
||||
generic_args: ty::GenericArgsRef<'tcx>,
|
||||
args: &[OpTy<'tcx>],
|
||||
dest: &MPlaceTy<'tcx>,
|
||||
) -> InterpResult<'tcx, EmulateItemResult> {
|
||||
|
|
@ -35,6 +37,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn read_ord_const_generic(o: AtomicOrdering) -> AtomicReadOrd {
|
||||
match o {
|
||||
AtomicOrdering::SeqCst => AtomicReadOrd::SeqCst,
|
||||
AtomicOrdering::Acquire => AtomicReadOrd::Acquire,
|
||||
AtomicOrdering::Relaxed => AtomicReadOrd::Relaxed,
|
||||
_ => panic!("invalid read ordering `{o:?}`"),
|
||||
}
|
||||
}
|
||||
|
||||
fn write_ord(ord: &str) -> AtomicWriteOrd {
|
||||
match ord {
|
||||
"seqcst" => AtomicWriteOrd::SeqCst,
|
||||
|
|
@ -66,7 +77,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
}
|
||||
|
||||
match &*intrinsic_structure {
|
||||
["load", ord] => this.atomic_load(args, dest, read_ord(ord))?,
|
||||
// New-style intrinsics that use const generics
|
||||
["load"] => {
|
||||
let ordering = generic_args.const_at(1).to_value();
|
||||
let ordering =
|
||||
ordering.valtree.unwrap_branch()[0].unwrap_leaf().to_atomic_ordering();
|
||||
this.atomic_load(args, dest, read_ord_const_generic(ordering))?;
|
||||
}
|
||||
|
||||
// Old-style intrinsics that have the ordering in the intrinsic name
|
||||
["store", ord] => this.atomic_store(args, write_ord(ord))?,
|
||||
|
||||
["fence", ord] => this.atomic_fence_intrinsic(args, fence_ord(ord))?,
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
let this = self.eval_context_mut();
|
||||
|
||||
if let Some(name) = intrinsic_name.strip_prefix("atomic_") {
|
||||
return this.emulate_atomic_intrinsic(name, args, dest);
|
||||
return this.emulate_atomic_intrinsic(name, generic_args, args, dest);
|
||||
}
|
||||
if let Some(name) = intrinsic_name.strip_prefix("simd_") {
|
||||
return this.emulate_simd_intrinsic(name, generic_args, args, dest);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
//@compile-flags: -Zmiri-symbolic-alignment-check -Cdebug-assertions=no
|
||||
#![feature(core_intrinsics)]
|
||||
use std::intrinsics;
|
||||
|
||||
fn main() {
|
||||
// Do a 4-aligned u64 atomic access. That should be UB on all platforms,
|
||||
|
|
@ -7,7 +8,7 @@ fn main() {
|
|||
let z = [0u32; 2];
|
||||
let zptr = &z as *const _ as *const u64;
|
||||
unsafe {
|
||||
::std::intrinsics::atomic_load_seqcst(zptr);
|
||||
intrinsics::atomic_load::<_, { intrinsics::AtomicOrdering::SeqCst }>(zptr);
|
||||
//~^ERROR: accessing memory with alignment 4, but alignment 8 is required
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
error: Undefined Behavior: accessing memory with alignment ALIGN, but alignment ALIGN is required
|
||||
--> tests/fail/unaligned_pointers/atomic_unaligned.rs:LL:CC
|
||||
|
|
||||
LL | ::std::intrinsics::atomic_load_seqcst(zptr);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory with alignment ALIGN, but alignment ALIGN is required
|
||||
LL | intrinsics::atomic_load::<_, { intrinsics::AtomicOrdering::SeqCst }>(zptr);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory with alignment ALIGN, but alignment ALIGN is required
|
||||
|
|
||||
= help: this usually indicates that your program performed an invalid operation and caused Undefined Behavior
|
||||
= help: but due to `-Zmiri-symbolic-alignment-check`, alignment errors can also be false positives
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
//@ run-pass
|
||||
#![feature(core_intrinsics)]
|
||||
use std::intrinsics as rusti;
|
||||
use std::intrinsics::{self as rusti, AtomicOrdering};
|
||||
|
||||
pub fn main() {
|
||||
unsafe {
|
||||
let mut x: Box<_> = Box::new(1);
|
||||
|
||||
assert_eq!(rusti::atomic_load_seqcst(&*x), 1);
|
||||
assert_eq!(rusti::atomic_load::<_, { AtomicOrdering::SeqCst }>(&*x), 1);
|
||||
*x = 5;
|
||||
assert_eq!(rusti::atomic_load_acquire(&*x), 5);
|
||||
assert_eq!(rusti::atomic_load::<_, { AtomicOrdering::Acquire }>(&*x), 5);
|
||||
|
||||
rusti::atomic_store_seqcst(&mut *x, 3);
|
||||
assert_eq!(*x, 3);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#![allow(warnings)]
|
||||
#![crate_type = "rlib"]
|
||||
|
||||
use std::intrinsics;
|
||||
use std::intrinsics::{self, AtomicOrdering};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Foo(i64);
|
||||
|
|
@ -12,8 +12,8 @@ pub type Bar = &'static Fn();
|
|||
pub type Quux = [u8; 100];
|
||||
|
||||
pub unsafe fn test_bool_load(p: &mut bool, v: bool) {
|
||||
intrinsics::atomic_load_seqcst(p);
|
||||
//~^ ERROR `atomic_load_seqcst` intrinsic: expected basic integer type, found `bool`
|
||||
intrinsics::atomic_load::<_, { AtomicOrdering::SeqCst }>(p);
|
||||
//~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `bool`
|
||||
}
|
||||
|
||||
pub unsafe fn test_bool_store(p: &mut bool, v: bool) {
|
||||
|
|
@ -32,8 +32,8 @@ pub unsafe fn test_bool_cxchg(p: &mut bool, v: bool) {
|
|||
}
|
||||
|
||||
pub unsafe fn test_Foo_load(p: &mut Foo, v: Foo) {
|
||||
intrinsics::atomic_load_seqcst(p);
|
||||
//~^ ERROR `atomic_load_seqcst` intrinsic: expected basic integer type, found `Foo`
|
||||
intrinsics::atomic_load::<_, { AtomicOrdering::SeqCst }>(p);
|
||||
//~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `Foo`
|
||||
}
|
||||
|
||||
pub unsafe fn test_Foo_store(p: &mut Foo, v: Foo) {
|
||||
|
|
@ -52,7 +52,7 @@ pub unsafe fn test_Foo_cxchg(p: &mut Foo, v: Foo) {
|
|||
}
|
||||
|
||||
pub unsafe fn test_Bar_load(p: &mut Bar, v: Bar) {
|
||||
intrinsics::atomic_load_seqcst(p);
|
||||
intrinsics::atomic_load::<_, { AtomicOrdering::SeqCst }>(p);
|
||||
//~^ ERROR expected basic integer type, found `&dyn Fn()`
|
||||
}
|
||||
|
||||
|
|
@ -72,8 +72,8 @@ pub unsafe fn test_Bar_cxchg(p: &mut Bar, v: Bar) {
|
|||
}
|
||||
|
||||
pub unsafe fn test_Quux_load(p: &mut Quux, v: Quux) {
|
||||
intrinsics::atomic_load_seqcst(p);
|
||||
//~^ ERROR `atomic_load_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
|
||||
intrinsics::atomic_load::<_, { AtomicOrdering::SeqCst }>(p);
|
||||
//~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
|
||||
}
|
||||
|
||||
pub unsafe fn test_Quux_store(p: &mut Quux, v: Quux) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
error[E0511]: invalid monomorphization of `atomic_load_seqcst` intrinsic: expected basic integer type, found `bool`
|
||||
error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `bool`
|
||||
--> $DIR/non-integer-atomic.rs:15:5
|
||||
|
|
||||
LL | intrinsics::atomic_load_seqcst(p);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | intrinsics::atomic_load::<_, { AtomicOrdering::SeqCst }>(p);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0511]: invalid monomorphization of `atomic_store_seqcst` intrinsic: expected basic integer type, found `bool`
|
||||
--> $DIR/non-integer-atomic.rs:20:5
|
||||
|
|
@ -22,11 +22,11 @@ error[E0511]: invalid monomorphization of `atomic_cxchg_seqcst_seqcst` intrinsic
|
|||
LL | intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0511]: invalid monomorphization of `atomic_load_seqcst` intrinsic: expected basic integer type, found `Foo`
|
||||
error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `Foo`
|
||||
--> $DIR/non-integer-atomic.rs:35:5
|
||||
|
|
||||
LL | intrinsics::atomic_load_seqcst(p);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | intrinsics::atomic_load::<_, { AtomicOrdering::SeqCst }>(p);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0511]: invalid monomorphization of `atomic_store_seqcst` intrinsic: expected basic integer type, found `Foo`
|
||||
--> $DIR/non-integer-atomic.rs:40:5
|
||||
|
|
@ -46,11 +46,11 @@ error[E0511]: invalid monomorphization of `atomic_cxchg_seqcst_seqcst` intrinsic
|
|||
LL | intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0511]: invalid monomorphization of `atomic_load_seqcst` intrinsic: expected basic integer type, found `&dyn Fn()`
|
||||
error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `&dyn Fn()`
|
||||
--> $DIR/non-integer-atomic.rs:55:5
|
||||
|
|
||||
LL | intrinsics::atomic_load_seqcst(p);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | intrinsics::atomic_load::<_, { AtomicOrdering::SeqCst }>(p);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0511]: invalid monomorphization of `atomic_store_seqcst` intrinsic: expected basic integer type, found `&dyn Fn()`
|
||||
--> $DIR/non-integer-atomic.rs:60:5
|
||||
|
|
@ -70,11 +70,11 @@ error[E0511]: invalid monomorphization of `atomic_cxchg_seqcst_seqcst` intrinsic
|
|||
LL | intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0511]: invalid monomorphization of `atomic_load_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
|
||||
error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
|
||||
--> $DIR/non-integer-atomic.rs:75:5
|
||||
|
|
||||
LL | intrinsics::atomic_load_seqcst(p);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | intrinsics::atomic_load::<_, { AtomicOrdering::SeqCst }>(p);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0511]: invalid monomorphization of `atomic_store_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
|
||||
--> $DIR/non-integer-atomic.rs:80:5
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue