Skip to content

Commit 7c3eeb9

Browse files
committed
Auto merge of #116307 - RalfJung:miri, r=RalfJung
Miri subtree update r? `@ghost`
2 parents 8fa7bdf + 6687c07 commit 7c3eeb9

15 files changed

+855
-35
lines changed

Cargo.lock

+14-4
Original file line numberDiff line numberDiff line change
@@ -2136,6 +2136,16 @@ dependencies = [
21362136
"winapi",
21372137
]
21382138

2139+
[[package]]
2140+
name = "libloading"
2141+
version = "0.8.1"
2142+
source = "registry+https://github.com/rust-lang/crates.io-index"
2143+
checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161"
2144+
dependencies = [
2145+
"cfg-if",
2146+
"windows-sys 0.48.0",
2147+
]
2148+
21392149
[[package]]
21402150
name = "libm"
21412151
version = "0.1.4"
@@ -2411,7 +2421,7 @@ dependencies = [
24112421
"lazy_static",
24122422
"libc",
24132423
"libffi",
2414-
"libloading",
2424+
"libloading 0.8.1",
24152425
"log",
24162426
"measureme",
24172427
"rand",
@@ -3914,7 +3924,7 @@ dependencies = [
39143924
name = "rustc_interface"
39153925
version = "0.0.0"
39163926
dependencies = [
3917-
"libloading",
3927+
"libloading 0.7.4",
39183928
"rustc-rayon",
39193929
"rustc-rayon-core",
39203930
"rustc_ast",
@@ -4045,7 +4055,7 @@ name = "rustc_metadata"
40454055
version = "0.0.0"
40464056
dependencies = [
40474057
"bitflags 1.3.2",
4048-
"libloading",
4058+
"libloading 0.7.4",
40494059
"odht",
40504060
"rustc_ast",
40514061
"rustc_attr",
@@ -4260,7 +4270,7 @@ dependencies = [
42604270
name = "rustc_plugin_impl"
42614271
version = "0.0.0"
42624272
dependencies = [
4263-
"libloading",
4273+
"libloading 0.7.4",
42644274
"rustc_ast",
42654275
"rustc_errors",
42664276
"rustc_fluent_macro",

src/tools/miri/Cargo.lock

+5-5
Original file line numberDiff line numberDiff line change
@@ -409,12 +409,12 @@ dependencies = [
409409

410410
[[package]]
411411
name = "libloading"
412-
version = "0.7.4"
412+
version = "0.8.0"
413413
source = "registry+https://github.com/rust-lang/crates.io-index"
414-
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
414+
checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb"
415415
dependencies = [
416416
"cfg-if",
417-
"winapi",
417+
"windows-sys 0.48.0",
418418
]
419419

420420
[[package]]
@@ -947,9 +947,9 @@ dependencies = [
947947

948948
[[package]]
949949
name = "ui_test"
950-
version = "0.21.1"
950+
version = "0.21.2"
951951
source = "registry+https://github.com/rust-lang/crates.io-index"
952-
checksum = "accffe020b57a6dd50014d457b5842c5a2ca73cd84f07d86d0a19c460a6509ae"
952+
checksum = "aaf4bf7c184b8dfc7a4d3b90df789b1eb992ee42811cd115f32a7a1eb781058d"
953953
dependencies = [
954954
"annotate-snippets",
955955
"anyhow",

src/tools/miri/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ libc = "0.2"
3232

3333
[target.'cfg(target_os = "linux")'.dependencies]
3434
libffi = "3.2.0"
35-
libloading = "0.7"
35+
libloading = "0.8"
3636

3737
[dev-dependencies]
3838
colored = "2"

src/tools/miri/rust-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2ba4eb2d49e774b5fbc2a06258ac7b0f60b92b7e
1+
bb6c66be3793ac5c738eeac91ecdc4b99388d0b4

src/tools/miri/src/shims/intrinsics/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
325325

326326
"fmaf32" => {
327327
let [a, b, c] = check_arg_count(args)?;
328-
// FIXME: Using host floats, to work around https://github.com/rust-lang/miri/issues/2468.
328+
// FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11
329329
let a = f32::from_bits(this.read_scalar(a)?.to_u32()?);
330330
let b = f32::from_bits(this.read_scalar(b)?.to_u32()?);
331331
let c = f32::from_bits(this.read_scalar(c)?.to_u32()?);
@@ -335,7 +335,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
335335

336336
"fmaf64" => {
337337
let [a, b, c] = check_arg_count(args)?;
338-
// FIXME: Using host floats, to work around https://github.com/rust-lang/miri/issues/2468.
338+
// FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11
339339
let a = f64::from_bits(this.read_scalar(a)?.to_u64()?);
340340
let b = f64::from_bits(this.read_scalar(b)?.to_u64()?);
341341
let c = f64::from_bits(this.read_scalar(c)?.to_u64()?);

src/tools/miri/src/shims/intrinsics/simd.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -495,15 +495,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
495495
let (right, right_len) = this.operand_to_simd(right)?;
496496
let (dest, dest_len) = this.place_to_simd(dest)?;
497497

498-
let index = generic_args[2].expect_const().eval(*this.tcx, this.param_env(), Some(this.tcx.span)).unwrap().unwrap_branch();
498+
let index = generic_args[2]
499+
.expect_const()
500+
.eval(*this.tcx, this.param_env(), Some(this.tcx.span))
501+
.unwrap()
502+
.unwrap_branch();
499503
let index_len = index.len();
500504

501505
assert_eq!(left_len, right_len);
502506
assert_eq!(index_len as u64, dest_len);
503507

504508
for i in 0..dest_len {
505-
let src_index: u64 = index[i as usize].unwrap_leaf()
506-
.try_to_u32().unwrap()
509+
let src_index: u64 = index[usize::try_from(i).unwrap()]
510+
.unwrap_leaf()
511+
.try_to_u32()
512+
.unwrap()
507513
.into();
508514
let dest = this.project_index(&dest, i)?;
509515

src/tools/miri/src/shims/x86/mod.rs

+53
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use shims::foreign_items::EmulateByNameResult;
99

1010
mod sse;
1111
mod sse2;
12+
mod sse3;
13+
mod ssse3;
1214

1315
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
1416
pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
@@ -88,6 +90,16 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
8890
this, link_name, abi, args, dest,
8991
);
9092
}
93+
name if name.starts_with("sse3.") => {
94+
return sse3::EvalContextExt::emulate_x86_sse3_intrinsic(
95+
this, link_name, abi, args, dest,
96+
);
97+
}
98+
name if name.starts_with("ssse3.") => {
99+
return ssse3::EvalContextExt::emulate_x86_ssse3_intrinsic(
100+
this, link_name, abi, args, dest,
101+
);
102+
}
91103
_ => return Ok(EmulateByNameResult::NotSupported),
92104
}
93105
Ok(EmulateByNameResult::NeedsJumping)
@@ -286,3 +298,44 @@ fn bin_op_simd_float_all<'tcx, F: rustc_apfloat::Float>(
286298

287299
Ok(())
288300
}
301+
302+
/// Horizontaly performs `which` operation on adjacent values of
303+
/// `left` and `right` SIMD vectors and stores the result in `dest`.
304+
fn horizontal_bin_op<'tcx>(
305+
this: &mut crate::MiriInterpCx<'_, 'tcx>,
306+
which: mir::BinOp,
307+
saturating: bool,
308+
left: &OpTy<'tcx, Provenance>,
309+
right: &OpTy<'tcx, Provenance>,
310+
dest: &PlaceTy<'tcx, Provenance>,
311+
) -> InterpResult<'tcx, ()> {
312+
let (left, left_len) = this.operand_to_simd(left)?;
313+
let (right, right_len) = this.operand_to_simd(right)?;
314+
let (dest, dest_len) = this.place_to_simd(dest)?;
315+
316+
assert_eq!(dest_len, left_len);
317+
assert_eq!(dest_len, right_len);
318+
assert_eq!(dest_len % 2, 0);
319+
320+
let middle = dest_len / 2;
321+
for i in 0..dest_len {
322+
// `i` is the index in `dest`
323+
// `j` is the index of the 2-item chunk in `src`
324+
let (j, src) =
325+
if i < middle { (i, &left) } else { (i.checked_sub(middle).unwrap(), &right) };
326+
// `base_i` is the index of the first item of the 2-item chunk in `src`
327+
let base_i = j.checked_mul(2).unwrap();
328+
let lhs = this.read_immediate(&this.project_index(src, base_i)?)?;
329+
let rhs = this.read_immediate(&this.project_index(src, base_i.checked_add(1).unwrap())?)?;
330+
331+
let res = if saturating {
332+
Immediate::from(this.saturating_arith(which, &lhs, &rhs)?)
333+
} else {
334+
*this.wrapping_binary_op(which, &lhs, &rhs)?
335+
};
336+
337+
this.write_immediate(res, &this.project_index(&dest, i)?)?;
338+
}
339+
340+
Ok(())
341+
}

src/tools/miri/src/shims/x86/sse2.rs

+36
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,42 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
8282
this.write_immediate(*res, &dest)?;
8383
}
8484
}
85+
// Used to implement the _mm_madd_epi16 function.
86+
// Multiplies packed signed 16-bit integers in `left` and `right`, producing
87+
// intermediate signed 32-bit integers. Horizontally add adjacent pairs of
88+
// intermediate 32-bit integers, and pack the results in `dest`.
89+
"pmadd.wd" => {
90+
let [left, right] =
91+
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
92+
93+
let (left, left_len) = this.operand_to_simd(left)?;
94+
let (right, right_len) = this.operand_to_simd(right)?;
95+
let (dest, dest_len) = this.place_to_simd(dest)?;
96+
97+
assert_eq!(left_len, right_len);
98+
assert_eq!(dest_len.checked_mul(2).unwrap(), left_len);
99+
100+
for i in 0..dest_len {
101+
let j1 = i.checked_mul(2).unwrap();
102+
let left1 = this.read_scalar(&this.project_index(&left, j1)?)?.to_i16()?;
103+
let right1 = this.read_scalar(&this.project_index(&right, j1)?)?.to_i16()?;
104+
105+
let j2 = j1.checked_add(1).unwrap();
106+
let left2 = this.read_scalar(&this.project_index(&left, j2)?)?.to_i16()?;
107+
let right2 = this.read_scalar(&this.project_index(&right, j2)?)?.to_i16()?;
108+
109+
let dest = this.project_index(&dest, i)?;
110+
111+
// Multiplications are i16*i16->i32, which will not overflow.
112+
let mul1 = i32::from(left1).checked_mul(right1.into()).unwrap();
113+
let mul2 = i32::from(left2).checked_mul(right2.into()).unwrap();
114+
// However, this addition can overflow in the most extreme case
115+
// (-0x8000)*(-0x8000)+(-0x8000)*(-0x8000) = 0x80000000
116+
let res = mul1.wrapping_add(mul2);
117+
118+
this.write_scalar(Scalar::from_i32(res), &dest)?;
119+
}
120+
}
85121
// Used to implement the _mm_mulhi_epi16 and _mm_mulhi_epu16 functions.
86122
"pmulh.w" | "pmulhu.w" => {
87123
let [left, right] =

src/tools/miri/src/shims/x86/sse3.rs

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
use rustc_middle::mir;
2+
use rustc_span::Symbol;
3+
use rustc_target::abi::Align;
4+
use rustc_target::spec::abi::Abi;
5+
6+
use super::horizontal_bin_op;
7+
use crate::*;
8+
use shims::foreign_items::EmulateByNameResult;
9+
10+
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
11+
pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
12+
crate::MiriInterpCxExt<'mir, 'tcx>
13+
{
14+
fn emulate_x86_sse3_intrinsic(
15+
&mut self,
16+
link_name: Symbol,
17+
abi: Abi,
18+
args: &[OpTy<'tcx, Provenance>],
19+
dest: &PlaceTy<'tcx, Provenance>,
20+
) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
21+
let this = self.eval_context_mut();
22+
// Prefix should have already been checked.
23+
let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse3.").unwrap();
24+
25+
match unprefixed_name {
26+
// Used to implement the _mm_addsub_ps and _mm_addsub_pd functions.
27+
// Alternatingly add and subtract floating point (f32 or f64) from
28+
// `left` and `right`
29+
"addsub.ps" | "addsub.pd" => {
30+
let [left, right] =
31+
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
32+
33+
let (left, left_len) = this.operand_to_simd(left)?;
34+
let (right, right_len) = this.operand_to_simd(right)?;
35+
let (dest, dest_len) = this.place_to_simd(dest)?;
36+
37+
assert_eq!(dest_len, left_len);
38+
assert_eq!(dest_len, right_len);
39+
40+
for i in 0..dest_len {
41+
let left = this.read_immediate(&this.project_index(&left, i)?)?;
42+
let right = this.read_immediate(&this.project_index(&right, i)?)?;
43+
let dest = this.project_index(&dest, i)?;
44+
45+
// Even elements are subtracted and odd elements are added.
46+
let op = if i % 2 == 0 { mir::BinOp::Sub } else { mir::BinOp::Add };
47+
let res = this.wrapping_binary_op(op, &left, &right)?;
48+
49+
this.write_immediate(*res, &dest)?;
50+
}
51+
}
52+
// Used to implement the _mm_h{add,sub}_p{s,d} functions.
53+
// Horizontally add/subtract adjacent floating point values
54+
// in `left` and `right`.
55+
"hadd.ps" | "hadd.pd" | "hsub.ps" | "hsub.pd" => {
56+
let [left, right] =
57+
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
58+
59+
let which = match unprefixed_name {
60+
"hadd.ps" | "hadd.pd" => mir::BinOp::Add,
61+
"hsub.ps" | "hsub.pd" => mir::BinOp::Sub,
62+
_ => unreachable!(),
63+
};
64+
65+
horizontal_bin_op(this, which, /*saturating*/ false, left, right, dest)?;
66+
}
67+
// Used to implement the _mm_lddqu_si128 function.
68+
// Reads a 128-bit vector from an unaligned pointer. This intrinsic
69+
// is expected to perform better than a regular unaligned read when
70+
// the data crosses a cache line, but for Miri this is just a regular
71+
// unaligned read.
72+
"ldu.dq" => {
73+
let [src_ptr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
74+
let src_ptr = this.read_pointer(src_ptr)?;
75+
let dest = dest.force_mplace(this)?;
76+
77+
this.mem_copy(
78+
src_ptr,
79+
Align::ONE,
80+
dest.ptr(),
81+
Align::ONE,
82+
dest.layout.size,
83+
/*nonoverlapping*/ true,
84+
)?;
85+
}
86+
_ => return Ok(EmulateByNameResult::NotSupported),
87+
}
88+
Ok(EmulateByNameResult::NeedsJumping)
89+
}
90+
}

0 commit comments

Comments
 (0)