mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-13 12:36:47 +00:00
commit
fe3038f263
4
src/tools/miri/.github/workflows/ci.yml
vendored
4
src/tools/miri/.github/workflows/ci.yml
vendored
@ -35,10 +35,6 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set the tag GC interval to 1 on linux
|
||||
if: runner.os == 'Linux'
|
||||
run: echo "MIRIFLAGS=-Zmiri-provenance-gc=1" >> $GITHUB_ENV
|
||||
|
||||
# Cache the global cargo directory, but NOT the local `target` directory which
|
||||
# we cannot reuse anyway when the nightly changes (and it grows quite large
|
||||
# over time).
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
use std::env;
|
||||
use std::ffi::OsStr;
|
||||
use std::fmt::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::process::{self, Command};
|
||||
|
||||
@ -140,12 +141,20 @@ pub fn setup(
|
||||
// Do the build.
|
||||
if print_sysroot {
|
||||
// Be silent.
|
||||
} else if only_setup {
|
||||
// We want to be explicit.
|
||||
eprintln!("Preparing a sysroot for Miri (target: {target})...");
|
||||
} else {
|
||||
// We want to be quiet, but still let the user know that something is happening.
|
||||
eprint!("Preparing a sysroot for Miri (target: {target})... ");
|
||||
let mut msg = String::new();
|
||||
write!(msg, "Preparing a sysroot for Miri (target: {target})").unwrap();
|
||||
if verbose > 0 {
|
||||
write!(msg, " in {}", sysroot_dir.display()).unwrap();
|
||||
}
|
||||
write!(msg, "...").unwrap();
|
||||
if only_setup {
|
||||
// We want to be explicit.
|
||||
eprintln!("{msg}");
|
||||
} else {
|
||||
// We want to be quiet, but still let the user know that something is happening.
|
||||
eprint!("{msg} ");
|
||||
}
|
||||
}
|
||||
SysrootBuilder::new(&sysroot_dir, target)
|
||||
.build_mode(BuildMode::Check)
|
||||
|
@ -30,16 +30,23 @@ endgroup
|
||||
|
||||
# Test
|
||||
function run_tests {
|
||||
if [ -n "${MIRI_TEST_TARGET+exists}" ]; then
|
||||
if [ -n "${MIRI_TEST_TARGET:-}" ]; then
|
||||
begingroup "Testing foreign architecture $MIRI_TEST_TARGET"
|
||||
else
|
||||
begingroup "Testing host architecture"
|
||||
fi
|
||||
|
||||
## ui test suite
|
||||
./miri test
|
||||
if [ -z "${MIRI_TEST_TARGET+exists}" ]; then
|
||||
# Host-only tests: running these on all targets is unlikely to catch more problems and would
|
||||
# On the host and on Linux, also stress-test the GC.
|
||||
if [ -z "${MIRI_TEST_TARGET:-}" ] || [ "$HOST_TARGET" = x86_64-unknown-linux-gnu ]; then
|
||||
MIRIFLAGS="${MIRIFLAGS:-} -Zmiri-provenance-gc=1" ./miri test
|
||||
else
|
||||
./miri test
|
||||
fi
|
||||
|
||||
# Host-only tests
|
||||
if [ -z "${MIRI_TEST_TARGET:-}" ]; then
|
||||
# Running these on all targets is unlikely to catch more problems and would
|
||||
# cost a lot of CI time.
|
||||
|
||||
# Tests with optimizations (`-O` is what cargo passes, but crank MIR optimizations up all the
|
||||
@ -85,10 +92,11 @@ function run_tests {
|
||||
}
|
||||
|
||||
function run_tests_minimal {
|
||||
if [ -n "${MIRI_TEST_TARGET+exists}" ]; then
|
||||
if [ -n "${MIRI_TEST_TARGET:-}" ]; then
|
||||
begingroup "Testing MINIMAL foreign architecture $MIRI_TEST_TARGET: only testing $@"
|
||||
else
|
||||
begingroup "Testing MINIMAL host architecture: only testing $@"
|
||||
echo "run_tests_minimal requires MIRI_TEST_TARGET to be set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./miri test -- "$@"
|
||||
@ -99,16 +107,22 @@ function run_tests_minimal {
|
||||
endgroup
|
||||
}
|
||||
|
||||
# host
|
||||
## Main Testing Logic ##
|
||||
|
||||
# Host target.
|
||||
run_tests
|
||||
|
||||
# Extra targets.
|
||||
# In particular, fully cover all tier 1 targets.
|
||||
case $HOST_TARGET in
|
||||
x86_64-unknown-linux-gnu)
|
||||
MIRI_TEST_TARGET=i686-unknown-linux-gnu run_tests
|
||||
MIRI_TEST_TARGET=aarch64-unknown-linux-gnu run_tests
|
||||
MIRI_TEST_TARGET=aarch64-apple-darwin run_tests
|
||||
MIRI_TEST_TARGET=i686-pc-windows-gnu run_tests
|
||||
MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc atomic env align
|
||||
# Some targets are only partially supported.
|
||||
MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align
|
||||
MIRI_TEST_TARGET=i686-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align
|
||||
MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic
|
||||
MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal no_std integer strings wasm
|
||||
MIRI_TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std integer strings wasm
|
||||
|
@ -286,7 +286,7 @@ impl Command {
|
||||
"This will pull a copy of the rust-lang/rust history into this Miri checkout, growing it by about 1GB."
|
||||
);
|
||||
print!(
|
||||
"To avoid that, abort now and set the `--rustc-git` flag to an existing rustc checkout. Proceed? [y/N] "
|
||||
"To avoid that, abort now and set the `RUSTC_GIT` environment variable to an existing rustc checkout. Proceed? [y/N] "
|
||||
);
|
||||
std::io::stdout().flush()?;
|
||||
let mut answer = String::new();
|
||||
|
@ -1 +1 @@
|
||||
820f06b21f8373060ff7b515715b8440a6a6c197
|
||||
3668a8af1b81447c4afa1f82f60d7b94b71a549f
|
||||
|
@ -5,17 +5,18 @@ use std::time::Duration;
|
||||
|
||||
use log::trace;
|
||||
|
||||
use rustc_apfloat::ieee::{Double, Single};
|
||||
use rustc_hir::def::{DefKind, Namespace};
|
||||
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::ty::{
|
||||
self,
|
||||
layout::{IntegerExt as _, LayoutOf, TyAndLayout},
|
||||
IntTy, Ty, TyCtxt, UintTy,
|
||||
layout::{LayoutOf, TyAndLayout},
|
||||
FloatTy, IntTy, Ty, TyCtxt, UintTy,
|
||||
};
|
||||
use rustc_span::{def_id::CrateNum, sym, Span, Symbol};
|
||||
use rustc_target::abi::{Align, FieldIdx, FieldsShape, Integer, Size, Variants};
|
||||
use rustc_target::abi::{Align, FieldIdx, FieldsShape, Size, Variants};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use rand::RngCore;
|
||||
@ -565,10 +566,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
/// is part of the UNIX family. It panics showing a message with the `name` of the foreign function
|
||||
/// if this is not the case.
|
||||
fn assert_target_os_is_unix(&self, name: &str) {
|
||||
assert!(
|
||||
target_os_is_unix(self.eval_context_ref().tcx.sess.target.os.as_ref()),
|
||||
"`{name}` is only available for supported UNIX family targets",
|
||||
);
|
||||
assert!(self.target_os_is_unix(), "`{name}` is only available for unix targets",);
|
||||
}
|
||||
|
||||
fn target_os_is_unix(&self) -> bool {
|
||||
self.eval_context_ref().tcx.sess.target.families.iter().any(|f| f == "unix")
|
||||
}
|
||||
|
||||
/// Get last error variable as a place, lazily allocating thread-local storage for it if
|
||||
@ -985,65 +987,74 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts `f` to integer type `dest_ty` after rounding with mode `round`.
|
||||
/// Converts `src` from floating point to integer type `dest_ty`
|
||||
/// after rounding with mode `round`.
|
||||
/// Returns `None` if `f` is NaN or out of range.
|
||||
fn float_to_int_checked<F>(
|
||||
fn float_to_int_checked(
|
||||
&self,
|
||||
f: F,
|
||||
src: &ImmTy<'tcx, Provenance>,
|
||||
cast_to: TyAndLayout<'tcx>,
|
||||
round: rustc_apfloat::Round,
|
||||
) -> Option<ImmTy<'tcx, Provenance>>
|
||||
where
|
||||
F: rustc_apfloat::Float + Into<Scalar<Provenance>>,
|
||||
{
|
||||
) -> InterpResult<'tcx, Option<ImmTy<'tcx, Provenance>>> {
|
||||
let this = self.eval_context_ref();
|
||||
|
||||
let val = match cast_to.ty.kind() {
|
||||
// Unsigned
|
||||
ty::Uint(t) => {
|
||||
let size = Integer::from_uint_ty(this, *t).size();
|
||||
let res = f.to_u128_r(size.bits_usize(), round, &mut false);
|
||||
if res.status.intersects(
|
||||
rustc_apfloat::Status::INVALID_OP
|
||||
| rustc_apfloat::Status::OVERFLOW
|
||||
| rustc_apfloat::Status::UNDERFLOW,
|
||||
) {
|
||||
// Floating point value is NaN (flagged with INVALID_OP) or outside the range
|
||||
// of values of the integer type (flagged with OVERFLOW or UNDERFLOW).
|
||||
return None;
|
||||
} else {
|
||||
// Floating point value can be represented by the integer type after rounding.
|
||||
// The INEXACT flag is ignored on purpose to allow rounding.
|
||||
Scalar::from_uint(res.value, size)
|
||||
fn float_to_int_inner<'tcx, F: rustc_apfloat::Float>(
|
||||
this: &MiriInterpCx<'_, 'tcx>,
|
||||
src: F,
|
||||
cast_to: TyAndLayout<'tcx>,
|
||||
round: rustc_apfloat::Round,
|
||||
) -> (Scalar<Provenance>, rustc_apfloat::Status) {
|
||||
let int_size = cast_to.layout.size;
|
||||
match cast_to.ty.kind() {
|
||||
// Unsigned
|
||||
ty::Uint(_) => {
|
||||
let res = src.to_u128_r(int_size.bits_usize(), round, &mut false);
|
||||
(Scalar::from_uint(res.value, int_size), res.status)
|
||||
}
|
||||
}
|
||||
// Signed
|
||||
ty::Int(t) => {
|
||||
let size = Integer::from_int_ty(this, *t).size();
|
||||
let res = f.to_i128_r(size.bits_usize(), round, &mut false);
|
||||
if res.status.intersects(
|
||||
rustc_apfloat::Status::INVALID_OP
|
||||
| rustc_apfloat::Status::OVERFLOW
|
||||
| rustc_apfloat::Status::UNDERFLOW,
|
||||
) {
|
||||
// Floating point value is NaN (flagged with INVALID_OP) or outside the range
|
||||
// of values of the integer type (flagged with OVERFLOW or UNDERFLOW).
|
||||
return None;
|
||||
} else {
|
||||
// Floating point value can be represented by the integer type after rounding.
|
||||
// The INEXACT flag is ignored on purpose to allow rounding.
|
||||
Scalar::from_int(res.value, size)
|
||||
// Signed
|
||||
ty::Int(_) => {
|
||||
let res = src.to_i128_r(int_size.bits_usize(), round, &mut false);
|
||||
(Scalar::from_int(res.value, int_size), res.status)
|
||||
}
|
||||
// Nothing else
|
||||
_ =>
|
||||
span_bug!(
|
||||
this.cur_span(),
|
||||
"attempted float-to-int conversion with non-int output type {}",
|
||||
cast_to.ty,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
let (val, status) = match src.layout.ty.kind() {
|
||||
// f32
|
||||
ty::Float(FloatTy::F32) =>
|
||||
float_to_int_inner::<Single>(this, src.to_scalar().to_f32()?, cast_to, round),
|
||||
// f64
|
||||
ty::Float(FloatTy::F64) =>
|
||||
float_to_int_inner::<Double>(this, src.to_scalar().to_f64()?, cast_to, round),
|
||||
// Nothing else
|
||||
_ =>
|
||||
span_bug!(
|
||||
this.cur_span(),
|
||||
"attempted float-to-int conversion with non-int output type {}",
|
||||
cast_to.ty,
|
||||
"attempted float-to-int conversion with non-float input type {}",
|
||||
src.layout.ty,
|
||||
),
|
||||
};
|
||||
Some(ImmTy::from_scalar(val, cast_to))
|
||||
|
||||
if status.intersects(
|
||||
rustc_apfloat::Status::INVALID_OP
|
||||
| rustc_apfloat::Status::OVERFLOW
|
||||
| rustc_apfloat::Status::UNDERFLOW,
|
||||
) {
|
||||
// Floating point value is NaN (flagged with INVALID_OP) or outside the range
|
||||
// of values of the integer type (flagged with OVERFLOW or UNDERFLOW).
|
||||
Ok(None)
|
||||
} else {
|
||||
// Floating point value can be represented by the integer type after rounding.
|
||||
// The INEXACT flag is ignored on purpose to allow rounding.
|
||||
Ok(Some(ImmTy::from_scalar(val, cast_to)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an integer type that is twice wide as `ty`
|
||||
@ -1063,6 +1074,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
_ => span_bug!(this.cur_span(), "unexpected type: {ty:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks that target feature `target_feature` is enabled.
|
||||
///
|
||||
/// If not enabled, emits an UB error that states that the feature is
|
||||
/// required by `intrinsic`.
|
||||
fn expect_target_feature_for_intrinsic(
|
||||
&self,
|
||||
intrinsic: Symbol,
|
||||
target_feature: &str,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
let this = self.eval_context_ref();
|
||||
if !this.tcx.sess.unstable_target_features.contains(&Symbol::intern(target_feature)) {
|
||||
throw_ub_format!(
|
||||
"attempted to call intrinsic `{intrinsic}` that requires missing target feature {target_feature}"
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
|
||||
@ -1143,12 +1172,6 @@ pub fn get_local_crates(tcx: TyCtxt<'_>) -> Vec<CrateNum> {
|
||||
local_crates
|
||||
}
|
||||
|
||||
/// Helper function used inside the shims of foreign functions to check that
|
||||
/// `target_os` is a supported UNIX OS.
|
||||
pub fn target_os_is_unix(target_os: &str) -> bool {
|
||||
matches!(target_os, "linux" | "macos" | "freebsd" | "android")
|
||||
}
|
||||
|
||||
pub(crate) fn bool_to_simd_element(b: bool, size: Size) -> Scalar<Provenance> {
|
||||
// SIMD uses all-1 as pattern for "true". In two's complement,
|
||||
// -1 has all its bits set to one and `from_int` will truncate or
|
||||
|
@ -125,7 +125,7 @@ pub use crate::machine::{
|
||||
};
|
||||
pub use crate::mono_hash_map::MonoHashMap;
|
||||
pub use crate::operator::EvalContextExt as _;
|
||||
pub use crate::provenance_gc::{EvalContextExt as _, VisitProvenance, VisitWith, LiveAllocs};
|
||||
pub use crate::provenance_gc::{EvalContextExt as _, LiveAllocs, VisitProvenance, VisitWith};
|
||||
pub use crate::range_map::RangeMap;
|
||||
|
||||
/// Insert rustc arguments at the beginning of the argument list that Miri wants to be
|
||||
|
@ -157,15 +157,13 @@ pub struct LiveAllocs<'a, 'mir, 'tcx> {
|
||||
|
||||
impl LiveAllocs<'_, '_, '_> {
|
||||
pub fn is_live(&self, id: AllocId) -> bool {
|
||||
self.collected.contains(&id) ||
|
||||
self.ecx.is_alloc_live(id)
|
||||
self.collected.contains(&id) || self.ecx.is_alloc_live(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
|
||||
fn run_provenance_gc(&mut self) {
|
||||
|
||||
// We collect all tags from various parts of the interpreter, but also
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -196,10 +194,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
|
||||
|
||||
fn remove_unreachable_allocs(&mut self, allocs: FxHashSet<AllocId>) {
|
||||
let this = self.eval_context_mut();
|
||||
let allocs = LiveAllocs {
|
||||
ecx: this,
|
||||
collected: allocs,
|
||||
};
|
||||
let allocs = LiveAllocs { ecx: this, collected: allocs };
|
||||
this.machine.allocation_spans.borrow_mut().retain(|id, _| allocs.is_live(*id));
|
||||
this.machine.intptrcast.borrow_mut().remove_unreachable_allocs(&allocs);
|
||||
if let Some(borrow_tracker) = &this.machine.borrow_tracker {
|
||||
|
@ -9,7 +9,6 @@ use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_target::abi::Size;
|
||||
|
||||
use crate::helpers::target_os_is_unix;
|
||||
use crate::*;
|
||||
|
||||
/// Check whether an operation that writes to a target buffer was successful.
|
||||
@ -53,16 +52,15 @@ impl<'tcx> EnvVars<'tcx> {
|
||||
ecx: &mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>,
|
||||
config: &MiriConfig,
|
||||
) -> InterpResult<'tcx> {
|
||||
let target_os = ecx.tcx.sess.target.os.as_ref();
|
||||
|
||||
// Initialize the `env_vars` map.
|
||||
// Skip the loop entirely if we don't want to forward anything.
|
||||
if ecx.machine.communicate() || !config.forwarded_env_vars.is_empty() {
|
||||
for (name, value) in &config.env {
|
||||
let forward = ecx.machine.communicate()
|
||||
|| config.forwarded_env_vars.iter().any(|v| **v == *name);
|
||||
if forward {
|
||||
let var_ptr = match target_os {
|
||||
target if target_os_is_unix(target) =>
|
||||
let var_ptr = match ecx.tcx.sess.target.os.as_ref() {
|
||||
_ if ecx.target_os_is_unix() =>
|
||||
alloc_env_var_as_c_str(name.as_ref(), value.as_ref(), ecx)?,
|
||||
"windows" => alloc_env_var_as_wide_str(name.as_ref(), value.as_ref(), ecx)?,
|
||||
unsupported =>
|
||||
@ -75,7 +73,17 @@ impl<'tcx> EnvVars<'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
ecx.update_environ()
|
||||
|
||||
// Initialize the `environ` pointer when needed.
|
||||
if ecx.target_os_is_unix() {
|
||||
// This is memory backing an extern static, hence `ExternStatic`, not `Env`.
|
||||
let layout = ecx.machine.layouts.mut_raw_ptr;
|
||||
let place = ecx.allocate(layout, MiriMemoryKind::ExternStatic.into())?;
|
||||
ecx.write_null(&place)?;
|
||||
ecx.machine.env_vars.environ = Some(place);
|
||||
ecx.update_environ()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn cleanup<'mir>(
|
||||
@ -87,9 +95,11 @@ impl<'tcx> EnvVars<'tcx> {
|
||||
ecx.deallocate_ptr(ptr, None, MiriMemoryKind::Runtime.into())?;
|
||||
}
|
||||
// Deallocate environ var list.
|
||||
let environ = ecx.machine.env_vars.environ.as_ref().unwrap();
|
||||
let old_vars_ptr = ecx.read_pointer(environ)?;
|
||||
ecx.deallocate_ptr(old_vars_ptr, None, MiriMemoryKind::Runtime.into())?;
|
||||
if ecx.target_os_is_unix() {
|
||||
let environ = ecx.machine.env_vars.environ.as_ref().unwrap();
|
||||
let old_vars_ptr = ecx.read_pointer(environ)?;
|
||||
ecx.deallocate_ptr(old_vars_ptr, None, MiriMemoryKind::Runtime.into())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -127,6 +137,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
|
||||
let name_ptr = this.read_pointer(name_op)?;
|
||||
let name = this.read_os_str_from_c_str(name_ptr)?;
|
||||
this.read_environ()?;
|
||||
Ok(match this.machine.env_vars.map.get(name) {
|
||||
Some(var_ptr) => {
|
||||
// The offset is used to strip the "{name}=" part of the string.
|
||||
@ -275,7 +286,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
// Delete environment variable `{name}`
|
||||
if let Some(var) = this.machine.env_vars.map.remove(&name) {
|
||||
this.deallocate_ptr(var, None, MiriMemoryKind::Runtime.into())?;
|
||||
this.update_environ()?;
|
||||
}
|
||||
Ok(this.eval_windows("c", "TRUE"))
|
||||
} else {
|
||||
@ -284,7 +294,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
if let Some(var) = this.machine.env_vars.map.insert(name, var_ptr) {
|
||||
this.deallocate_ptr(var, None, MiriMemoryKind::Runtime.into())?;
|
||||
}
|
||||
this.update_environ()?;
|
||||
Ok(this.eval_windows("c", "TRUE"))
|
||||
}
|
||||
}
|
||||
@ -431,15 +440,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
fn update_environ(&mut self) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
// Deallocate the old environ list, if any.
|
||||
if let Some(environ) = this.machine.env_vars.environ.as_ref() {
|
||||
let old_vars_ptr = this.read_pointer(environ)?;
|
||||
let environ = this.machine.env_vars.environ.as_ref().unwrap().clone();
|
||||
let old_vars_ptr = this.read_pointer(&environ)?;
|
||||
if !this.ptr_is_null(old_vars_ptr)? {
|
||||
this.deallocate_ptr(old_vars_ptr, None, MiriMemoryKind::Runtime.into())?;
|
||||
} else {
|
||||
// No `environ` allocated yet, let's do that.
|
||||
// This is memory backing an extern static, hence `ExternStatic`, not `Env`.
|
||||
let layout = this.machine.layouts.mut_raw_ptr;
|
||||
let place = this.allocate(layout, MiriMemoryKind::ExternStatic.into())?;
|
||||
this.machine.env_vars.environ = Some(place);
|
||||
}
|
||||
|
||||
// Collect all the pointers to each variable in a vector.
|
||||
@ -459,11 +463,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
let place = this.project_field(&vars_place, idx)?;
|
||||
this.write_pointer(var, &place)?;
|
||||
}
|
||||
this.write_pointer(vars_place.ptr(), &this.machine.env_vars.environ.clone().unwrap())?;
|
||||
this.write_pointer(vars_place.ptr(), &environ)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reads from the `environ` static.
|
||||
/// We don't actually care about the result, but we care about this potentially causing a data race.
|
||||
fn read_environ(&self) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_ref();
|
||||
let environ = this.machine.env_vars.environ.as_ref().unwrap();
|
||||
let _vars_ptr = this.read_pointer(environ)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn getpid(&mut self) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
this.assert_target_os_is_unix("getpid");
|
||||
|
@ -22,7 +22,6 @@ use rustc_target::{
|
||||
};
|
||||
|
||||
use super::backtrace::EvalContextExt as _;
|
||||
use crate::helpers::target_os_is_unix;
|
||||
use crate::*;
|
||||
|
||||
/// Type of dynamic symbols (for `dlsym` et al)
|
||||
@ -1012,9 +1011,11 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
"llvm.arm.hint" if this.tcx.sess.target.arch == "arm" => {
|
||||
let [arg] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?;
|
||||
let arg = this.read_scalar(arg)?.to_i32()?;
|
||||
// Note that different arguments might have different target feature requirements.
|
||||
match arg {
|
||||
// YIELD
|
||||
1 => {
|
||||
this.expect_target_feature_for_intrinsic(link_name, "v6")?;
|
||||
this.yield_active_thread();
|
||||
}
|
||||
_ => {
|
||||
@ -1058,7 +1059,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
// Platform-specific shims
|
||||
_ =>
|
||||
return match this.tcx.sess.target.os.as_ref() {
|
||||
target_os if target_os_is_unix(target_os) =>
|
||||
_ if this.target_os_is_unix() =>
|
||||
shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_inner(
|
||||
this, link_name, abi, args, dest,
|
||||
),
|
||||
|
@ -365,36 +365,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
let [val] = check_arg_count(args)?;
|
||||
let val = this.read_immediate(val)?;
|
||||
|
||||
let res = match val.layout.ty.kind() {
|
||||
ty::Float(FloatTy::F32) => {
|
||||
let f = val.to_scalar().to_f32()?;
|
||||
this
|
||||
.float_to_int_checked(f, dest.layout, Round::TowardZero)
|
||||
.ok_or_else(|| {
|
||||
err_ub_format!(
|
||||
"`float_to_int_unchecked` intrinsic called on {f} which cannot be represented in target type `{:?}`",
|
||||
dest.layout.ty
|
||||
)
|
||||
})?
|
||||
}
|
||||
ty::Float(FloatTy::F64) => {
|
||||
let f = val.to_scalar().to_f64()?;
|
||||
this
|
||||
.float_to_int_checked(f, dest.layout, Round::TowardZero)
|
||||
.ok_or_else(|| {
|
||||
err_ub_format!(
|
||||
"`float_to_int_unchecked` intrinsic called on {f} which cannot be represented in target type `{:?}`",
|
||||
dest.layout.ty
|
||||
)
|
||||
})?
|
||||
}
|
||||
_ =>
|
||||
span_bug!(
|
||||
this.cur_span(),
|
||||
"`float_to_int_unchecked` called with non-float input type {:?}",
|
||||
val.layout.ty
|
||||
),
|
||||
};
|
||||
let res = this
|
||||
.float_to_int_checked(&val, dest.layout, Round::TowardZero)?
|
||||
.ok_or_else(|| {
|
||||
err_ub_format!(
|
||||
"`float_to_int_unchecked` intrinsic called on {val} which cannot be represented in target type `{:?}`",
|
||||
dest.layout.ty
|
||||
)
|
||||
})?;
|
||||
|
||||
this.write_immediate(*res, dest)?;
|
||||
}
|
||||
|
@ -447,22 +447,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
(ty::Float(_), ty::Int(_) | ty::Uint(_)) if safe_cast =>
|
||||
this.float_to_float_or_int(&op, dest.layout)?,
|
||||
// Float-to-int in unchecked mode
|
||||
(ty::Float(FloatTy::F32), ty::Int(_) | ty::Uint(_)) if unsafe_cast => {
|
||||
let f = op.to_scalar().to_f32()?;
|
||||
this.float_to_int_checked(f, dest.layout, Round::TowardZero)
|
||||
(ty::Float(_), ty::Int(_) | ty::Uint(_)) if unsafe_cast => {
|
||||
this.float_to_int_checked(&op, dest.layout, Round::TowardZero)?
|
||||
.ok_or_else(|| {
|
||||
err_ub_format!(
|
||||
"`simd_cast` intrinsic called on {f} which cannot be represented in target type `{:?}`",
|
||||
dest.layout.ty
|
||||
)
|
||||
})?
|
||||
}
|
||||
(ty::Float(FloatTy::F64), ty::Int(_) | ty::Uint(_)) if unsafe_cast => {
|
||||
let f = op.to_scalar().to_f64()?;
|
||||
this.float_to_int_checked(f, dest.layout, Round::TowardZero)
|
||||
.ok_or_else(|| {
|
||||
err_ub_format!(
|
||||
"`simd_cast` intrinsic called on {f} which cannot be represented in target type `{:?}`",
|
||||
"`simd_cast` intrinsic called on {op} which cannot be represented in target type `{:?}`",
|
||||
dest.layout.ty
|
||||
)
|
||||
})?
|
||||
|
@ -31,8 +31,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
let mut relative_clocks;
|
||||
|
||||
match this.tcx.sess.target.os.as_ref() {
|
||||
"linux" => {
|
||||
// Linux has two main kinds of clocks. REALTIME clocks return the actual time since the
|
||||
"linux" | "freebsd" => {
|
||||
// Linux and FreeBSD have two main kinds of clocks. REALTIME clocks return the actual time since the
|
||||
// Unix epoch, including effects which may cause time to move backwards such as NTP.
|
||||
// Linux further distinguishes regular and "coarse" clocks, but the "coarse" version
|
||||
// is just specified to be "faster and less precise", so we implement both the same way.
|
||||
|
@ -1,30 +0,0 @@
|
||||
use rustc_span::Symbol;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use crate::*;
|
||||
use shims::foreign_items::EmulateForeignItemResult;
|
||||
|
||||
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
||||
|
||||
pub fn is_dyn_sym(_name: &str) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
#[allow(unused, clippy::match_single_binding)] // there isn't anything here yet
|
||||
fn emulate_foreign_item_inner(
|
||||
&mut self,
|
||||
link_name: Symbol,
|
||||
abi: Abi,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, EmulateForeignItemResult> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
match link_name.as_str() {
|
||||
_ => return Ok(EmulateForeignItemResult::NotSupported),
|
||||
}
|
||||
|
||||
Ok(EmulateForeignItemResult::NeedsJumping)
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
pub mod foreign_items;
|
@ -15,7 +15,6 @@ use shims::unix::mem::EvalContextExt as _;
|
||||
use shims::unix::sync::EvalContextExt as _;
|
||||
use shims::unix::thread::EvalContextExt as _;
|
||||
|
||||
use shims::unix::android::foreign_items as android;
|
||||
use shims::unix::freebsd::foreign_items as freebsd;
|
||||
use shims::unix::linux::foreign_items as linux;
|
||||
use shims::unix::macos::foreign_items as macos;
|
||||
@ -32,11 +31,10 @@ fn is_dyn_sym(name: &str, target_os: &str) -> bool {
|
||||
// Give specific OSes a chance to allow their symbols.
|
||||
_ =>
|
||||
match target_os {
|
||||
"android" => android::is_dyn_sym(name),
|
||||
"freebsd" => freebsd::is_dyn_sym(name),
|
||||
"linux" => linux::is_dyn_sym(name),
|
||||
"macos" => macos::is_dyn_sym(name),
|
||||
target_os => panic!("unsupported Unix OS {target_os}"),
|
||||
_ => false,
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -163,6 +161,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
"ftruncate64" => {
|
||||
let [fd, length] =
|
||||
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
let fd = this.read_scalar(fd)?.to_i32()?;
|
||||
let length = this.read_scalar(length)?.to_i64()?;
|
||||
let result = this.ftruncate64(fd, length.into())?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"ftruncate" => {
|
||||
let [fd, length] =
|
||||
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
let fd = this.read_scalar(fd)?.to_i32()?;
|
||||
let length = this.read_scalar(length)?.to_int(this.libc_ty_layout("off_t").size)?;
|
||||
let result = this.ftruncate64(fd, length)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
@ -696,7 +704,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
_ => {
|
||||
let target_os = &*this.tcx.sess.target.os;
|
||||
return match target_os {
|
||||
"android" => android::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
|
||||
"freebsd" => freebsd::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
|
||||
"linux" => linux::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
|
||||
"macos" => macos::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
|
||||
|
@ -1504,16 +1504,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn ftruncate64(
|
||||
&mut self,
|
||||
fd_op: &OpTy<'tcx, Provenance>,
|
||||
length_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||
fn ftruncate64(&mut self, fd: i32, length: i128) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let fd = this.read_scalar(fd_op)?.to_i32()?;
|
||||
let length = this.read_scalar(length_op)?.to_i64()?;
|
||||
|
||||
// Reject if isolation is enabled.
|
||||
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
||||
this.reject_in_isolation("`ftruncate64`", reject_with)?;
|
||||
|
@ -72,13 +72,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
let result = this.lseek64(fd, offset, whence)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"ftruncate" => {
|
||||
let [fd, length] =
|
||||
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
// macOS is 64bit-only, so this is ftruncate64
|
||||
let result = this.ftruncate64(fd, length)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"realpath$DARWIN_EXTSN" => {
|
||||
let [path, resolved_path] =
|
||||
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
|
@ -5,7 +5,6 @@ mod mem;
|
||||
mod sync;
|
||||
mod thread;
|
||||
|
||||
mod android;
|
||||
mod freebsd;
|
||||
mod linux;
|
||||
mod macos;
|
||||
|
@ -18,6 +18,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, EmulateForeignItemResult> {
|
||||
let this = self.eval_context_mut();
|
||||
this.expect_target_feature_for_intrinsic(link_name, "aes")?;
|
||||
// Prefix should have already been checked.
|
||||
let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.aesni.").unwrap();
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::{mir, ty};
|
||||
use rustc_span::Symbol;
|
||||
use rustc_target::abi::Size;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
@ -119,53 +119,32 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||
}
|
||||
}
|
||||
|
||||
/// Floating point comparison operation
|
||||
///
|
||||
/// <https://www.felixcloutier.com/x86/cmpss>
|
||||
/// <https://www.felixcloutier.com/x86/cmpps>
|
||||
/// <https://www.felixcloutier.com/x86/cmpsd>
|
||||
/// <https://www.felixcloutier.com/x86/cmppd>
|
||||
#[derive(Copy, Clone)]
|
||||
enum FloatCmpOp {
|
||||
Eq,
|
||||
Lt,
|
||||
Le,
|
||||
Unord,
|
||||
Neq,
|
||||
/// Not less-than
|
||||
Nlt,
|
||||
/// Not less-or-equal
|
||||
Nle,
|
||||
/// Ordered, i.e. neither of them is NaN
|
||||
Ord,
|
||||
}
|
||||
|
||||
impl FloatCmpOp {
|
||||
/// Convert from the `imm` argument used to specify the comparison
|
||||
/// operation in intrinsics such as `llvm.x86.sse.cmp.ss`.
|
||||
fn from_intrinsic_imm(imm: i8, intrinsic: &str) -> InterpResult<'_, Self> {
|
||||
match imm {
|
||||
0 => Ok(Self::Eq),
|
||||
1 => Ok(Self::Lt),
|
||||
2 => Ok(Self::Le),
|
||||
3 => Ok(Self::Unord),
|
||||
4 => Ok(Self::Neq),
|
||||
5 => Ok(Self::Nlt),
|
||||
6 => Ok(Self::Nle),
|
||||
7 => Ok(Self::Ord),
|
||||
imm => {
|
||||
throw_unsup_format!("invalid `imm` parameter of {intrinsic}: {imm}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum FloatBinOp {
|
||||
/// Arithmetic operation
|
||||
Arith(mir::BinOp),
|
||||
/// Comparison
|
||||
Cmp(FloatCmpOp),
|
||||
///
|
||||
/// The semantics of this operator is a case distinction: we compare the two operands,
|
||||
/// and then we return one of the four booleans `gt`, `lt`, `eq`, `unord` depending on
|
||||
/// which class they fall into.
|
||||
///
|
||||
/// AVX supports all 16 combinations, SSE only a subset
|
||||
///
|
||||
/// <https://www.felixcloutier.com/x86/cmpss>
|
||||
/// <https://www.felixcloutier.com/x86/cmpps>
|
||||
/// <https://www.felixcloutier.com/x86/cmpsd>
|
||||
/// <https://www.felixcloutier.com/x86/cmppd>
|
||||
Cmp {
|
||||
/// Result when lhs < rhs
|
||||
gt: bool,
|
||||
/// Result when lhs > rhs
|
||||
lt: bool,
|
||||
/// Result when lhs == rhs
|
||||
eq: bool,
|
||||
/// Result when lhs is NaN or rhs is NaN
|
||||
unord: bool,
|
||||
},
|
||||
/// Minimum value (with SSE semantics)
|
||||
///
|
||||
/// <https://www.felixcloutier.com/x86/minss>
|
||||
@ -182,6 +161,51 @@ enum FloatBinOp {
|
||||
Max,
|
||||
}
|
||||
|
||||
impl FloatBinOp {
|
||||
/// Convert from the `imm` argument used to specify the comparison
|
||||
/// operation in intrinsics such as `llvm.x86.sse.cmp.ss`.
|
||||
fn cmp_from_imm<'tcx>(
|
||||
this: &crate::MiriInterpCx<'_, 'tcx>,
|
||||
imm: i8,
|
||||
intrinsic: Symbol,
|
||||
) -> InterpResult<'tcx, Self> {
|
||||
// Only bits 0..=4 are used, remaining should be zero.
|
||||
if imm & !0b1_1111 != 0 {
|
||||
throw_unsup_format!("invalid `imm` parameter of {intrinsic}: 0x{imm:x}");
|
||||
}
|
||||
// Bit 4 specifies whether the operation is quiet or signaling, which
|
||||
// we do not care in Miri.
|
||||
// Bits 0..=2 specifies the operation.
|
||||
// `gt` indicates the result to be returned when the LHS is strictly
|
||||
// greater than the RHS, and so on.
|
||||
let (gt, lt, eq, mut unord) = match imm & 0b111 {
|
||||
// Equal
|
||||
0x0 => (false, false, true, false),
|
||||
// Less-than
|
||||
0x1 => (false, true, false, false),
|
||||
// Less-or-equal
|
||||
0x2 => (false, true, true, false),
|
||||
// Unordered (either is NaN)
|
||||
0x3 => (false, false, false, true),
|
||||
// Not equal
|
||||
0x4 => (true, true, false, true),
|
||||
// Not less-than
|
||||
0x5 => (true, false, true, true),
|
||||
// Not less-or-equal
|
||||
0x6 => (true, false, false, true),
|
||||
// Ordered (neither is NaN)
|
||||
0x7 => (true, true, true, false),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
// When bit 3 is 1 (only possible in AVX), unord is toggled.
|
||||
if imm & 0b1000 != 0 {
|
||||
this.expect_target_feature_for_intrinsic(intrinsic, "avx")?;
|
||||
unord = !unord;
|
||||
}
|
||||
Ok(Self::Cmp { gt, lt, eq, unord })
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs `which` scalar operation on `left` and `right` and returns
|
||||
/// the result.
|
||||
fn bin_op_float<'tcx, F: rustc_apfloat::Float>(
|
||||
@ -195,20 +219,15 @@ fn bin_op_float<'tcx, F: rustc_apfloat::Float>(
|
||||
let res = this.wrapping_binary_op(which, left, right)?;
|
||||
Ok(res.to_scalar())
|
||||
}
|
||||
FloatBinOp::Cmp(which) => {
|
||||
FloatBinOp::Cmp { gt, lt, eq, unord } => {
|
||||
let left = left.to_scalar().to_float::<F>()?;
|
||||
let right = right.to_scalar().to_float::<F>()?;
|
||||
// FIXME: Make sure that these operations match the semantics
|
||||
// of cmpps/cmpss/cmppd/cmpsd
|
||||
let res = match which {
|
||||
FloatCmpOp::Eq => left == right,
|
||||
FloatCmpOp::Lt => left < right,
|
||||
FloatCmpOp::Le => left <= right,
|
||||
FloatCmpOp::Unord => left.is_nan() || right.is_nan(),
|
||||
FloatCmpOp::Neq => left != right,
|
||||
FloatCmpOp::Nlt => !(left < right),
|
||||
FloatCmpOp::Nle => !(left <= right),
|
||||
FloatCmpOp::Ord => !left.is_nan() && !right.is_nan(),
|
||||
|
||||
let res = match left.partial_cmp(&right) {
|
||||
None => unord,
|
||||
Some(std::cmp::Ordering::Less) => lt,
|
||||
Some(std::cmp::Ordering::Equal) => eq,
|
||||
Some(std::cmp::Ordering::Greater) => gt,
|
||||
};
|
||||
Ok(bool_to_simd_element(res, Size::from_bits(F::BITS)))
|
||||
}
|
||||
@ -312,6 +331,43 @@ fn bin_op_simd_float_all<'tcx, F: rustc_apfloat::Float>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Converts each element of `op` from floating point to signed integer.
|
||||
///
|
||||
/// When the input value is NaN or out of range, fall back to minimum value.
|
||||
///
|
||||
/// If `op` has more elements than `dest`, extra elements are ignored. If `op`
|
||||
/// has less elements than `dest`, the rest is filled with zeros.
|
||||
fn convert_float_to_int<'tcx>(
|
||||
this: &mut crate::MiriInterpCx<'_, 'tcx>,
|
||||
op: &OpTy<'tcx, Provenance>,
|
||||
rnd: rustc_apfloat::Round,
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
let (op, op_len) = this.operand_to_simd(op)?;
|
||||
let (dest, dest_len) = this.place_to_simd(dest)?;
|
||||
|
||||
// Output must be *signed* integers.
|
||||
assert!(matches!(dest.layout.field(this, 0).ty.kind(), ty::Int(_)));
|
||||
|
||||
for i in 0..op_len.min(dest_len) {
|
||||
let op = this.read_immediate(&this.project_index(&op, i)?)?;
|
||||
let dest = this.project_index(&dest, i)?;
|
||||
|
||||
let res = this.float_to_int_checked(&op, dest.layout, rnd)?.unwrap_or_else(|| {
|
||||
// Fallback to minimum acording to SSE/AVX semantics.
|
||||
ImmTy::from_int(dest.layout.size.signed_int_min(), dest.layout)
|
||||
});
|
||||
this.write_immediate(*res, &dest)?;
|
||||
}
|
||||
// Fill remainder with zeros
|
||||
for i in op_len..dest_len {
|
||||
let dest = this.project_index(&dest, i)?;
|
||||
this.write_scalar(Scalar::from_int(0, dest.layout.size), &dest)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Horizontaly performs `which` operation on adjacent values of
|
||||
/// `left` and `right` SIMD vectors and stores the result in `dest`.
|
||||
fn horizontal_bin_op<'tcx>(
|
||||
|
@ -5,7 +5,7 @@ use rustc_target::spec::abi::Abi;
|
||||
|
||||
use rand::Rng as _;
|
||||
|
||||
use super::{bin_op_simd_float_all, bin_op_simd_float_first, FloatBinOp, FloatCmpOp};
|
||||
use super::{bin_op_simd_float_all, bin_op_simd_float_first, FloatBinOp};
|
||||
use crate::*;
|
||||
use shims::foreign_items::EmulateForeignItemResult;
|
||||
|
||||
@ -21,6 +21,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, EmulateForeignItemResult> {
|
||||
let this = self.eval_context_mut();
|
||||
this.expect_target_feature_for_intrinsic(link_name, "sse")?;
|
||||
// Prefix should have already been checked.
|
||||
let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse.").unwrap();
|
||||
// All these intrinsics operate on 128-bit (f32x4) SIMD vectors unless stated otherwise.
|
||||
@ -95,33 +96,37 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||
|
||||
unary_op_ps(this, which, op, dest)?;
|
||||
}
|
||||
// Used to implement the _mm_cmp_ss function.
|
||||
// Used to implement the _mm_cmp*_ss functions.
|
||||
// Performs a comparison operation on the first component of `left`
|
||||
// and `right`, returning 0 if false or `u32::MAX` if true. The remaining
|
||||
// components are copied from `left`.
|
||||
// _mm_cmp_ss is actually an AVX function where the operation is specified
|
||||
// by a const parameter.
|
||||
// _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_ss are SSE functions
|
||||
// with hard-coded operations.
|
||||
"cmp.ss" => {
|
||||
let [left, right, imm] =
|
||||
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
|
||||
let which = FloatBinOp::Cmp(FloatCmpOp::from_intrinsic_imm(
|
||||
this.read_scalar(imm)?.to_i8()?,
|
||||
"llvm.x86.sse.cmp.ss",
|
||||
)?);
|
||||
let which =
|
||||
FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?;
|
||||
|
||||
bin_op_simd_float_first::<Single>(this, which, left, right, dest)?;
|
||||
}
|
||||
// Used to implement the _mm_cmp_ps function.
|
||||
// Used to implement the _mm_cmp*_ps functions.
|
||||
// Performs a comparison operation on each component of `left`
|
||||
// and `right`. For each component, returns 0 if false or u32::MAX
|
||||
// if true.
|
||||
// _mm_cmp_ps is actually an AVX function where the operation is specified
|
||||
// by a const parameter.
|
||||
// _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_ps are SSE functions
|
||||
// with hard-coded operations.
|
||||
"cmp.ps" => {
|
||||
let [left, right, imm] =
|
||||
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
|
||||
let which = FloatBinOp::Cmp(FloatCmpOp::from_intrinsic_imm(
|
||||
this.read_scalar(imm)?.to_i8()?,
|
||||
"llvm.x86.sse.cmp.ps",
|
||||
)?);
|
||||
let which =
|
||||
FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?;
|
||||
|
||||
bin_op_simd_float_all::<Single>(this, which, left, right, dest)?;
|
||||
}
|
||||
@ -163,7 +168,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||
let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
let (op, _) = this.operand_to_simd(op)?;
|
||||
|
||||
let op = this.read_scalar(&this.project_index(&op, 0)?)?.to_f32()?;
|
||||
let op = this.read_immediate(&this.project_index(&op, 0)?)?;
|
||||
|
||||
let rnd = match unprefixed_name {
|
||||
// "current SSE rounding mode", assume nearest
|
||||
@ -175,7 +180,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let res = this.float_to_int_checked(op, dest.layout, rnd).unwrap_or_else(|| {
|
||||
let res = this.float_to_int_checked(&op, dest.layout, rnd)?.unwrap_or_else(|| {
|
||||
// Fallback to minimum acording to SSE semantics.
|
||||
ImmTy::from_int(dest.layout.size.signed_int_min(), dest.layout)
|
||||
});
|
||||
|
@ -4,7 +4,7 @@ use rustc_middle::ty::Ty;
|
||||
use rustc_span::Symbol;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use super::{bin_op_simd_float_all, bin_op_simd_float_first, FloatBinOp, FloatCmpOp};
|
||||
use super::{bin_op_simd_float_all, bin_op_simd_float_first, convert_float_to_int, FloatBinOp};
|
||||
use crate::*;
|
||||
use shims::foreign_items::EmulateForeignItemResult;
|
||||
|
||||
@ -20,6 +20,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, EmulateForeignItemResult> {
|
||||
let this = self.eval_context_mut();
|
||||
this.expect_target_feature_for_intrinsic(link_name, "sse2")?;
|
||||
// Prefix should have already been checked.
|
||||
let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse2.").unwrap();
|
||||
|
||||
@ -259,37 +260,42 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||
this.write_scalar(Scalar::from_u64(res), &dest)?;
|
||||
}
|
||||
}
|
||||
// Used to implement the _mm_cvtps_epi32 and _mm_cvttps_epi32 functions.
|
||||
// Converts packed f32 to packed i32.
|
||||
"cvtps2dq" | "cvttps2dq" => {
|
||||
// Used to implement the _mm_cvtps_epi32, _mm_cvttps_epi32, _mm_cvtpd_epi32
|
||||
// and _mm_cvttpd_epi32 functions.
|
||||
// Converts packed f32/f64 to packed i32.
|
||||
"cvtps2dq" | "cvttps2dq" | "cvtpd2dq" | "cvttpd2dq" => {
|
||||
let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
|
||||
let (op, op_len) = this.operand_to_simd(op)?;
|
||||
let (dest, dest_len) = this.place_to_simd(dest)?;
|
||||
|
||||
assert_eq!(dest_len, op_len);
|
||||
let (op_len, _) = op.layout.ty.simd_size_and_type(*this.tcx);
|
||||
let (dest_len, _) = dest.layout.ty.simd_size_and_type(*this.tcx);
|
||||
match unprefixed_name {
|
||||
"cvtps2dq" | "cvttps2dq" => {
|
||||
// f32x4 to i32x4 conversion
|
||||
assert_eq!(op_len, 4);
|
||||
assert_eq!(dest_len, op_len);
|
||||
}
|
||||
"cvtpd2dq" | "cvttpd2dq" => {
|
||||
// f64x2 to i32x4 conversion
|
||||
// the last two values are filled with zeros
|
||||
assert_eq!(op_len, 2);
|
||||
assert_eq!(dest_len, 4);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
let rnd = match unprefixed_name {
|
||||
// "current SSE rounding mode", assume nearest
|
||||
// https://www.felixcloutier.com/x86/cvtps2dq
|
||||
"cvtps2dq" => rustc_apfloat::Round::NearestTiesToEven,
|
||||
// https://www.felixcloutier.com/x86/cvtpd2dq
|
||||
"cvtps2dq" | "cvtpd2dq" => rustc_apfloat::Round::NearestTiesToEven,
|
||||
// always truncate
|
||||
// https://www.felixcloutier.com/x86/cvttps2dq
|
||||
"cvttps2dq" => rustc_apfloat::Round::TowardZero,
|
||||
// https://www.felixcloutier.com/x86/cvttpd2dq
|
||||
"cvttps2dq" | "cvttpd2dq" => rustc_apfloat::Round::TowardZero,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
for i in 0..dest_len {
|
||||
let op = this.read_scalar(&this.project_index(&op, i)?)?.to_f32()?;
|
||||
let dest = this.project_index(&dest, i)?;
|
||||
|
||||
let res =
|
||||
this.float_to_int_checked(op, dest.layout, rnd).unwrap_or_else(|| {
|
||||
// Fallback to minimum acording to SSE2 semantics.
|
||||
ImmTy::from_int(i32::MIN, this.machine.layouts.i32)
|
||||
});
|
||||
this.write_immediate(*res, &dest)?;
|
||||
}
|
||||
convert_float_to_int(this, op, rnd, dest)?;
|
||||
}
|
||||
// Used to implement the _mm_packs_epi16 function.
|
||||
// Converts two 16-bit integer vectors to a single 8-bit integer
|
||||
@ -461,18 +467,20 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||
this.write_scalar(res, &dest)?;
|
||||
}
|
||||
}
|
||||
// Used to implement the _mm_cmp*_sd function.
|
||||
// Used to implement the _mm_cmp*_sd functions.
|
||||
// Performs a comparison operation on the first component of `left`
|
||||
// and `right`, returning 0 if false or `u64::MAX` if true. The remaining
|
||||
// components are copied from `left`.
|
||||
// _mm_cmp_sd is actually an AVX function where the operation is specified
|
||||
// by a const parameter.
|
||||
// _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_sd are SSE2 functions
|
||||
// with hard-coded operations.
|
||||
"cmp.sd" => {
|
||||
let [left, right, imm] =
|
||||
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
|
||||
let which = FloatBinOp::Cmp(FloatCmpOp::from_intrinsic_imm(
|
||||
this.read_scalar(imm)?.to_i8()?,
|
||||
"llvm.x86.sse2.cmp.sd",
|
||||
)?);
|
||||
let which =
|
||||
FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?;
|
||||
|
||||
bin_op_simd_float_first::<Double>(this, which, left, right, dest)?;
|
||||
}
|
||||
@ -480,14 +488,16 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||
// Performs a comparison operation on each component of `left`
|
||||
// and `right`. For each component, returns 0 if false or `u64::MAX`
|
||||
// if true.
|
||||
// _mm_cmp_pd is actually an AVX function where the operation is specified
|
||||
// by a const parameter.
|
||||
// _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_pd are SSE2 functions
|
||||
// with hard-coded operations.
|
||||
"cmp.pd" => {
|
||||
let [left, right, imm] =
|
||||
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
|
||||
let which = FloatBinOp::Cmp(FloatCmpOp::from_intrinsic_imm(
|
||||
this.read_scalar(imm)?.to_i8()?,
|
||||
"llvm.x86.sse2.cmp.pd",
|
||||
)?);
|
||||
let which =
|
||||
FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?;
|
||||
|
||||
bin_op_simd_float_all::<Double>(this, which, left, right, dest)?;
|
||||
}
|
||||
@ -522,45 +532,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||
};
|
||||
this.write_scalar(Scalar::from_i32(i32::from(res)), dest)?;
|
||||
}
|
||||
// Used to implement the _mm_cvtpd_epi32 and _mm_cvttpd_epi32 functions.
|
||||
// Converts packed f64 to packed i32.
|
||||
"cvtpd2dq" | "cvttpd2dq" => {
|
||||
let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
|
||||
let (op, op_len) = this.operand_to_simd(op)?;
|
||||
let (dest, dest_len) = this.place_to_simd(dest)?;
|
||||
|
||||
// op is f64x2, dest is i32x4
|
||||
assert_eq!(op_len, 2);
|
||||
assert_eq!(dest_len, 4);
|
||||
|
||||
let rnd = match unprefixed_name {
|
||||
// "current SSE rounding mode", assume nearest
|
||||
// https://www.felixcloutier.com/x86/cvtpd2dq
|
||||
"cvtpd2dq" => rustc_apfloat::Round::NearestTiesToEven,
|
||||
// always truncate
|
||||
// https://www.felixcloutier.com/x86/cvttpd2dq
|
||||
"cvttpd2dq" => rustc_apfloat::Round::TowardZero,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
for i in 0..op_len {
|
||||
let op = this.read_scalar(&this.project_index(&op, i)?)?.to_f64()?;
|
||||
let dest = this.project_index(&dest, i)?;
|
||||
|
||||
let res =
|
||||
this.float_to_int_checked(op, dest.layout, rnd).unwrap_or_else(|| {
|
||||
// Fallback to minimum acording to SSE2 semantics.
|
||||
ImmTy::from_int(i32::MIN, this.machine.layouts.i32)
|
||||
});
|
||||
this.write_immediate(*res, &dest)?;
|
||||
}
|
||||
// Fill the remaining with zeros
|
||||
for i in op_len..dest_len {
|
||||
let dest = this.project_index(&dest, i)?;
|
||||
this.write_scalar(Scalar::from_i32(0), &dest)?;
|
||||
}
|
||||
}
|
||||
// Use to implement the _mm_cvtsd_si32, _mm_cvttsd_si32,
|
||||
// _mm_cvtsd_si64 and _mm_cvttsd_si64 functions.
|
||||
// Converts the first component of `op` from f64 to i32/i64.
|
||||
@ -568,7 +539,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||
let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
let (op, _) = this.operand_to_simd(op)?;
|
||||
|
||||
let op = this.read_scalar(&this.project_index(&op, 0)?)?.to_f64()?;
|
||||
let op = this.read_immediate(&this.project_index(&op, 0)?)?;
|
||||
|
||||
let rnd = match unprefixed_name {
|
||||
// "current SSE rounding mode", assume nearest
|
||||
@ -580,7 +551,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let res = this.float_to_int_checked(op, dest.layout, rnd).unwrap_or_else(|| {
|
||||
let res = this.float_to_int_checked(&op, dest.layout, rnd)?.unwrap_or_else(|| {
|
||||
// Fallback to minimum acording to SSE semantics.
|
||||
ImmTy::from_int(dest.layout.size.signed_int_min(), dest.layout)
|
||||
});
|
||||
|
@ -18,6 +18,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, EmulateForeignItemResult> {
|
||||
let this = self.eval_context_mut();
|
||||
this.expect_target_feature_for_intrinsic(link_name, "sse3")?;
|
||||
// Prefix should have already been checked.
|
||||
let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse3.").unwrap();
|
||||
|
||||
|
@ -18,6 +18,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, EmulateForeignItemResult> {
|
||||
let this = self.eval_context_mut();
|
||||
this.expect_target_feature_for_intrinsic(link_name, "sse4.1")?;
|
||||
// Prefix should have already been checked.
|
||||
let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse41.").unwrap();
|
||||
|
||||
@ -199,7 +200,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||
Scalar::from_u16(min_index.try_into().unwrap()),
|
||||
&this.project_index(&dest, 1)?,
|
||||
)?;
|
||||
// Fill remaining with zeros
|
||||
// Fill remainder with zeros
|
||||
for i in 2..dest_len {
|
||||
this.write_scalar(Scalar::from_u16(0), &this.project_index(&dest, i)?)?;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, EmulateForeignItemResult> {
|
||||
let this = self.eval_context_mut();
|
||||
this.expect_target_feature_for_intrinsic(link_name, "ssse3")?;
|
||||
// Prefix should have already been checked.
|
||||
let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.ssse3.").unwrap();
|
||||
|
||||
|
17
src/tools/miri/tests/fail-dep/shims/env-set_var-data-race.rs
Normal file
17
src/tools/miri/tests/fail-dep/shims/env-set_var-data-race.rs
Normal file
@ -0,0 +1,17 @@
|
||||
//@compile-flags: -Zmiri-disable-isolation -Zmiri-preemption-rate=0
|
||||
//@ignore-target-windows: No libc on Windows
|
||||
|
||||
use std::env;
|
||||
use std::thread;
|
||||
|
||||
fn main() {
|
||||
let t = thread::spawn(|| unsafe {
|
||||
// Access the environment in another thread without taking the env lock.
|
||||
// This represents some C code that queries the environment.
|
||||
libc::getenv(b"TZ\0".as_ptr().cast()); //~ERROR: Data race detected
|
||||
});
|
||||
// Meanwhile, the main thread uses the "safe" Rust env accessor.
|
||||
env::set_var("MY_RUST_VAR", "Ferris");
|
||||
|
||||
t.join().unwrap();
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `main` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
--> $DIR/env-set_var-data-race.rs:LL:CC
|
||||
|
|
||||
LL | libc::getenv(b"TZ/0".as_ptr().cast());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) non-atomic write on thread `main` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
|
||||
|
|
||||
help: and (1) occurred earlier here
|
||||
--> $DIR/env-set_var-data-race.rs:LL:CC
|
||||
|
|
||||
LL | env::set_var("MY_RUST_VAR", "Ferris");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside closure at $DIR/env-set_var-data-race.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inf which cannot be represented in target type `i32`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inf_f32 which cannot be represented in target type `i32`
|
||||
--> $DIR/float_to_int_32_inf1.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f32, i32>(f32::INFINITY);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on +Inf which cannot be represented in target type `i32`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on +Inf_f32 which cannot be represented in target type `i32`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inf which cannot be represented in target type `i32`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inf_f32 which cannot be represented in target type `i32`
|
||||
--> $DIR/float_to_int_32_infneg1.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f32, i32>(f32::NEG_INFINITY);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inf which cannot be represented in target type `i32`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inf_f32 which cannot be represented in target type `i32`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaN which cannot be represented in target type `u32`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaN_f32 which cannot be represented in target type `u32`
|
||||
--> $DIR/float_to_int_32_nan.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f32, u32>(f32::NAN);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaN which cannot be represented in target type `u32`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaN_f32 which cannot be represented in target type `u32`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaN which cannot be represented in target type `u32`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaN_f32 which cannot be represented in target type `u32`
|
||||
--> $DIR/float_to_int_32_nanneg.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f32, u32>(-f32::NAN);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaN which cannot be represented in target type `u32`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaN_f32 which cannot be represented in target type `u32`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1 which cannot be represented in target type `u32`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1f32 which cannot be represented in target type `u32`
|
||||
--> $DIR/float_to_int_32_neg.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f32, u32>(-1.000000001f32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1 which cannot be represented in target type `u32`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1f32 which cannot be represented in target type `u32`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 2.14748365E+9 which cannot be represented in target type `i32`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 2.14748365E+9f32 which cannot be represented in target type `i32`
|
||||
--> $DIR/float_to_int_32_too_big1.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f32, i32>(2147483648.0f32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 2.14748365E+9 which cannot be represented in target type `i32`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 2.14748365E+9f32 which cannot be represented in target type `i32`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 4.2949673E+9 which cannot be represented in target type `u32`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 4.2949673E+9f32 which cannot be represented in target type `u32`
|
||||
--> $DIR/float_to_int_32_too_big2.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f32, u32>((u32::MAX - 127) as f32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 4.2949673E+9 which cannot be represented in target type `u32`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 4.2949673E+9f32 which cannot be represented in target type `u32`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -2.1474839E+9 which cannot be represented in target type `i32`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -2.1474839E+9f32 which cannot be represented in target type `i32`
|
||||
--> $DIR/float_to_int_32_too_small1.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f32, i32>(-2147483904.0f32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -2.1474839E+9 which cannot be represented in target type `i32`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -2.1474839E+9f32 which cannot be represented in target type `i32`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inf which cannot be represented in target type `u128`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inf_f64 which cannot be represented in target type `u128`
|
||||
--> $DIR/float_to_int_64_inf1.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f64, u128>(f64::INFINITY);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on +Inf which cannot be represented in target type `u128`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on +Inf_f64 which cannot be represented in target type `u128`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inf which cannot be represented in target type `u128`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inf_f64 which cannot be represented in target type `u128`
|
||||
--> $DIR/float_to_int_64_infneg1.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f64, u128>(f64::NEG_INFINITY);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inf which cannot be represented in target type `u128`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inf_f64 which cannot be represented in target type `u128`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inf which cannot be represented in target type `i128`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inf_f64 which cannot be represented in target type `i128`
|
||||
--> $DIR/float_to_int_64_infneg2.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f64, i128>(f64::NEG_INFINITY);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inf which cannot be represented in target type `i128`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inf_f64 which cannot be represented in target type `i128`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaN which cannot be represented in target type `u32`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaN_f64 which cannot be represented in target type `u32`
|
||||
--> $DIR/float_to_int_64_nan.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f64, u32>(f64::NAN);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaN which cannot be represented in target type `u32`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaN_f64 which cannot be represented in target type `u32`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1.0000000000000999 which cannot be represented in target type `u128`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1.0000000000000999f64 which cannot be represented in target type `u128`
|
||||
--> $DIR/float_to_int_64_neg.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f64, u128>(-1.0000000000001f64);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1.0000000000000999 which cannot be represented in target type `u128`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1.0000000000000999f64 which cannot be represented in target type `u128`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 2147483648 which cannot be represented in target type `i32`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 2147483648f64 which cannot be represented in target type `i32`
|
||||
--> $DIR/float_to_int_64_too_big1.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f64, i32>(2147483648.0f64);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 2147483648 which cannot be represented in target type `i32`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 2147483648f64 which cannot be represented in target type `i32`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 9.2233720368547758E+18 which cannot be represented in target type `i64`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 9.2233720368547758E+18f64 which cannot be represented in target type `i64`
|
||||
--> $DIR/float_to_int_64_too_big2.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f64, i64>(9223372036854775808.0f64);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 9.2233720368547758E+18 which cannot be represented in target type `i64`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 9.2233720368547758E+18f64 which cannot be represented in target type `i64`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 1.8446744073709552E+19 which cannot be represented in target type `u64`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 1.8446744073709552E+19f64 which cannot be represented in target type `u64`
|
||||
--> $DIR/float_to_int_64_too_big3.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f64, u64>(18446744073709551616.0f64);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 1.8446744073709552E+19 which cannot be represented in target type `u64`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 1.8446744073709552E+19f64 which cannot be represented in target type `u64`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 3.4028236692093846E+38 which cannot be represented in target type `u128`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 3.4028236692093846E+38f64 which cannot be represented in target type `u128`
|
||||
--> $DIR/float_to_int_64_too_big4.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f64, u128>(u128::MAX as f64);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 3.4028236692093846E+38 which cannot be represented in target type `u128`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 3.4028236692093846E+38f64 which cannot be represented in target type `u128`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 2.4028236692093845E+38 which cannot be represented in target type `i128`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 2.4028236692093845E+38f64 which cannot be represented in target type `i128`
|
||||
--> $DIR/float_to_int_64_too_big5.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f64, i128>(240282366920938463463374607431768211455.0f64);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 2.4028236692093845E+38 which cannot be represented in target type `i128`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 2.4028236692093845E+38f64 which cannot be represented in target type `i128`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 1.7976931348623157E+308 which cannot be represented in target type `u128`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 1.7976931348623157E+308f64 which cannot be represented in target type `u128`
|
||||
--> $DIR/float_to_int_64_too_big6.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f64, u128>(f64::MAX);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 1.7976931348623157E+308 which cannot be represented in target type `u128`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 1.7976931348623157E+308f64 which cannot be represented in target type `u128`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1.7976931348623157E+308 which cannot be represented in target type `i128`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1.7976931348623157E+308f64 which cannot be represented in target type `i128`
|
||||
--> $DIR/float_to_int_64_too_big7.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f64, i128>(f64::MIN);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1.7976931348623157E+308 which cannot be represented in target type `i128`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1.7976931348623157E+308f64 which cannot be represented in target type `i128`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -2147483649 which cannot be represented in target type `i32`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -2147483649f64 which cannot be represented in target type `i32`
|
||||
--> $DIR/float_to_int_64_too_small1.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f64, i32>(-2147483649.0f64);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -2147483649 which cannot be represented in target type `i32`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -2147483649f64 which cannot be represented in target type `i32`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -9.2233720368547778E+18 which cannot be represented in target type `i64`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -9.2233720368547778E+18f64 which cannot be represented in target type `i64`
|
||||
--> $DIR/float_to_int_64_too_small2.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f64, i64>(-9223372036854777856.0f64);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -9.2233720368547778E+18 which cannot be represented in target type `i64`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -9.2233720368547778E+18f64 which cannot be represented in target type `i64`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -2.4028236692093845E+38 which cannot be represented in target type `i128`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -2.4028236692093845E+38f64 which cannot be represented in target type `i128`
|
||||
--> $DIR/float_to_int_64_too_small3.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f64, i128>(-240282366920938463463374607431768211455.0f64);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -2.4028236692093845E+38 which cannot be represented in target type `i128`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -2.4028236692093845E+38f64 which cannot be represented in target type `i128`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `simd_cast` intrinsic called on 3.40282347E+38 which cannot be represented in target type `i32`
|
||||
error: Undefined Behavior: `simd_cast` intrinsic called on 3.40282347E+38f32 which cannot be represented in target type `i32`
|
||||
--> $DIR/simd-float-to-int.rs:LL:CC
|
||||
|
|
||||
LL | let _x: i32x2 = f32x2::from_array([f32::MAX, f32::MIN]).to_int_unchecked();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `simd_cast` intrinsic called on 3.40282347E+38 which cannot be represented in target type `i32`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `simd_cast` intrinsic called on 3.40282347E+38f32 which cannot be represented in target type `i32`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
42
src/tools/miri/tests/fail/shims/intrinsic_target_feature.rs
Normal file
42
src/tools/miri/tests/fail/shims/intrinsic_target_feature.rs
Normal file
@ -0,0 +1,42 @@
|
||||
// Ignore everything except x86 and x86_64
|
||||
// Any new targets that are added to CI should be ignored here.
|
||||
// We cannot use `cfg`-based tricks here since the output would be
|
||||
// different for non-x86 targets.
|
||||
//@ignore-target-aarch64
|
||||
//@ignore-target-arm
|
||||
//@ignore-target-avr
|
||||
//@ignore-target-s390x
|
||||
//@ignore-target-thumbv7em
|
||||
//@ignore-target-wasm32
|
||||
// Explicitly disable SSE4.1 because it is enabled by default on macOS
|
||||
//@compile-flags: -C target-feature=-sse4.1
|
||||
|
||||
#![feature(link_llvm_intrinsics, simd_ffi)]
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
use std::arch::x86::*;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
fn main() {
|
||||
assert!(is_x86_feature_detected!("sse"));
|
||||
assert!(!is_x86_feature_detected!("sse4.1"));
|
||||
|
||||
unsafe {
|
||||
// Pass, since SSE is enabled
|
||||
addss(_mm_setzero_ps(), _mm_setzero_ps());
|
||||
|
||||
// Fail, since SSE4.1 is not enabled
|
||||
dpps(_mm_setzero_ps(), _mm_setzero_ps(), 0);
|
||||
//~^ ERROR: Undefined Behavior: attempted to call intrinsic `llvm.x86.sse41.dpps` that requires missing target feature sse4.1
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(improper_ctypes)]
|
||||
extern "C" {
|
||||
#[link_name = "llvm.x86.sse.add.ss"]
|
||||
fn addss(a: __m128, b: __m128) -> __m128;
|
||||
|
||||
#[link_name = "llvm.x86.sse41.dpps"]
|
||||
fn dpps(a: __m128, b: __m128, imm8: u8) -> __m128;
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
error: Undefined Behavior: attempted to call intrinsic `llvm.x86.sse41.dpps` that requires missing target feature sse4.1
|
||||
--> $DIR/intrinsic_target_feature.rs:LL:CC
|
||||
|
|
||||
LL | dpps(_mm_setzero_ps(), _mm_setzero_ps(), 0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempted to call intrinsic `llvm.x86.sse41.dpps` that requires missing target feature sse4.1
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
= note: BACKTRACE:
|
||||
= note: inside `main` at $DIR/intrinsic_target_feature.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -2,15 +2,13 @@
|
||||
//@ignore-target-windows: No libc on Windows
|
||||
|
||||
use std::ffi::CStr;
|
||||
use std::ffi::CString;
|
||||
use std::thread;
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
thread::spawn(|| {
|
||||
// Access the environment in another thread without taking the env lock
|
||||
let k = CString::new("MIRI_ENV_VAR_TEST".as_bytes()).unwrap();
|
||||
let s = libc::getenv(k.as_ptr()) as *const libc::c_char;
|
||||
let s = libc::getenv("MIRI_ENV_VAR_TEST\0".as_ptr().cast());
|
||||
if s.is_null() {
|
||||
panic!("null");
|
||||
}
|
||||
@ -19,5 +17,6 @@ fn main() {
|
||||
thread::yield_now();
|
||||
// After the main thread exits, env vars will be cleaned up -- but because we have not *joined*
|
||||
// the other thread, those accesses technically race with those in the other thread.
|
||||
// We don't want to emit an error here, though.
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
//@ignore-target-windows: no libc on Windows
|
||||
//@ignore-target-freebsd: FIXME needs foreign function `stat@FBSD_1.0`
|
||||
//@compile-flags: -Zmiri-isolation-error=warn-nobacktrace
|
||||
//@normalize-stderr-test: "(stat(x)?)" -> "$$STAT"
|
||||
|
||||
|
@ -23,6 +23,7 @@ fn main() {
|
||||
test_file_open_unix_extra_third_arg();
|
||||
#[cfg(target_os = "linux")]
|
||||
test_o_tmpfile_flag();
|
||||
test_posix_mkstemp();
|
||||
}
|
||||
|
||||
/// Prepare: compute filename and make sure the file does not exist.
|
||||
@ -151,3 +152,45 @@ fn test_o_tmpfile_flag() {
|
||||
.raw_os_error(),
|
||||
);
|
||||
}
|
||||
|
||||
fn test_posix_mkstemp() {
|
||||
use std::ffi::OsStr;
|
||||
use std::os::unix::io::FromRawFd;
|
||||
use std::path::Path;
|
||||
|
||||
let valid_template = "fooXXXXXX";
|
||||
// C needs to own this as `mkstemp(3)` says:
|
||||
// "Since it will be modified, `template` must not be a string constant, but
|
||||
// should be declared as a character array."
|
||||
// There seems to be no `as_mut_ptr` on `CString` so we need to use `into_raw`.
|
||||
let ptr = CString::new(valid_template).unwrap().into_raw();
|
||||
let fd = unsafe { libc::mkstemp(ptr) };
|
||||
// Take ownership back in Rust to not leak memory.
|
||||
let slice = unsafe { CString::from_raw(ptr) };
|
||||
assert!(fd > 0);
|
||||
let osstr = OsStr::from_bytes(slice.to_bytes());
|
||||
let path: &Path = osstr.as_ref();
|
||||
let name = path.file_name().unwrap().to_string_lossy();
|
||||
assert!(name.ne("fooXXXXXX"));
|
||||
assert!(name.starts_with("foo"));
|
||||
assert_eq!(name.len(), 9);
|
||||
assert_eq!(
|
||||
name.chars().skip(3).filter(char::is_ascii_alphanumeric).collect::<Vec<char>>().len(),
|
||||
6
|
||||
);
|
||||
let file = unsafe { File::from_raw_fd(fd) };
|
||||
assert!(file.set_len(0).is_ok());
|
||||
|
||||
let invalid_templates = vec!["foo", "barXX", "XXXXXXbaz", "whatXXXXXXever", "X"];
|
||||
for t in invalid_templates {
|
||||
let ptr = CString::new(t).unwrap().into_raw();
|
||||
let fd = unsafe { libc::mkstemp(ptr) };
|
||||
let _ = unsafe { CString::from_raw(ptr) };
|
||||
// "On error, -1 is returned, and errno is set to
|
||||
// indicate the error"
|
||||
assert_eq!(fd, -1);
|
||||
let e = std::io::Error::last_os_error();
|
||||
assert_eq!(e.raw_os_error(), Some(libc::EINVAL));
|
||||
assert_eq!(e.kind(), std::io::ErrorKind::InvalidInput);
|
||||
}
|
||||
}
|
||||
|
@ -172,14 +172,13 @@ fn test_thread_local_errno() {
|
||||
}
|
||||
|
||||
/// Tests whether clock support exists at all
|
||||
#[cfg(not(target_os = "freebsd"))]
|
||||
fn test_clocks() {
|
||||
let mut tp = std::mem::MaybeUninit::<libc::timespec>::uninit();
|
||||
let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME, tp.as_mut_ptr()) };
|
||||
assert_eq!(is_error, 0);
|
||||
let is_error = unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC, tp.as_mut_ptr()) };
|
||||
assert_eq!(is_error, 0);
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||
{
|
||||
let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME_COARSE, tp.as_mut_ptr()) };
|
||||
assert_eq!(is_error, 0);
|
||||
@ -238,51 +237,6 @@ fn test_isatty() {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "freebsd"))]
|
||||
fn test_posix_mkstemp() {
|
||||
use std::ffi::CString;
|
||||
use std::ffi::OsStr;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::os::unix::io::FromRawFd;
|
||||
use std::path::Path;
|
||||
|
||||
let valid_template = "fooXXXXXX";
|
||||
// C needs to own this as `mkstemp(3)` says:
|
||||
// "Since it will be modified, `template` must not be a string constant, but
|
||||
// should be declared as a character array."
|
||||
// There seems to be no `as_mut_ptr` on `CString` so we need to use `into_raw`.
|
||||
let ptr = CString::new(valid_template).unwrap().into_raw();
|
||||
let fd = unsafe { libc::mkstemp(ptr) };
|
||||
// Take ownership back in Rust to not leak memory.
|
||||
let slice = unsafe { CString::from_raw(ptr) };
|
||||
assert!(fd > 0);
|
||||
let osstr = OsStr::from_bytes(slice.to_bytes());
|
||||
let path: &Path = osstr.as_ref();
|
||||
let name = path.file_name().unwrap().to_string_lossy();
|
||||
assert!(name.ne("fooXXXXXX"));
|
||||
assert!(name.starts_with("foo"));
|
||||
assert_eq!(name.len(), 9);
|
||||
assert_eq!(
|
||||
name.chars().skip(3).filter(char::is_ascii_alphanumeric).collect::<Vec<char>>().len(),
|
||||
6
|
||||
);
|
||||
let file = unsafe { File::from_raw_fd(fd) };
|
||||
assert!(file.set_len(0).is_ok());
|
||||
|
||||
let invalid_templates = vec!["foo", "barXX", "XXXXXXbaz", "whatXXXXXXever", "X"];
|
||||
for t in invalid_templates {
|
||||
let ptr = CString::new(t).unwrap().into_raw();
|
||||
let fd = unsafe { libc::mkstemp(ptr) };
|
||||
let _ = unsafe { CString::from_raw(ptr) };
|
||||
// "On error, -1 is returned, and errno is set to
|
||||
// indicate the error"
|
||||
assert_eq!(fd, -1);
|
||||
let e = std::io::Error::last_os_error();
|
||||
assert_eq!(e.raw_os_error(), Some(libc::EINVAL));
|
||||
assert_eq!(e.kind(), std::io::ErrorKind::InvalidInput);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_memcpy() {
|
||||
unsafe {
|
||||
let src = [1i8, 2, 3];
|
||||
@ -406,9 +360,6 @@ fn test_reallocarray() {
|
||||
fn main() {
|
||||
test_posix_gettimeofday();
|
||||
|
||||
#[cfg(not(target_os = "freebsd"))] // FIXME we should support this on FreeBSD as well
|
||||
test_posix_mkstemp();
|
||||
|
||||
test_posix_realpath_alloc();
|
||||
test_posix_realpath_noalloc();
|
||||
test_posix_realpath_errors();
|
||||
@ -417,7 +368,6 @@ fn main() {
|
||||
|
||||
test_isatty();
|
||||
|
||||
#[cfg(not(target_os = "freebsd"))] // FIXME we should support this on FreeBSD as well
|
||||
test_clocks();
|
||||
|
||||
test_dlsym();
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Ignore everything except x86 and x86_64
|
||||
// Any additional target are added to CI should be ignored here
|
||||
// Any new targets that are added to CI should be ignored here.
|
||||
// (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.)
|
||||
//@ignore-target-aarch64
|
||||
//@ignore-target-arm
|
||||
|
162
src/tools/miri/tests/pass/intrinsics-x86-avx.rs
Normal file
162
src/tools/miri/tests/pass/intrinsics-x86-avx.rs
Normal file
@ -0,0 +1,162 @@
|
||||
// Ignore everything except x86 and x86_64
|
||||
// Any new targets that are added to CI should be ignored here.
|
||||
// (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.)
|
||||
//@ignore-target-aarch64
|
||||
//@ignore-target-arm
|
||||
//@ignore-target-avr
|
||||
//@ignore-target-s390x
|
||||
//@ignore-target-thumbv7em
|
||||
//@ignore-target-wasm32
|
||||
//@compile-flags: -C target-feature=+avx
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
use std::arch::x86::*;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use std::arch::x86_64::*;
|
||||
use std::mem::transmute;
|
||||
|
||||
fn main() {
|
||||
assert!(is_x86_feature_detected!("avx"));
|
||||
|
||||
unsafe {
|
||||
test_avx();
|
||||
}
|
||||
}
|
||||
|
||||
#[target_feature(enable = "avx")]
|
||||
unsafe fn test_avx() {
|
||||
fn expected_cmp<F: PartialOrd>(imm: i32, lhs: F, rhs: F, if_t: F, if_f: F) -> F {
|
||||
let res = match imm {
|
||||
_CMP_EQ_OQ => lhs == rhs,
|
||||
_CMP_LT_OS => lhs < rhs,
|
||||
_CMP_LE_OS => lhs <= rhs,
|
||||
_CMP_UNORD_Q => lhs.partial_cmp(&rhs).is_none(),
|
||||
_CMP_NEQ_UQ => lhs != rhs,
|
||||
_CMP_NLT_UQ => !(lhs < rhs),
|
||||
_CMP_NLE_UQ => !(lhs <= rhs),
|
||||
_CMP_ORD_Q => lhs.partial_cmp(&rhs).is_some(),
|
||||
_CMP_EQ_UQ => lhs == rhs || lhs.partial_cmp(&rhs).is_none(),
|
||||
_CMP_NGE_US => !(lhs >= rhs),
|
||||
_CMP_NGT_US => !(lhs > rhs),
|
||||
_CMP_FALSE_OQ => false,
|
||||
_CMP_NEQ_OQ => lhs != rhs && lhs.partial_cmp(&rhs).is_some(),
|
||||
_CMP_GE_OS => lhs >= rhs,
|
||||
_CMP_GT_OS => lhs > rhs,
|
||||
_CMP_TRUE_US => true,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
if res { if_t } else { if_f }
|
||||
}
|
||||
fn expected_cmp_f32(imm: i32, lhs: f32, rhs: f32) -> f32 {
|
||||
expected_cmp(imm, lhs, rhs, f32::from_bits(u32::MAX), 0.0)
|
||||
}
|
||||
fn expected_cmp_f64(imm: i32, lhs: f64, rhs: f64) -> f64 {
|
||||
expected_cmp(imm, lhs, rhs, f64::from_bits(u64::MAX), 0.0)
|
||||
}
|
||||
|
||||
#[target_feature(enable = "avx")]
|
||||
unsafe fn test_mm_cmp_ss<const IMM: i32>() {
|
||||
let values = [
|
||||
(1.0, 1.0),
|
||||
(0.0, 1.0),
|
||||
(1.0, 0.0),
|
||||
(f32::NAN, 0.0),
|
||||
(0.0, f32::NAN),
|
||||
(f32::NAN, f32::NAN),
|
||||
];
|
||||
|
||||
for (lhs, rhs) in values {
|
||||
let a = _mm_setr_ps(lhs, 2.0, 3.0, 4.0);
|
||||
let b = _mm_setr_ps(rhs, 5.0, 6.0, 7.0);
|
||||
let r: [u32; 4] = transmute(_mm_cmp_ss::<IMM>(a, b));
|
||||
let e: [u32; 4] =
|
||||
transmute(_mm_setr_ps(expected_cmp_f32(IMM, lhs, rhs), 2.0, 3.0, 4.0));
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
}
|
||||
|
||||
#[target_feature(enable = "avx")]
|
||||
unsafe fn test_mm_cmp_ps<const IMM: i32>() {
|
||||
let values = [
|
||||
(1.0, 1.0),
|
||||
(0.0, 1.0),
|
||||
(1.0, 0.0),
|
||||
(f32::NAN, 0.0),
|
||||
(0.0, f32::NAN),
|
||||
(f32::NAN, f32::NAN),
|
||||
];
|
||||
|
||||
for (lhs, rhs) in values {
|
||||
let a = _mm_set1_ps(lhs);
|
||||
let b = _mm_set1_ps(rhs);
|
||||
let r: [u32; 4] = transmute(_mm_cmp_ps::<IMM>(a, b));
|
||||
let e: [u32; 4] = transmute(_mm_set1_ps(expected_cmp_f32(IMM, lhs, rhs)));
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
}
|
||||
|
||||
#[target_feature(enable = "avx")]
|
||||
unsafe fn test_mm_cmp_sd<const IMM: i32>() {
|
||||
let values = [
|
||||
(1.0, 1.0),
|
||||
(0.0, 1.0),
|
||||
(1.0, 0.0),
|
||||
(f64::NAN, 0.0),
|
||||
(0.0, f64::NAN),
|
||||
(f64::NAN, f64::NAN),
|
||||
];
|
||||
|
||||
for (lhs, rhs) in values {
|
||||
let a = _mm_setr_pd(lhs, 2.0);
|
||||
let b = _mm_setr_pd(rhs, 3.0);
|
||||
let r: [u64; 2] = transmute(_mm_cmp_sd::<IMM>(a, b));
|
||||
let e: [u64; 2] = transmute(_mm_setr_pd(expected_cmp_f64(IMM, lhs, rhs), 2.0));
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
}
|
||||
|
||||
#[target_feature(enable = "avx")]
|
||||
unsafe fn test_mm_cmp_pd<const IMM: i32>() {
|
||||
let values = [
|
||||
(1.0, 1.0),
|
||||
(0.0, 1.0),
|
||||
(1.0, 0.0),
|
||||
(f64::NAN, 0.0),
|
||||
(0.0, f64::NAN),
|
||||
(f64::NAN, f64::NAN),
|
||||
];
|
||||
|
||||
for (lhs, rhs) in values {
|
||||
let a = _mm_set1_pd(lhs);
|
||||
let b = _mm_set1_pd(rhs);
|
||||
let r: [u64; 2] = transmute(_mm_cmp_pd::<IMM>(a, b));
|
||||
let e: [u64; 2] = transmute(_mm_set1_pd(expected_cmp_f64(IMM, lhs, rhs)));
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
}
|
||||
|
||||
#[target_feature(enable = "avx")]
|
||||
unsafe fn test_cmp<const IMM: i32>() {
|
||||
test_mm_cmp_ss::<IMM>();
|
||||
test_mm_cmp_ps::<IMM>();
|
||||
test_mm_cmp_sd::<IMM>();
|
||||
test_mm_cmp_pd::<IMM>();
|
||||
}
|
||||
|
||||
test_cmp::<_CMP_EQ_OQ>();
|
||||
test_cmp::<_CMP_LT_OS>();
|
||||
test_cmp::<_CMP_LE_OS>();
|
||||
test_cmp::<_CMP_UNORD_Q>();
|
||||
test_cmp::<_CMP_NEQ_UQ>();
|
||||
test_cmp::<_CMP_NLT_UQ>();
|
||||
test_cmp::<_CMP_NLE_UQ>();
|
||||
test_cmp::<_CMP_ORD_Q>();
|
||||
test_cmp::<_CMP_EQ_UQ>();
|
||||
test_cmp::<_CMP_NGE_US>();
|
||||
test_cmp::<_CMP_NGT_US>();
|
||||
test_cmp::<_CMP_FALSE_OQ>();
|
||||
test_cmp::<_CMP_NEQ_OQ>();
|
||||
test_cmp::<_CMP_GE_OS>();
|
||||
test_cmp::<_CMP_GT_OS>();
|
||||
test_cmp::<_CMP_TRUE_US>();
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
// Ignore everything except x86 and x86_64
|
||||
// Any additional target are added to CI should be ignored here
|
||||
// Any new targets that are added to CI should be ignored here.
|
||||
// (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.)
|
||||
//@ignore-target-aarch64
|
||||
//@ignore-target-arm
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Ignore everything except x86 and x86_64
|
||||
// Any additional target are added to CI should be ignored here
|
||||
// Any new targets that are added to CI should be ignored here.
|
||||
// (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.)
|
||||
//@ignore-target-aarch64
|
||||
//@ignore-target-arm
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Ignore everything except x86 and x86_64
|
||||
// Any additional target are added to CI should be ignored here
|
||||
// Any new targets that are added to CI should be ignored here.
|
||||
// (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.)
|
||||
//@ignore-target-aarch64
|
||||
//@ignore-target-arm
|
||||
|
@ -7,12 +7,10 @@ mod macros;
|
||||
mod fs;
|
||||
mod miri_extern;
|
||||
|
||||
pub use fs::*;
|
||||
pub use miri_extern::*;
|
||||
pub use self::fs::*;
|
||||
pub use self::miri_extern::*;
|
||||
|
||||
pub fn run_provenance_gc() {
|
||||
// SAFETY: No preconditions. The GC is fine to run at any time.
|
||||
unsafe {
|
||||
miri_run_provenance_gc()
|
||||
}
|
||||
unsafe { miri_run_provenance_gc() }
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user