diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 23e6f054a7c1e..1eac2157cac3c 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1079,7 +1079,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( .map(|(arg_idx, val)| { let idx = val.unwrap_leaf().try_to_i32().unwrap(); if idx >= i32::try_from(total_len).unwrap() { - bx.sess().dcx().emit_err(InvalidMonomorphization::ShuffleIndexOutOfBounds { + bx.sess().dcx().emit_err(InvalidMonomorphization::SimdIndexOutOfBounds { span, name, arg_idx: arg_idx as u64, @@ -1138,24 +1138,15 @@ fn generic_simd_intrinsic<'ll, 'tcx>( let val = bx.const_get_elt(vector, i as u64); match bx.const_to_opt_u128(val, true) { None => { - bx.sess().dcx().emit_err( - InvalidMonomorphization::ShuffleIndexNotConstant { - span, - name, - arg_idx, - }, - ); - None + bug!("typeck should have already ensured that these are const") } Some(idx) if idx >= total_len => { - bx.sess().dcx().emit_err( - InvalidMonomorphization::ShuffleIndexOutOfBounds { - span, - name, - arg_idx, - total_len, - }, - ); + bx.sess().dcx().emit_err(InvalidMonomorphization::SimdIndexOutOfBounds { + span, + name, + arg_idx, + total_len, + }); None } Some(idx) => Some(bx.const_i32(idx as i32)), @@ -1184,10 +1175,22 @@ fn generic_simd_intrinsic<'ll, 'tcx>( out_ty: arg_tys[2] } ); + let idx = bx + .const_to_opt_u128(args[1].immediate(), false) + .expect("typeck should have ensure that this is a const"); + if idx >= in_len.into() { + bx.sess().dcx().emit_err(InvalidMonomorphization::SimdIndexOutOfBounds { + span, + name, + arg_idx: 1, + total_len: in_len.into(), + }); + return Ok(bx.const_null(llret_ty)); + } return Ok(bx.insert_element( args[0].immediate(), args[2].immediate(), - args[1].immediate(), + bx.const_i32(idx as i32), )); } if name == sym::simd_extract { @@ -1195,7 +1198,19 @@ fn generic_simd_intrinsic<'ll, 'tcx>( ret_ty == in_elem, InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); - return Ok(bx.extract_element(args[0].immediate(), args[1].immediate())); + let idx = bx + .const_to_opt_u128(args[1].immediate(), false) + .expect("typeck should have ensure that this is a const"); + if idx >= in_len.into() { + bx.sess().dcx().emit_err(InvalidMonomorphization::SimdIndexOutOfBounds { + span, + name, + arg_idx: 1, + total_len: in_len.into(), + }); + return Ok(bx.const_null(llret_ty)); + } + return Ok(bx.extract_element(args[0].immediate(), bx.const_i32(idx as i32))); } if name == sym::simd_select { diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index fa7719d89716e..5ba66d1be4329 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -106,14 +106,12 @@ codegen_ssa_invalid_monomorphization_return_type = invalid monomorphization of ` codegen_ssa_invalid_monomorphization_second_argument_length = invalid monomorphization of `{$name}` intrinsic: expected second argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len} -codegen_ssa_invalid_monomorphization_shuffle_index_not_constant = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is not a constant - -codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is out of bounds (limit {$total_len}) - codegen_ssa_invalid_monomorphization_simd_argument = invalid monomorphization of `{$name}` intrinsic: expected SIMD argument type, found non-SIMD `{$ty}` codegen_ssa_invalid_monomorphization_simd_first = invalid monomorphization of `{$name}` intrinsic: expected SIMD first type, found non-SIMD `{$ty}` +codegen_ssa_invalid_monomorphization_simd_index_out_of_bounds = invalid monomorphization of `{$name}` intrinsic: SIMD index #{$arg_idx} is out of bounds (limit {$total_len}) + codegen_ssa_invalid_monomorphization_simd_input = invalid monomorphization of `{$name}` intrinsic: expected SIMD input type, found non-SIMD `{$ty}` codegen_ssa_invalid_monomorphization_simd_return = invalid monomorphization of `{$name}` intrinsic: expected SIMD return type, found non-SIMD `{$ty}` diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index e42a8bd9ed98d..a7ac502b24837 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -797,16 +797,8 @@ pub enum InvalidMonomorphization<'tcx> { out_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_not_constant, code = E0511)] - ShuffleIndexNotConstant { - #[primary_span] - span: Span, - name: Symbol, - arg_idx: u64, - }, - - #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds, code = E0511)] - ShuffleIndexOutOfBounds { + #[diag(codegen_ssa_invalid_monomorphization_simd_index_out_of_bounds, code = E0511)] + SimdIndexOutOfBounds { #[primary_span] span: Span, name: Symbol, diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index f020616f6d8c8..1cb991b38f7e9 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -379,10 +379,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let (input, input_len) = self.operand_to_simd(&args[0])?; let (dest, dest_len) = self.place_to_simd(dest)?; assert_eq!(input_len, dest_len, "Return vector length must match input length"); - assert!( - index < dest_len, - "Index `{index}` must be in bounds of vector with length {dest_len}" - ); + // Bounds are not checked by typeck so we have to do it ourselves. + if index >= input_len { + throw_ub_format!( + "`simd_insert` index {index} is out-of-bounds of vector with length {input_len}" + ); + } for i in 0..dest_len { let place = self.project_index(&dest, i)?; @@ -397,10 +399,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { sym::simd_extract => { let index = u64::from(self.read_scalar(&args[1])?.to_u32()?); let (input, input_len) = self.operand_to_simd(&args[0])?; - assert!( - index < input_len, - "index `{index}` must be in bounds of vector with length {input_len}" - ); + // Bounds are not checked by typeck so we have to do it ourselves. + if index >= input_len { + throw_ub_format!( + "`simd_extract` index {index} is out-of-bounds of vector with length {input_len}" + ); + } self.copy_op(&self.project_index(&input, index)?, dest)?; } sym::likely | sym::unlikely | sym::black_box => { diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs index ea2d104694af7..ca8773cac14b5 100644 --- a/src/tools/miri/src/shims/intrinsics/simd.rs +++ b/src/tools/miri/src/shims/intrinsics/simd.rs @@ -563,9 +563,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let right_idx = src_index.checked_sub(left_len).unwrap(); this.read_immediate(&this.project_index(&right, right_idx)?)? } else { - span_bug!( - this.cur_span(), - "simd_shuffle index {src_index} is out of bounds for 2 vectors of size {left_len}", + throw_ub_format!( + "`simd_shuffle_generic` index {src_index} is out-of-bounds for 2 vectors with length {dest_len}" ); }; this.write_immediate(*val, &dest)?; @@ -604,9 +603,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let right_idx = src_index.checked_sub(left_len).unwrap(); this.read_immediate(&this.project_index(&right, right_idx)?)? } else { - span_bug!( - this.cur_span(), - "simd_shuffle index {src_index} is out of bounds for 2 vectors of size {left_len}", + throw_ub_format!( + "`simd_shuffle` index {src_index} is out-of-bounds for 2 vectors with length {dest_len}" ); }; this.write_immediate(*val, &dest)?; diff --git a/src/tools/miri/tests/fail/intrinsics/simd-extract.rs b/src/tools/miri/tests/fail/intrinsics/simd-extract.rs new file mode 100644 index 0000000000000..02b9d30df5e97 --- /dev/null +++ b/src/tools/miri/tests/fail/intrinsics/simd-extract.rs @@ -0,0 +1,8 @@ +#![feature(portable_simd, core_intrinsics)] +use std::simd::*; + +fn main() { + let v = i32x4::splat(0); + let _x: i32 = unsafe { std::intrinsics::simd::simd_extract(v, 4) }; + //~^ERROR: index 4 is out-of-bounds +} diff --git a/src/tools/miri/tests/fail/intrinsics/simd-extract.stderr b/src/tools/miri/tests/fail/intrinsics/simd-extract.stderr new file mode 100644 index 0000000000000..dc6b22de4925a --- /dev/null +++ b/src/tools/miri/tests/fail/intrinsics/simd-extract.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: `simd_extract` index 4 is out-of-bounds of vector with length 4 + --> $DIR/simd-extract.rs:LL:CC + | +LL | let _x: i32 = unsafe { std::intrinsics::simd::simd_extract(v, 4) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `simd_extract` index 4 is out-of-bounds of vector with length 4 + | + = 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/simd-extract.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 + diff --git a/tests/ui/simd/shuffle-not-out-of-bounds.rs b/tests/ui/simd/not-out-of-bounds.rs similarity index 88% rename from tests/ui/simd/shuffle-not-out-of-bounds.rs rename to tests/ui/simd/not-out-of-bounds.rs index 158e9956435da..36d7a5865bc54 100644 --- a/tests/ui/simd/shuffle-not-out-of-bounds.rs +++ b/tests/ui/simd/not-out-of-bounds.rs @@ -1,6 +1,6 @@ //@ build-fail #![allow(non_camel_case_types)] -#![feature(repr_simd, platform_intrinsics)] +#![feature(repr_simd, core_intrinsics)] // Test for #73542 to verify out-of-bounds shuffle vectors do not compile. @@ -28,9 +28,7 @@ struct u8x32([u8; 32]); #[derive(Copy, Clone)] struct u8x64([u8; 64]); -extern "platform-intrinsic" { - pub fn simd_shuffle(x: T, y: T, idx: I) -> U; -} +use std::intrinsics::simd::*; // Test vectors by lane size. Since LLVM does not distinguish between a shuffle // over two f32s and a shuffle over two u64s, or any other such combination, @@ -70,13 +68,16 @@ fn main() { test_shuffle_lanes!(32, u8x32, simd_shuffle); test_shuffle_lanes!(64, u8x64, simd_shuffle); - extern "platform-intrinsic" { - fn simd_shuffle(a: T, b: T, i: I) -> U; - } let v = u8x2([0, 0]); const I: [u32; 2] = [4, 4]; unsafe { let _: u8x2 = simd_shuffle(v, v, I); //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic } + + // also check insert/extract + unsafe { + simd_insert(v, 2, 0); //~ ERROR invalid monomorphization of `simd_insert` intrinsic + let _val: u8 = simd_extract(v, 2); //~ ERROR invalid monomorphization of `simd_extract` intrinsic + } } diff --git a/tests/ui/simd/shuffle-not-out-of-bounds.stderr b/tests/ui/simd/not-out-of-bounds.stderr similarity index 71% rename from tests/ui/simd/shuffle-not-out-of-bounds.stderr rename to tests/ui/simd/not-out-of-bounds.stderr index 59e5ab858664a..5682935c1f1ae 100644 --- a/tests/ui/simd/shuffle-not-out-of-bounds.stderr +++ b/tests/ui/simd/not-out-of-bounds.stderr @@ -1,5 +1,5 @@ -error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 4) - --> $DIR/shuffle-not-out-of-bounds.rs:51:21 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 4) + --> $DIR/not-out-of-bounds.rs:49:21 | LL | $y(vec1, vec2, ARR) | ^^^^^^^^^^^^^^^^^^^ @@ -9,8 +9,8 @@ LL | test_shuffle_lanes!(2, u8x2, simd_shuffle); | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 8) - --> $DIR/shuffle-not-out-of-bounds.rs:51:21 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 8) + --> $DIR/not-out-of-bounds.rs:49:21 | LL | $y(vec1, vec2, ARR) | ^^^^^^^^^^^^^^^^^^^ @@ -20,8 +20,8 @@ LL | test_shuffle_lanes!(4, u8x4, simd_shuffle); | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 16) - --> $DIR/shuffle-not-out-of-bounds.rs:51:21 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 16) + --> $DIR/not-out-of-bounds.rs:49:21 | LL | $y(vec1, vec2, ARR) | ^^^^^^^^^^^^^^^^^^^ @@ -31,8 +31,8 @@ LL | test_shuffle_lanes!(8, u8x8, simd_shuffle); | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 32) - --> $DIR/shuffle-not-out-of-bounds.rs:51:21 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 32) + --> $DIR/not-out-of-bounds.rs:49:21 | LL | $y(vec1, vec2, ARR) | ^^^^^^^^^^^^^^^^^^^ @@ -42,8 +42,8 @@ LL | test_shuffle_lanes!(16, u8x16, simd_shuffle); | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 64) - --> $DIR/shuffle-not-out-of-bounds.rs:51:21 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 64) + --> $DIR/not-out-of-bounds.rs:49:21 | LL | $y(vec1, vec2, ARR) | ^^^^^^^^^^^^^^^^^^^ @@ -53,8 +53,8 @@ LL | test_shuffle_lanes!(32, u8x32, simd_shuffle); | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 128) - --> $DIR/shuffle-not-out-of-bounds.rs:51:21 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 128) + --> $DIR/not-out-of-bounds.rs:49:21 | LL | $y(vec1, vec2, ARR) | ^^^^^^^^^^^^^^^^^^^ @@ -64,12 +64,24 @@ LL | test_shuffle_lanes!(64, u8x64, simd_shuffle); | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 4) - --> $DIR/shuffle-not-out-of-bounds.rs:79:23 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 4) + --> $DIR/not-out-of-bounds.rs:74:23 | LL | let _: u8x2 = simd_shuffle(v, v, I); | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 7 previous errors +error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected inserted type `u8` (element of input `u8x2`), found `i32` + --> $DIR/not-out-of-bounds.rs:80:9 + | +LL | simd_insert(v, 2, 0); + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_extract` intrinsic: SIMD index #1 is out of bounds (limit 2) + --> $DIR/not-out-of-bounds.rs:81:24 + | +LL | let _val: u8 = simd_extract(v, 2); + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0511`.