1
Fork 0

Auto merge of #114449 - matthiaskrgr:rollup-cekswes, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 - #113534 (Forbid old-style `simd_shuffleN` intrinsics)
 - #113999 (Specify macro is invalid in certain contexts)
 - #114348 (Migrate GUI colors test to original CSS color format)
 - #114373 (unix/kernel_copy.rs: copy_file_range_candidate allows empty output files)
 - #114404 (Migrate GUI colors test to original CSS color format)
 - #114409 (builtin impl confirmation wuhu)
 - #114429 (compiletest: Handle non-utf8 paths (fix FIXME))
 - #114431 (Enable tests on rustc_codegen_ssa)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-08-04 05:34:47 +00:00
commit 098c1db7e5
31 changed files with 708 additions and 481 deletions

View file

@ -117,8 +117,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
});
}
// simd_shuffle32<T, U>(x: T, y: T, idx: [u32; 32]) -> U
_ if intrinsic.as_str().starts_with("simd_shuffle") => {
// simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U
sym::simd_shuffle => {
let (x, y, idx) = match args {
[x, y, idx] => (x, y, idx),
_ => {
@ -133,36 +133,26 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
return;
}
// If this intrinsic is the older "simd_shuffleN" form, simply parse the integer.
// If there is no suffix, use the index array length.
let n: u16 = if intrinsic == sym::simd_shuffle {
// Make sure this is actually an array, since typeck only checks the length-suffixed
// version of this intrinsic.
let idx_ty = fx.monomorphize(idx.ty(fx.mir, fx.tcx));
match idx_ty.kind() {
ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => len
.try_eval_target_usize(fx.tcx, ty::ParamEnv::reveal_all())
.unwrap_or_else(|| {
span_bug!(span, "could not evaluate shuffle index array length")
})
.try_into()
.unwrap(),
_ => {
fx.tcx.sess.span_err(
span,
format!(
"simd_shuffle index must be an array of `u32`, got `{}`",
idx_ty,
),
);
// Prevent verifier error
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
return;
}
// Make sure this is actually an array, since typeck only checks the length-suffixed
// version of this intrinsic.
let idx_ty = fx.monomorphize(idx.ty(fx.mir, fx.tcx));
let n: u16 = match idx_ty.kind() {
ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => len
.try_eval_target_usize(fx.tcx, ty::ParamEnv::reveal_all())
.unwrap_or_else(|| {
span_bug!(span, "could not evaluate shuffle index array length")
})
.try_into()
.unwrap(),
_ => {
fx.tcx.sess.span_err(
span,
format!("simd_shuffle index must be an array of `u32`, got `{}`", idx_ty),
);
// Prevent verifier error
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
return;
}
} else {
// FIXME remove this case
intrinsic.as_str()["simd_shuffle".len()..].parse().unwrap()
};
assert_eq!(x.layout(), y.layout());
@ -179,7 +169,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
let indexes = {
use rustc_middle::mir::interpret::*;
let idx_const = crate::constant::mir_operand_get_const_val(fx, idx)
.expect("simd_shuffle* idx not const");
.expect("simd_shuffle idx not const");
let idx_bytes = match idx_const {
ConstValue::ByRef { alloc, offset } => {

View file

@ -1,11 +1,11 @@
#[cfg(feature="master")]
use gccjit::{ComparisonOp, UnaryOp};
use gccjit::ToRValue;
use gccjit::{BinaryOp, RValue, Type};
#[cfg(feature = "master")]
use gccjit::{ComparisonOp, UnaryOp};
use rustc_codegen_ssa::base::compare_simd_types;
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
#[cfg(feature="master")]
#[cfg(feature = "master")]
use rustc_codegen_ssa::errors::ExpectedPointerMutability;
use rustc_codegen_ssa::errors::InvalidMonomorphization;
use rustc_codegen_ssa::mir::operand::OperandRef;
@ -19,7 +19,7 @@ use rustc_span::{sym, Span, Symbol};
use rustc_target::abi::Align;
use crate::builder::Builder;
#[cfg(feature="master")]
#[cfg(feature = "master")]
use crate::context::CodegenCx;
pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
@ -57,7 +57,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
let arg_tys = sig.inputs();
if name == sym::simd_select_bitmask {
require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] });
require_simd!(
arg_tys[1],
InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }
);
let (len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
let expected_int_bits = (len.max(8) - 1).next_power_of_two();
@ -95,7 +98,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
// NOTE: since the arguments can be vectors of floats, make sure the mask is a vector of
// integer.
let mask_element_type = bx.type_ix(arg1_element_type.get_size() as u64 * 8);
let vector_mask_type = bx.context.new_vector_type(mask_element_type, arg1_vector_type.get_num_units() as u64);
let vector_mask_type =
bx.context.new_vector_type(mask_element_type, arg1_vector_type.get_num_units() as u64);
let mut elements = vec![];
let one = bx.context.new_rvalue_one(mask.get_type());
@ -149,38 +153,24 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
// compare them as equal, so bitcast.
// FIXME(antoyo): allow comparing vector types as equal in libgccjit.
let arg2 = bx.context.new_bitcast(None, args[1].immediate(), arg1.get_type());
return Ok(compare_simd_types(
bx,
arg1,
arg2,
in_elem,
llret_ty,
cmp_op,
));
return Ok(compare_simd_types(bx, arg1, arg2, in_elem, llret_ty, cmp_op));
}
if let Some(stripped) = name.as_str().strip_prefix("simd_shuffle") {
let n: u64 = if stripped.is_empty() {
// Make sure this is actually an array, since typeck only checks the length-suffixed
// version of this intrinsic.
match args[2].layout.ty.kind() {
ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => {
len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(
|| span_bug!(span, "could not evaluate shuffle index array length"),
)
}
_ => return_error!(InvalidMonomorphization::SimdShuffle {
span,
name,
ty: args[2].layout.ty
}),
if name == sym::simd_shuffle {
// Make sure this is actually an array, since typeck only checks the length-suffixed
// version of this intrinsic.
let n: u64 = match args[2].layout.ty.kind() {
ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => {
len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(
|| span_bug!(span, "could not evaluate shuffle index array length"),
)
}
} else {
stripped.parse().unwrap_or_else(|_| {
span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?")
})
_ => return_error!(InvalidMonomorphization::SimdShuffle {
span,
name,
ty: args[2].layout.ty
}),
};
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
@ -202,7 +192,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
if name == sym::simd_insert {
require!(
in_elem == arg_tys[2],
InvalidMonomorphization::InsertedType { span, name, in_elem, in_ty, out_ty: arg_tys[2] }
InvalidMonomorphization::InsertedType {
span,
name,
in_elem,
in_ty,
out_ty: arg_tys[2]
}
);
let vector = args[0].immediate();
let index = args[1].immediate();
@ -228,7 +224,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
if name == sym::simd_select {
let m_elem_ty = in_elem;
let m_len = in_len;
require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] });
require_simd!(
arg_tys[1],
InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }
);
let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
require!(
m_len == v_len,
@ -241,7 +240,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
return Ok(bx.vector_select(args[0].immediate(), args[1].immediate(), args[2].immediate()));
}
#[cfg(feature="master")]
#[cfg(feature = "master")]
if name == sym::simd_cast || name == sym::simd_as {
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
@ -267,19 +266,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
Unsupported,
}
let in_style =
match in_elem.kind() {
ty::Int(_) | ty::Uint(_) => Style::Int,
ty::Float(_) => Style::Float,
_ => Style::Unsupported,
};
let in_style = match in_elem.kind() {
ty::Int(_) | ty::Uint(_) => Style::Int,
ty::Float(_) => Style::Float,
_ => Style::Unsupported,
};
let out_style =
match out_elem.kind() {
ty::Int(_) | ty::Uint(_) => Style::Int,
ty::Float(_) => Style::Float,
_ => Style::Unsupported,
};
let out_style = match out_elem.kind() {
ty::Int(_) | ty::Uint(_) => Style::Int,
ty::Float(_) => Style::Float,
_ => Style::Unsupported,
};
match (in_style, out_style) {
(Style::Unsupported, Style::Unsupported) => {
@ -294,7 +291,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
out_elem
}
);
},
}
_ => return Ok(bx.context.convert_vector(None, args[0].immediate(), llret_ty)),
}
}
@ -342,10 +339,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
let mut shift = 0;
for i in 0..in_len {
let elem = bx.extract_element(vector, bx.context.new_rvalue_from_int(bx.int_type, i as i32));
let elem =
bx.extract_element(vector, bx.context.new_rvalue_from_int(bx.int_type, i as i32));
let shifted = elem >> sign_shift;
let masked = shifted & one;
result = result | (bx.context.new_cast(None, masked, result_type) << bx.context.new_rvalue_from_int(result_type, shift));
result = result
| (bx.context.new_cast(None, masked, result_type)
<< bx.context.new_rvalue_from_int(result_type, shift));
shift += 1;
}
@ -394,46 +394,50 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
return Err(());
}};
}
let (elem_ty_str, elem_ty) =
if let ty::Float(f) = in_elem.kind() {
let elem_ty = bx.cx.type_float_from_ty(*f);
match f.bit_width() {
32 => ("f", elem_ty),
64 => ("", elem_ty),
_ => {
return_error!(InvalidMonomorphization::FloatingPointVector { span, name, f_ty: *f, in_ty });
}
let (elem_ty_str, elem_ty) = if let ty::Float(f) = in_elem.kind() {
let elem_ty = bx.cx.type_float_from_ty(*f);
match f.bit_width() {
32 => ("f", elem_ty),
64 => ("", elem_ty),
_ => {
return_error!(InvalidMonomorphization::FloatingPointVector {
span,
name,
f_ty: *f,
in_ty
});
}
}
else {
return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty });
};
} else {
return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty });
};
let vec_ty = bx.cx.type_vector(elem_ty, in_len);
let intr_name =
match name {
sym::simd_ceil => "ceil",
sym::simd_fabs => "fabs", // TODO(antoyo): pand with 170141183420855150465331762880109871103
sym::simd_fcos => "cos",
sym::simd_fexp2 => "exp2",
sym::simd_fexp => "exp",
sym::simd_flog10 => "log10",
sym::simd_flog2 => "log2",
sym::simd_flog => "log",
sym::simd_floor => "floor",
sym::simd_fma => "fma",
sym::simd_fpowi => "__builtin_powi",
sym::simd_fpow => "pow",
sym::simd_fsin => "sin",
sym::simd_fsqrt => "sqrt",
sym::simd_round => "round",
sym::simd_trunc => "trunc",
_ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name })
};
let intr_name = match name {
sym::simd_ceil => "ceil",
sym::simd_fabs => "fabs", // TODO(antoyo): pand with 170141183420855150465331762880109871103
sym::simd_fcos => "cos",
sym::simd_fexp2 => "exp2",
sym::simd_fexp => "exp",
sym::simd_flog10 => "log10",
sym::simd_flog2 => "log2",
sym::simd_flog => "log",
sym::simd_floor => "floor",
sym::simd_fma => "fma",
sym::simd_fpowi => "__builtin_powi",
sym::simd_fpow => "pow",
sym::simd_fsin => "sin",
sym::simd_fsqrt => "sqrt",
sym::simd_round => "round",
sym::simd_trunc => "trunc",
_ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }),
};
let builtin_name = format!("{}{}", intr_name, elem_ty_str);
let funcs = bx.cx.functions.borrow();
let function = funcs.get(&builtin_name).unwrap_or_else(|| panic!("unable to find builtin function {}", builtin_name));
let function = funcs
.get(&builtin_name)
.unwrap_or_else(|| panic!("unable to find builtin function {}", builtin_name));
// TODO(antoyo): add platform-specific behavior here for architectures that have these
// intrinsics as instructions (for instance, gpus)
@ -479,8 +483,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
return simd_simple_float_intrinsic(name, in_elem, in_ty, in_len, bx, span, args);
}
#[cfg(feature="master")]
fn vector_ty<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, elem_ty: Ty<'tcx>, vec_len: u64) -> Type<'gcc> {
#[cfg(feature = "master")]
fn vector_ty<'gcc, 'tcx>(
cx: &CodegenCx<'gcc, 'tcx>,
elem_ty: Ty<'tcx>,
vec_len: u64,
) -> Type<'gcc> {
// FIXME: use cx.layout_of(ty).llvm_type() ?
let elem_ty = match *elem_ty.kind() {
ty::Int(v) => cx.type_int_from_ty(v),
@ -491,15 +499,22 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
cx.type_vector(elem_ty, vec_len)
}
#[cfg(feature="master")]
fn gather<'a, 'gcc, 'tcx>(default: RValue<'gcc>, pointers: RValue<'gcc>, mask: RValue<'gcc>, pointer_count: usize, bx: &mut Builder<'a, 'gcc, 'tcx>, in_len: u64, underlying_ty: Ty<'tcx>, invert: bool) -> RValue<'gcc> {
let vector_type =
if pointer_count > 1 {
bx.context.new_vector_type(bx.usize_type, in_len)
}
else {
vector_ty(bx, underlying_ty, in_len)
};
#[cfg(feature = "master")]
fn gather<'a, 'gcc, 'tcx>(
default: RValue<'gcc>,
pointers: RValue<'gcc>,
mask: RValue<'gcc>,
pointer_count: usize,
bx: &mut Builder<'a, 'gcc, 'tcx>,
in_len: u64,
underlying_ty: Ty<'tcx>,
invert: bool,
) -> RValue<'gcc> {
let vector_type = if pointer_count > 1 {
bx.context.new_vector_type(bx.usize_type, in_len)
} else {
vector_ty(bx, underlying_ty, in_len)
};
let elem_type = vector_type.dyncast_vector().expect("vector type").get_element_type();
let mut values = vec![];
@ -530,13 +545,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
if invert {
bx.shuffle_vector(vector, default, mask)
}
else {
} else {
bx.shuffle_vector(default, vector, mask)
}
}
#[cfg(feature="master")]
#[cfg(feature = "master")]
if name == sym::simd_gather {
// simd_gather(values: <N x T>, pointers: <N x *_ T>,
// mask: <N x i{M}>) -> <N x T>
@ -546,8 +560,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
// All types must be simd vector types
require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty });
require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] });
require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] });
require_simd!(
arg_tys[1],
InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }
);
require_simd!(
arg_tys[2],
InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }
);
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
// Of the same length:
@ -641,10 +661,19 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
}
}
return Ok(gather(args[0].immediate(), args[1].immediate(), args[2].immediate(), pointer_count, bx, in_len, underlying_ty, false));
return Ok(gather(
args[0].immediate(),
args[1].immediate(),
args[2].immediate(),
pointer_count,
bx,
in_len,
underlying_ty,
false,
));
}
#[cfg(feature="master")]
#[cfg(feature = "master")]
if name == sym::simd_scatter {
// simd_scatter(values: <N x T>, pointers: <N x *mut T>,
// mask: <N x i{M}>) -> ()
@ -654,8 +683,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
// All types must be simd vector types
require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty });
require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] });
require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] });
require_simd!(
arg_tys[1],
InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }
);
require_simd!(
arg_tys[2],
InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }
);
// Of the same length:
let (element_len1, _) = arg_tys[1].simd_size_and_type(bx.tcx());
@ -744,17 +779,24 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
}
}
let result = gather(args[0].immediate(), args[1].immediate(), args[2].immediate(), pointer_count, bx, in_len, underlying_ty, true);
let result = gather(
args[0].immediate(),
args[1].immediate(),
args[2].immediate(),
pointer_count,
bx,
in_len,
underlying_ty,
true,
);
let pointers = args[1].immediate();
let vector_type =
if pointer_count > 1 {
bx.context.new_vector_type(bx.usize_type, in_len)
}
else {
vector_ty(bx, underlying_ty, in_len)
};
let vector_type = if pointer_count > 1 {
bx.context.new_vector_type(bx.usize_type, in_len)
} else {
vector_ty(bx, underlying_ty, in_len)
};
let elem_type = vector_type.dyncast_vector().expect("vector type").get_element_type();
for i in 0..in_len {
@ -809,11 +851,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
let rhs = args[1].immediate();
let is_add = name == sym::simd_saturating_add;
let ptr_bits = bx.tcx().data_layout.pointer_size.bits() as _;
let (signed, elem_width, elem_ty) =
match *in_elem.kind() {
ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)),
ty::Uint(i) => (false, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_uint_from_ty(i)),
_ => {
let (signed, elem_width, elem_ty) = match *in_elem.kind() {
ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)),
ty::Uint(i) => {
(false, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_uint_from_ty(i))
}
_ => {
return_error!(InvalidMonomorphization::ExpectedVectorElementType {
span,
name,
@ -823,77 +866,82 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
}
};
let result =
match (signed, is_add) {
(false, true) => {
let res = lhs + rhs;
let cmp = bx.context.new_comparison(None, ComparisonOp::LessThan, res, lhs);
res | cmp
},
(true, true) => {
// Algorithm from: https://codereview.stackexchange.com/questions/115869/saturated-signed-addition
// TODO(antoyo): improve using conditional operators if possible.
// TODO(antoyo): dyncast_vector should not require a call to unqualified.
let arg_type = lhs.get_type().unqualified();
// TODO(antoyo): convert lhs and rhs to unsigned.
let sum = lhs + rhs;
let vector_type = arg_type.dyncast_vector().expect("vector type");
let unit = vector_type.get_num_units();
let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1);
let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]);
let result = match (signed, is_add) {
(false, true) => {
let res = lhs + rhs;
let cmp = bx.context.new_comparison(None, ComparisonOp::LessThan, res, lhs);
res | cmp
}
(true, true) => {
// Algorithm from: https://codereview.stackexchange.com/questions/115869/saturated-signed-addition
// TODO(antoyo): improve using conditional operators if possible.
// TODO(antoyo): dyncast_vector should not require a call to unqualified.
let arg_type = lhs.get_type().unqualified();
// TODO(antoyo): convert lhs and rhs to unsigned.
let sum = lhs + rhs;
let vector_type = arg_type.dyncast_vector().expect("vector type");
let unit = vector_type.get_num_units();
let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1);
let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]);
let xor1 = lhs ^ rhs;
let xor2 = lhs ^ sum;
let and = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2;
let mask = and >> width;
let xor1 = lhs ^ rhs;
let xor2 = lhs ^ sum;
let and =
bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2;
let mask = and >> width;
let one = bx.context.new_rvalue_one(elem_ty);
let ones = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]);
let shift1 = ones << width;
let shift2 = sum >> width;
let mask_min = shift1 ^ shift2;
let one = bx.context.new_rvalue_one(elem_ty);
let ones =
bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]);
let shift1 = ones << width;
let shift2 = sum >> width;
let mask_min = shift1 ^ shift2;
let and1 = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum;
let and2 = mask & mask_min;
let and1 =
bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum;
let and2 = mask & mask_min;
and1 + and2
},
(false, false) => {
let res = lhs - rhs;
let cmp = bx.context.new_comparison(None, ComparisonOp::LessThanEquals, res, lhs);
res & cmp
},
(true, false) => {
// TODO(antoyo): dyncast_vector should not require a call to unqualified.
let arg_type = lhs.get_type().unqualified();
// TODO(antoyo): this uses the same algorithm from saturating add, but add the
// negative of the right operand. Find a proper subtraction algorithm.
let rhs = bx.context.new_unary_op(None, UnaryOp::Minus, arg_type, rhs);
and1 + and2
}
(false, false) => {
let res = lhs - rhs;
let cmp = bx.context.new_comparison(None, ComparisonOp::LessThanEquals, res, lhs);
res & cmp
}
(true, false) => {
// TODO(antoyo): dyncast_vector should not require a call to unqualified.
let arg_type = lhs.get_type().unqualified();
// TODO(antoyo): this uses the same algorithm from saturating add, but add the
// negative of the right operand. Find a proper subtraction algorithm.
let rhs = bx.context.new_unary_op(None, UnaryOp::Minus, arg_type, rhs);
// TODO(antoyo): convert lhs and rhs to unsigned.
let sum = lhs + rhs;
let vector_type = arg_type.dyncast_vector().expect("vector type");
let unit = vector_type.get_num_units();
let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1);
let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]);
// TODO(antoyo): convert lhs and rhs to unsigned.
let sum = lhs + rhs;
let vector_type = arg_type.dyncast_vector().expect("vector type");
let unit = vector_type.get_num_units();
let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1);
let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]);
let xor1 = lhs ^ rhs;
let xor2 = lhs ^ sum;
let and = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2;
let mask = and >> width;
let xor1 = lhs ^ rhs;
let xor2 = lhs ^ sum;
let and =
bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2;
let mask = and >> width;
let one = bx.context.new_rvalue_one(elem_ty);
let ones = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]);
let shift1 = ones << width;
let shift2 = sum >> width;
let mask_min = shift1 ^ shift2;
let one = bx.context.new_rvalue_one(elem_ty);
let ones =
bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]);
let shift1 = ones << width;
let shift2 = sum >> width;
let mask_min = shift1 ^ shift2;
let and1 = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum;
let and2 = mask & mask_min;
let and1 =
bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum;
let and2 = mask & mask_min;
and1 + and2
}
};
and1 + and2
}
};
return Ok(result);
}
@ -968,7 +1016,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
1.0
);
macro_rules! minmax_red {
($name:ident: $int_red:ident, $float_red:ident) => {
if name == sym::$name {
@ -979,13 +1026,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
return match in_elem.kind() {
ty::Int(_) | ty::Uint(_) => Ok(bx.$int_red(args[0].immediate())),
ty::Float(_) => Ok(bx.$float_red(args[0].immediate())),
_ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
span,
_ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
span,
name,
symbol: sym::$name,
in_ty,
in_elem,
ret_ty
in_elem,
ret_ty
}),
};
}
@ -1025,7 +1072,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
return match in_elem.kind() {
ty::Int(_) | ty::Uint(_) => {
let r = bx.vector_reduce_op(input, $op);
Ok(if !$boolean { r } else { bx.icmp(IntPredicate::IntNE, r, bx.context.new_rvalue_zero(r.get_type())) })
Ok(if !$boolean {
r
} else {
bx.icmp(
IntPredicate::IntNE,
r,
bx.context.new_rvalue_zero(r.get_type()),
)
})
}
_ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
span,

View file

@ -1020,28 +1020,20 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
));
}
if let Some(stripped) = name.as_str().strip_prefix("simd_shuffle") {
// If this intrinsic is the older "simd_shuffleN" form, simply parse the integer.
// If there is no suffix, use the index array length.
let n: u64 = if stripped.is_empty() {
// Make sure this is actually an array, since typeck only checks the length-suffixed
// version of this intrinsic.
match args[2].layout.ty.kind() {
ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => {
len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(
|| span_bug!(span, "could not evaluate shuffle index array length"),
)
}
_ => return_error!(InvalidMonomorphization::SimdShuffle {
span,
name,
ty: args[2].layout.ty
}),
if name == sym::simd_shuffle {
// Make sure this is actually an array, since typeck only checks the length-suffixed
// version of this intrinsic.
let n: u64 = match args[2].layout.ty.kind() {
ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => {
len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(
|| span_bug!(span, "could not evaluate shuffle index array length"),
)
}
} else {
stripped.parse().unwrap_or_else(|_| {
span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?")
})
_ => return_error!(InvalidMonomorphization::SimdShuffle {
span,
name,
ty: args[2].layout.ty
}),
};
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });

View file

@ -3,9 +3,6 @@ name = "rustc_codegen_ssa"
version = "0.0.0"
edition = "2021"
[lib]
test = false
[dependencies]
ar_archive_writer = "0.1.3"
bitflags = "1.2.1"

View file

@ -862,11 +862,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
.iter()
.enumerate()
.map(|(i, arg)| {
// The indices passed to simd_shuffle* in the
// The indices passed to simd_shuffle in the
// third argument must be constant. This is
// checked by const-qualification, which also
// promotes any complex rvalues to constants.
if i == 2 && intrinsic.as_str().starts_with("simd_shuffle") {
if i == 2 && intrinsic == sym::simd_shuffle {
if let mir::Operand::Constant(constant) = arg {
let (llval, ty) = self.simd_shuffle_indices(&bx, constant);
return OperandRef {

View file

@ -16,7 +16,7 @@ extern "platform-intrinsic" {
The `simd_shuffle` function needs the length of the array passed as
last parameter in its name. Example:
```
```ignore (no longer compiles)
#![feature(platform_intrinsics)]
extern "platform-intrinsic" {

View file

@ -567,20 +567,6 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
| sym::simd_reduce_min_nanless
| sym::simd_reduce_max_nanless => (2, vec![param(0)], param(1)),
sym::simd_shuffle => (3, vec![param(0), param(0), param(1)], param(2)),
name if name.as_str().starts_with("simd_shuffle") => {
match name.as_str()["simd_shuffle".len()..].parse() {
Ok(n) => {
let params = vec![param(0), param(0), Ty::new_array(tcx, tcx.types.u32, n)];
(2, params, param(1))
}
Err(_) => {
let msg =
format!("unrecognized platform-specific intrinsic function: `{name}`");
tcx.sess.struct_span_err(it.span, msg).emit();
return;
}
}
}
_ => {
let msg = format!("unrecognized platform-specific intrinsic function: `{name}`");
tcx.sess.struct_span_err(it.span, msg).emit();

View file

@ -305,7 +305,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
terminator.kind = TerminatorKind::Unreachable;
}
}
_ if intrinsic_name.as_str().starts_with("simd_shuffle") => {
sym::simd_shuffle => {
validate_simd_shuffle(tcx, args, terminator.source_info.span);
}
_ => {}

View file

@ -461,6 +461,12 @@ parse_loop_else = `{$loop_kind}...else` loops are not supported
.note = consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
.loop_keyword = `else` is attached to this loop
parse_macro_expands_to_adt_field = macros cannot expand to {$adt_ty} fields
parse_macro_expands_to_enum_variant = macros cannot expand to enum variants
parse_macro_expands_to_match_arm = macros cannot expand to match arms
parse_macro_invocation_visibility = can't qualify macro invocation with `pub`
.suggestion = remove the visibility
.help = try adjusting the macro to put `{$vis}` inside the invocation

View file

@ -1815,6 +1815,12 @@ pub struct UnknownPrefix<'a> {
pub sugg: Option<UnknownPrefixSugg>,
}
#[derive(Subdiagnostic)]
#[note(parse_macro_expands_to_adt_field)]
pub struct MacroExpandsToAdtField<'a> {
pub adt_ty: &'a str,
}
#[derive(Subdiagnostic)]
pub enum UnknownPrefixSugg {
#[suggestion(

View file

@ -2641,6 +2641,7 @@ impl<'a> Parser<'a> {
pub(crate) fn maybe_recover_unexpected_comma(
&mut self,
lo: Span,
is_mac_invoc: bool,
rt: CommaRecoveryMode,
) -> PResult<'a, ()> {
if self.token != token::Comma {
@ -2661,24 +2662,28 @@ impl<'a> Parser<'a> {
let seq_span = lo.to(self.prev_token.span);
let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern");
if let Ok(seq_snippet) = self.span_to_snippet(seq_span) {
err.multipart_suggestion(
format!(
"try adding parentheses to match on a tuple{}",
if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." },
),
vec![
(seq_span.shrink_to_lo(), "(".to_string()),
(seq_span.shrink_to_hi(), ")".to_string()),
],
Applicability::MachineApplicable,
);
if let CommaRecoveryMode::EitherTupleOrPipe = rt {
err.span_suggestion(
seq_span,
"...or a vertical bar to match on multiple alternatives",
seq_snippet.replace(',', " |"),
if is_mac_invoc {
err.note(fluent::parse_macro_expands_to_match_arm);
} else {
err.multipart_suggestion(
format!(
"try adding parentheses to match on a tuple{}",
if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." },
),
vec![
(seq_span.shrink_to_lo(), "(".to_string()),
(seq_span.shrink_to_hi(), ")".to_string()),
],
Applicability::MachineApplicable,
);
if let CommaRecoveryMode::EitherTupleOrPipe = rt {
err.span_suggestion(
seq_span,
"...or a vertical bar to match on multiple alternatives",
seq_snippet.replace(',', " |"),
Applicability::MachineApplicable,
);
}
}
}
Err(err)

View file

@ -1,8 +1,8 @@
use crate::errors;
use super::diagnostics::{dummy_arg, ConsumeClosingDelim};
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken};
use crate::errors::{self, MacroExpandsToAdtField};
use crate::fluent_generated as fluent;
use ast::StaticItem;
use rustc_ast::ast::*;
use rustc_ast::ptr::P;
@ -1450,6 +1450,17 @@ impl<'a> Parser<'a> {
}
let ident = this.parse_field_ident("enum", vlo)?;
if this.token == token::Not {
if let Err(mut err) = this.unexpected::<()>() {
err.note(fluent::parse_macro_expands_to_enum_variant).emit();
}
this.bump();
this.parse_delim_args()?;
return Ok((None, TrailingToken::MaybeComma));
}
let struct_def = if this.check(&token::OpenDelim(Delimiter::Brace)) {
// Parse a struct variant.
let (fields, recovered) =
@ -1477,7 +1488,7 @@ impl<'a> Parser<'a> {
Ok((Some(vr), TrailingToken::MaybeComma))
},
).map_err(|mut err|{
).map_err(|mut err| {
err.help("enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`");
err
})
@ -1687,7 +1698,8 @@ impl<'a> Parser<'a> {
self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
let lo = this.token.span;
let vis = this.parse_visibility(FollowedByType::No)?;
Ok((this.parse_single_struct_field(adt_ty, lo, vis, attrs)?, TrailingToken::None))
this.parse_single_struct_field(adt_ty, lo, vis, attrs)
.map(|field| (field, TrailingToken::None))
})
}
@ -1821,8 +1833,8 @@ impl<'a> Parser<'a> {
"field names and their types are separated with `:`",
":",
Applicability::MachineApplicable,
);
err.emit();
)
.emit();
} else {
return Err(err);
}
@ -1839,6 +1851,23 @@ impl<'a> Parser<'a> {
attrs: AttrVec,
) -> PResult<'a, FieldDef> {
let name = self.parse_field_ident(adt_ty, lo)?;
// Parse the macro invocation and recover
if self.token.kind == token::Not {
if let Err(mut err) = self.unexpected::<FieldDef>() {
err.subdiagnostic(MacroExpandsToAdtField { adt_ty }).emit();
self.bump();
self.parse_delim_args()?;
return Ok(FieldDef {
span: DUMMY_SP,
ident: None,
vis,
id: DUMMY_NODE_ID,
ty: self.mk_ty(DUMMY_SP, TyKind::Err),
attrs,
is_placeholder: false,
});
}
}
self.expect_field_ty_separator()?;
let ty = self.parse_ty()?;
if self.token.kind == token::Colon && self.look_ahead(1, |tok| tok.kind != token::Colon) {

View file

@ -142,7 +142,11 @@ impl<'a> Parser<'a> {
// Parse the first pattern (`p_0`).
let mut first_pat = self.parse_pat_no_top_alt(expected, syntax_loc)?;
if rc == RecoverComma::Yes {
self.maybe_recover_unexpected_comma(first_pat.span, rt)?;
self.maybe_recover_unexpected_comma(
first_pat.span,
matches!(first_pat.kind, PatKind::MacCall(_)),
rt,
)?;
}
// If the next token is not a `|`,
@ -184,7 +188,7 @@ impl<'a> Parser<'a> {
err
})?;
if rc == RecoverComma::Yes {
self.maybe_recover_unexpected_comma(pat.span, rt)?;
self.maybe_recover_unexpected_comma(pat.span, false, rt)?;
}
pats.push(pat);
}

View file

@ -987,9 +987,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let target = self.infcx.shallow_resolve(target);
debug!(?source, ?target, "confirm_builtin_unsize_candidate");
let mut nested = vec![];
let src;
match (source.kind(), target.kind()) {
Ok(match (source.kind(), target.kind()) {
// Trait+Kx+'a -> Trait+Ky+'b (auto traits and lifetime subtyping).
(&ty::Dynamic(ref data_a, r_a, dyn_a), &ty::Dynamic(ref data_b, r_b, dyn_b))
if dyn_a == dyn_b =>
@ -1016,16 +1014,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Require that the traits involved in this upcast are **equal**;
// only the **lifetime bound** is changed.
let InferOk { obligations, .. } = self
let InferOk { mut obligations, .. } = self
.infcx
.at(&obligation.cause, obligation.param_env)
.sup(DefineOpaqueTypes::No, target, source_trait)
.map_err(|_| Unimplemented)?;
nested.extend(obligations);
// Register one obligation for 'a: 'b.
let outlives = ty::OutlivesPredicate(r_a, r_b);
nested.push(Obligation::with_depth(
obligations.push(Obligation::with_depth(
tcx,
obligation.cause.clone(),
obligation.recursion_depth + 1,
@ -1033,7 +1030,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation.predicate.rebind(outlives),
));
src = BuiltinImplSource::Misc;
ImplSource::Builtin(BuiltinImplSource::Misc, obligations)
}
// `T` -> `Trait`
@ -1059,11 +1056,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// words, if the object type is `Foo + Send`, this would create an obligation for
// the `Send` check.)
// - Projection predicates
nested.extend(
data.iter().map(|predicate| {
predicate_to_obligation(predicate.with_self_ty(tcx, source))
}),
);
let mut nested: Vec<_> = data
.iter()
.map(|predicate| predicate_to_obligation(predicate.with_self_ty(tcx, source)))
.collect();
// We can only make objects from sized types.
let tr = ty::TraitRef::from_lang_item(
@ -1081,7 +1077,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ty::Binder::dummy(ty::ClauseKind::TypeOutlives(outlives)).to_predicate(tcx),
));
src = BuiltinImplSource::Misc;
ImplSource::Builtin(BuiltinImplSource::Misc, nested)
}
// `[T; n]` -> `[T]`
@ -1091,9 +1087,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.at(&obligation.cause, obligation.param_env)
.eq(DefineOpaqueTypes::No, b, a)
.map_err(|_| Unimplemented)?;
nested.extend(obligations);
src = BuiltinImplSource::Misc;
ImplSource::Builtin(BuiltinImplSource::Misc, obligations)
}
// `Struct<T>` -> `Struct<U>`
@ -1106,6 +1101,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let tail_field = def.non_enum_variant().tail();
let tail_field_ty = tcx.type_of(tail_field.did);
let mut nested = vec![];
// Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`,
// normalizing in the process, since `type_of` returns something directly from
// astconv (which means it's un-normalized).
@ -1151,7 +1148,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
);
nested.push(tail_unsize_obligation);
src = BuiltinImplSource::Misc;
ImplSource::Builtin(BuiltinImplSource::Misc, nested)
}
// `(.., T)` -> `(.., U)`
@ -1166,27 +1163,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// last element is equal to the target.
let new_tuple =
Ty::new_tup_from_iter(tcx, a_mid.iter().copied().chain(iter::once(b_last)));
let InferOk { obligations, .. } = self
let InferOk { mut obligations, .. } = self
.infcx
.at(&obligation.cause, obligation.param_env)
.eq(DefineOpaqueTypes::No, target, new_tuple)
.map_err(|_| Unimplemented)?;
nested.extend(obligations);
// Add a nested `T: Unsize<U>` predicate.
let last_unsize_obligation = obligation.with(
tcx,
ty::TraitRef::new(tcx, obligation.predicate.def_id(), [a_last, b_last]),
);
nested.push(last_unsize_obligation);
obligations.push(last_unsize_obligation);
src = BuiltinImplSource::TupleUnsizing;
ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, obligations)
}
_ => bug!("source: {source}, target: {target}"),
};
Ok(ImplSource::Builtin(src, nested))
})
}
fn confirm_const_destruct_candidate(

View file

@ -89,6 +89,12 @@ enum FdMeta {
NoneObtained,
}
#[derive(PartialEq)]
enum FdHandle {
Input,
Output,
}
impl FdMeta {
fn maybe_fifo(&self) -> bool {
match self {
@ -114,12 +120,14 @@ impl FdMeta {
}
}
fn copy_file_range_candidate(&self) -> bool {
fn copy_file_range_candidate(&self, f: FdHandle) -> bool {
match self {
// copy_file_range will fail on empty procfs files. `read` can determine whether EOF has been reached
// without extra cost and skip the write, thus there is no benefit in attempting copy_file_range
FdMeta::Metadata(meta) if meta.is_file() && meta.len() > 0 => true,
FdMeta::NoneObtained => true,
FdMeta::Metadata(meta) if f == FdHandle::Input && meta.is_file() && meta.len() > 0 => {
true
}
FdMeta::Metadata(meta) if f == FdHandle::Output && meta.is_file() => true,
_ => false,
}
}
@ -197,7 +205,9 @@ impl<R: CopyRead, W: CopyWrite> SpecCopy for Copier<'_, '_, R, W> {
written += flush()?;
let max_write = reader.min_limit();
if input_meta.copy_file_range_candidate() && output_meta.copy_file_range_candidate() {
if input_meta.copy_file_range_candidate(FdHandle::Input)
&& output_meta.copy_file_range_candidate(FdHandle::Output)
{
let result = copy_regular_files(readfd, writefd, max_write);
result.update_take(reader);

View file

@ -1939,7 +1939,8 @@ impl<'test> TestCx<'test> {
let mut test_client =
Command::new(self.config.remote_test_client.as_ref().unwrap());
test_client
.args(&["run", &support_libs.len().to_string(), &prog])
.args(&["run", &support_libs.len().to_string()])
.arg(&prog)
.args(support_libs)
.args(args);
@ -2525,7 +2526,7 @@ impl<'test> TestCx<'test> {
// If this is emscripten, then run tests under nodejs
if self.config.target.contains("emscripten") {
if let Some(ref p) = self.config.nodejs {
args.push(p.clone());
args.push(p.into());
} else {
self.fatal("emscripten target requested and no NodeJS binary found (--nodejs)");
}
@ -2533,7 +2534,7 @@ impl<'test> TestCx<'test> {
// shim
} else if self.config.target.contains("wasm32") {
if let Some(ref p) = self.config.nodejs {
args.push(p.clone());
args.push(p.into());
} else {
self.fatal("wasm32 target requested and no NodeJS binary found (--nodejs)");
}
@ -2545,13 +2546,12 @@ impl<'test> TestCx<'test> {
.unwrap() // chop off `ui`
.parent()
.unwrap(); // chop off `tests`
args.push(src.join("src/etc/wasm32-shim.js").display().to_string());
args.push(src.join("src/etc/wasm32-shim.js").into_os_string());
}
let exe_file = self.make_exe_name();
// FIXME (#9639): This needs to handle non-utf8 paths
args.push(exe_file.to_str().unwrap().to_owned());
args.push(exe_file.into_os_string());
// Add the arguments in the run_flags directive
args.extend(self.split_maybe_args(&self.props.run_flags));
@ -2560,12 +2560,16 @@ impl<'test> TestCx<'test> {
ProcArgs { prog, args }
}
fn split_maybe_args(&self, argstr: &Option<String>) -> Vec<String> {
fn split_maybe_args(&self, argstr: &Option<String>) -> Vec<OsString> {
match *argstr {
Some(ref s) => s
.split(' ')
.filter_map(|s| {
if s.chars().all(|c| c.is_whitespace()) { None } else { Some(s.to_owned()) }
if s.chars().all(|c| c.is_whitespace()) {
None
} else {
Some(OsString::from(s))
}
})
.collect(),
None => Vec::new(),
@ -4372,8 +4376,8 @@ impl<'test> TestCx<'test> {
}
struct ProcArgs {
prog: String,
args: Vec<String>,
prog: OsString,
args: Vec<OsString>,
}
pub struct ProcRes {

View file

@ -6,13 +6,13 @@
struct I32x2(i32, i32);
extern "platform-intrinsic" {
fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
fn simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U;
}
fn main() {
unsafe {
const IDX: [u32; 2] = [0, 0];
let _: I32x2 = simd_shuffle2(I32x2(1, 2), I32x2(3, 4), IDX);
let _: I32x2 = simd_shuffle2(I32x2(1, 2), I32x2(3, 4), IDX);
let _: I32x2 = simd_shuffle(I32x2(1, 2), I32x2(3, 4), IDX);
let _: I32x2 = simd_shuffle(I32x2(1, 2), I32x2(3, 4), IDX);
}
}

View file

@ -29,52 +29,39 @@ click: "#help-button"
assert-css: ("#help-button .popover", {"display": "none"})
assert-css: ("#settings-menu .popover", {"display": "none"})
define-function: (
"check-popover-colors",
(theme, border_color),
block {
set-local-storage: {
"rustdoc-theme": |theme|,
"rustdoc-use-system-theme": "false",
}
reload:
click: "#help-button"
assert-css: (
"#help-button .popover",
{"display": "block", "border-color": |border_color|},
)
compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-color"])
compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"])
}
)
// We check the borders color now:
// Ayu theme
set-local-storage: {
"rustdoc-theme": "ayu",
"rustdoc-use-system-theme": "false",
}
reload:
click: "#help-button"
assert-css: (
"#help-button .popover",
{"display": "block", "border-color": "rgb(92, 103, 115)"},
)
compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-color"])
compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"])
// Dark theme
set-local-storage: {
"rustdoc-theme": "dark",
"rustdoc-use-system-theme": "false",
}
reload:
click: "#help-button"
assert-css: (
"#help-button .popover",
{"display": "block", "border-color": "rgb(224, 224, 224)"},
)
compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-color"])
compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"])
// Light theme
set-local-storage: {
"rustdoc-theme": "light",
"rustdoc-use-system-theme": "false",
}
reload:
click: "#help-button"
assert-css: (
"#help-button .popover",
{"display": "block", "border-color": "rgb(224, 224, 224)"},
)
compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-color"])
compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"])
call-function: ("check-popover-colors", {
"theme": "ayu",
"border_color": "#5c6773",
})
call-function: ("check-popover-colors", {
"theme": "dark",
"border_color": "#e0e0e0",
})
call-function: ("check-popover-colors", {
"theme": "light",
"border_color": "#e0e0e0",
})
// Opening the mobile sidebar should close the settings popover.
set-window-size: (650, 600)

View file

@ -141,7 +141,7 @@ call-function: ("check-colors", {
"theme": "ayu",
"color": "#c5c5c5",
"color_hover": "#ffb44c",
"background": "rgb(20, 25, 31)",
"background": "#14191f",
"background_hover": "#14191f",
"background_toggle": "rgba(0, 0, 0, 0)",
"background_toggle_hover": "rgba(70, 70, 70, 0.33)",

View file

@ -0,0 +1,70 @@
// compile-flags: --crate-type=lib
macro_rules! field {
($name:ident:$type:ty) => {
$name:$type
};
}
macro_rules! variant {
($name:ident) => {
$name
}
}
struct Struct {
field!(bar:u128),
//~^ NOTE macros cannot expand to struct fields
//~| ERROR unexpected token: `!`
//~| NOTE unexpected token after this
a: u32,
b: u32,
field!(recovers:()), //~ NOTE macros cannot expand to struct fields
//~^ ERROR unexpected token: `!`
//~^^ NOTE unexpected token after this
}
enum EnumVariant {
variant!(whoops),
//~^ NOTE macros cannot expand to enum variants
//~| ERROR unexpected token: `!`
//~| NOTE unexpected token after this
U32,
F64,
variant!(recovers),
//~^ NOTE macros cannot expand to enum variants
//~| ERROR unexpected token: `!`
//~| NOTE unexpected token after this
Data {
field!(x:u32),
//~^ NOTE macros cannot expand to struct fields
//~| ERROR unexpected token: `!`
//~| NOTE unexpected token after this
}
}
enum EnumVariantField {
Named {
field!(oopsies:()),
//~^ NOTE macros cannot expand to struct fields
//~| ERROR unexpected token: `!`
//~| unexpected token after this
field!(oopsies2:()),
//~^ NOTE macros cannot expand to struct fields
//~| ERROR unexpected token: `!`
//~| unexpected token after this
},
}
union Union {
A: u32,
field!(oopsies:()),
//~^ NOTE macros cannot expand to union fields
//~| ERROR unexpected token: `!`
//~| unexpected token after this
B: u32,
field!(recovers:()),
//~^ NOTE macros cannot expand to union fields
//~| ERROR unexpected token: `!`
//~| unexpected token after this
}

View file

@ -0,0 +1,74 @@
error: unexpected token: `!`
--> $DIR/macro-expand-to-field.rs:16:10
|
LL | field!(bar:u128),
| ^ unexpected token after this
|
= note: macros cannot expand to struct fields
error: unexpected token: `!`
--> $DIR/macro-expand-to-field.rs:22:10
|
LL | field!(recovers:()),
| ^ unexpected token after this
|
= note: macros cannot expand to struct fields
error: unexpected token: `!`
--> $DIR/macro-expand-to-field.rs:28:12
|
LL | variant!(whoops),
| ^ unexpected token after this
|
= note: macros cannot expand to enum variants
error: unexpected token: `!`
--> $DIR/macro-expand-to-field.rs:34:12
|
LL | variant!(recovers),
| ^ unexpected token after this
|
= note: macros cannot expand to enum variants
error: unexpected token: `!`
--> $DIR/macro-expand-to-field.rs:39:14
|
LL | field!(x:u32),
| ^ unexpected token after this
|
= note: macros cannot expand to struct fields
error: unexpected token: `!`
--> $DIR/macro-expand-to-field.rs:48:14
|
LL | field!(oopsies:()),
| ^ unexpected token after this
|
= note: macros cannot expand to struct fields
error: unexpected token: `!`
--> $DIR/macro-expand-to-field.rs:52:14
|
LL | field!(oopsies2:()),
| ^ unexpected token after this
|
= note: macros cannot expand to struct fields
error: unexpected token: `!`
--> $DIR/macro-expand-to-field.rs:61:10
|
LL | field!(oopsies:()),
| ^ unexpected token after this
|
= note: macros cannot expand to union fields
error: unexpected token: `!`
--> $DIR/macro-expand-to-field.rs:66:10
|
LL | field!(recovers:()),
| ^ unexpected token after this
|
= note: macros cannot expand to union fields
error: aborting due to 9 previous errors

View file

@ -0,0 +1,18 @@
macro_rules! arm {
($pattern:pat => $block:block) => {
$pattern => $block
};
}
fn main() {
let x = Some(1);
match x {
Some(1) => {},
arm!(None => {}),
//~^ NOTE macros cannot expand to match arms
//~| ERROR unexpected `,` in pattern
// doesn't recover
Some(2) => {},
_ => {},
};
}

View file

@ -0,0 +1,10 @@
error: unexpected `,` in pattern
--> $DIR/macro-expand-to-match-arm.rs:11:25
|
LL | arm!(None => {}),
| ^
|
= note: macros cannot expand to match arms
error: aborting due to previous error

View file

@ -22,9 +22,7 @@ extern "platform-intrinsic" {
fn simd_insert<T, E>(x: T, idx: u32, y: E) -> T;
fn simd_extract<T, E>(x: T, idx: u32) -> E;
fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
fn simd_shuffle4<T, U>(x: T, y: T, idx: [u32; 4]) -> U;
fn simd_shuffle8<T, U>(x: T, y: T, idx: [u32; 8]) -> U;
fn simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U;
}
macro_rules! all_eq {
@ -83,19 +81,19 @@ fn main() {
let y4 = i32x4(140, 141, 142, 143);
let y8 = i32x8(180, 181, 182, 183, 184, 185, 186, 187);
unsafe {
all_eq!(simd_shuffle2(x2, y2, const { [3u32, 0] }), i32x2(121, 20));
all_eq!(simd_shuffle4(x2, y2, const { [3u32, 0, 1, 2] }), i32x4(121, 20, 21, 120));
all_eq!(simd_shuffle8(x2, y2, const { [3u32, 0, 1, 2, 1, 2, 3, 0] }),
all_eq!(simd_shuffle(x2, y2, const { [3u32, 0] }), i32x2(121, 20));
all_eq!(simd_shuffle(x2, y2, const { [3u32, 0, 1, 2] }), i32x4(121, 20, 21, 120));
all_eq!(simd_shuffle(x2, y2, const { [3u32, 0, 1, 2, 1, 2, 3, 0] }),
i32x8(121, 20, 21, 120, 21, 120, 121, 20));
all_eq!(simd_shuffle2(x4, y4, const { [7u32, 2] }), i32x2(143, 42));
all_eq!(simd_shuffle4(x4, y4, const { [7u32, 2, 5, 0] }), i32x4(143, 42, 141, 40));
all_eq!(simd_shuffle8(x4, y4, const { [7u32, 2, 5, 0, 3, 6, 4, 1] }),
all_eq!(simd_shuffle(x4, y4, const { [7u32, 2] }), i32x2(143, 42));
all_eq!(simd_shuffle(x4, y4, const { [7u32, 2, 5, 0] }), i32x4(143, 42, 141, 40));
all_eq!(simd_shuffle(x4, y4, const { [7u32, 2, 5, 0, 3, 6, 4, 1] }),
i32x8(143, 42, 141, 40, 43, 142, 140, 41));
all_eq!(simd_shuffle2(x8, y8, const { [11u32, 5] }), i32x2(183, 85));
all_eq!(simd_shuffle4(x8, y8, const { [11u32, 5, 15, 0] }), i32x4(183, 85, 187, 80));
all_eq!(simd_shuffle8(x8, y8, const { [11u32, 5, 15, 0, 3, 8, 12, 1] }),
all_eq!(simd_shuffle(x8, y8, const { [11u32, 5] }), i32x2(183, 85));
all_eq!(simd_shuffle(x8, y8, const { [11u32, 5, 15, 0] }), i32x4(183, 85, 187, 80));
all_eq!(simd_shuffle(x8, y8, const { [11u32, 5, 15, 0, 3, 8, 12, 1] }),
i32x8(183, 85, 187, 80, 83, 180, 184, 81));
}

View file

@ -34,9 +34,7 @@ extern "platform-intrinsic" {
fn simd_insert<T, E>(x: T, idx: u32, y: E) -> T;
fn simd_extract<T, E>(x: T, idx: u32) -> E;
fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
fn simd_shuffle4<T, U>(x: T, y: T, idx: [u32; 4]) -> U;
fn simd_shuffle8<T, U>(x: T, y: T, idx: [u32; 8]) -> U;
fn simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U;
}
fn main() {
@ -51,27 +49,27 @@ fn main() {
//~^ ERROR expected return type `i32` (element of input `i32x4`), found `f32`
const IDX2: [u32; 2] = [0; 2];
simd_shuffle2::<i32, i32>(0, 0, IDX2);
simd_shuffle::<i32, _, i32>(0, 0, IDX2);
//~^ ERROR expected SIMD input type, found non-SIMD `i32`
const IDX4: [u32; 4] = [0; 4];
simd_shuffle4::<i32, i32>(0, 0, IDX4);
simd_shuffle::<i32, _, i32>(0, 0, IDX4);
//~^ ERROR expected SIMD input type, found non-SIMD `i32`
const IDX8: [u32; 8] = [0; 8];
simd_shuffle8::<i32, i32>(0, 0, IDX8);
simd_shuffle::<i32, _, i32>(0, 0, IDX8);
//~^ ERROR expected SIMD input type, found non-SIMD `i32`
simd_shuffle2::<_, f32x2>(x, x, IDX2);
simd_shuffle::<_, _, f32x2>(x, x, IDX2);
//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32`
simd_shuffle4::<_, f32x4>(x, x, IDX4);
simd_shuffle::<_, _, f32x4>(x, x, IDX4);
//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32`
simd_shuffle8::<_, f32x8>(x, x, IDX8);
simd_shuffle::<_, _, f32x8>(x, x, IDX8);
//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32`
simd_shuffle2::<_, i32x8>(x, x, IDX2);
simd_shuffle::<_, _, i32x8>(x, x, IDX2);
//~^ ERROR expected return type of length 2, found `i32x8` with length 8
simd_shuffle4::<_, i32x8>(x, x, IDX4);
simd_shuffle::<_, _, i32x8>(x, x, IDX4);
//~^ ERROR expected return type of length 4, found `i32x8` with length 8
simd_shuffle8::<_, i32x2>(x, x, IDX8);
simd_shuffle::<_, _, i32x2>(x, x, IDX8);
//~^ ERROR expected return type of length 8, found `i32x2` with length 2
}
}

View file

@ -1,74 +1,74 @@
error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected SIMD input type, found non-SIMD `i32`
--> $DIR/generic-elements.rs:46:9
--> $DIR/generic-elements.rs:44:9
|
LL | simd_insert(0, 0, 0);
| ^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected inserted type `i32` (element of input `i32x4`), found `f64`
--> $DIR/generic-elements.rs:48:9
--> $DIR/generic-elements.rs:46:9
|
LL | simd_insert(x, 0, 1.0);
| ^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_extract` intrinsic: expected return type `i32` (element of input `i32x4`), found `f32`
--> $DIR/generic-elements.rs:50:9
--> $DIR/generic-elements.rs:48:9
|
LL | simd_extract::<_, f32>(x, 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected SIMD input type, found non-SIMD `i32`
--> $DIR/generic-elements.rs:54:9
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32`
--> $DIR/generic-elements.rs:52:9
|
LL | simd_shuffle2::<i32, i32>(0, 0, IDX2);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | simd_shuffle::<i32, _, i32>(0, 0, IDX2);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected SIMD input type, found non-SIMD `i32`
--> $DIR/generic-elements.rs:57:9
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32`
--> $DIR/generic-elements.rs:55:9
|
LL | simd_shuffle4::<i32, i32>(0, 0, IDX4);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | simd_shuffle::<i32, _, i32>(0, 0, IDX4);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected SIMD input type, found non-SIMD `i32`
--> $DIR/generic-elements.rs:60:9
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32`
--> $DIR/generic-elements.rs:58:9
|
LL | simd_shuffle8::<i32, i32>(0, 0, IDX8);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | simd_shuffle::<i32, _, i32>(0, 0, IDX8);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32`
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32`
--> $DIR/generic-elements.rs:61:9
|
LL | simd_shuffle::<_, _, f32x2>(x, x, IDX2);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32`
--> $DIR/generic-elements.rs:63:9
|
LL | simd_shuffle2::<_, f32x2>(x, x, IDX2);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | simd_shuffle::<_, _, f32x4>(x, x, IDX4);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32`
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32`
--> $DIR/generic-elements.rs:65:9
|
LL | simd_shuffle4::<_, f32x4>(x, x, IDX4);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | simd_shuffle::<_, _, f32x8>(x, x, IDX8);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32`
--> $DIR/generic-elements.rs:67:9
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `i32x8` with length 8
--> $DIR/generic-elements.rs:68:9
|
LL | simd_shuffle8::<_, f32x8>(x, x, IDX8);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | simd_shuffle::<_, _, i32x8>(x, x, IDX2);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return type of length 2, found `i32x8` with length 8
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 4, found `i32x8` with length 8
--> $DIR/generic-elements.rs:70:9
|
LL | simd_shuffle2::<_, i32x8>(x, x, IDX2);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | simd_shuffle::<_, _, i32x8>(x, x, IDX4);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return type of length 4, found `i32x8` with length 8
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 8, found `i32x2` with length 2
--> $DIR/generic-elements.rs:72:9
|
LL | simd_shuffle4::<_, i32x8>(x, x, IDX4);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return type of length 8, found `i32x2` with length 2
--> $DIR/generic-elements.rs:74:9
|
LL | simd_shuffle8::<_, i32x2>(x, x, IDX8);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | simd_shuffle::<_, _, i32x2>(x, x, IDX8);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 12 previous errors

View file

@ -6,7 +6,7 @@
#![feature(platform_intrinsics, repr_simd)]
extern "platform-intrinsic" {
fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
fn simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U;
}
#[repr(simd)]
@ -22,5 +22,5 @@ fn main() {
#[inline(always)]
unsafe fn inline_me() -> Simd2 {
const IDX: [u32; 2] = [0, 3];
simd_shuffle2(Simd2(10, 11), Simd2(12, 13), IDX)
simd_shuffle(Simd2(10, 11), Simd2(12, 13), IDX)
}

View file

@ -6,7 +6,7 @@
#![feature(platform_intrinsics, repr_simd)]
extern "platform-intrinsic" {
fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
fn simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U;
}
#[repr(simd)]
@ -16,7 +16,7 @@ struct Simd2(u8, u8);
fn main() {
unsafe {
const IDX: [u32; 2] = [0, 1];
let p_res: Simd2 = simd_shuffle2(Simd2(10, 11), Simd2(12, 13), IDX);
let p_res: Simd2 = simd_shuffle(Simd2(10, 11), Simd2(12, 13), IDX);
let a_res: Simd2 = inline_me();
assert_10_11(p_res);
@ -38,5 +38,5 @@ fn assert_10_13(x: Simd2) {
#[inline(always)]
unsafe fn inline_me() -> Simd2 {
const IDX: [u32; 2] = [0, 3];
simd_shuffle2(Simd2(10, 11), Simd2(12, 13), IDX)
simd_shuffle(Simd2(10, 11), Simd2(12, 13), IDX)
}

View file

@ -29,12 +29,7 @@ struct u8x32([u8; 32]);
struct u8x64([u8; 64]);
extern "platform-intrinsic" {
pub fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
pub fn simd_shuffle4<T, U>(x: T, y: T, idx: [u32; 4]) -> U;
pub fn simd_shuffle8<T, U>(x: T, y: T, idx: [u32; 8]) -> U;
pub fn simd_shuffle16<T, U>(x: T, y: T, idx: [u32; 16]) -> U;
pub fn simd_shuffle32<T, U>(x: T, y: T, idx: [u32; 32]) -> U;
pub fn simd_shuffle64<T, U>(x: T, y: T, idx: [u32; 64]) -> U;
pub fn simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U;
}
// Test vectors by lane size. Since LLVM does not distinguish between a shuffle
@ -58,22 +53,22 @@ macro_rules! test_shuffle_lanes {
}
}
}
//~^^^^^ ERROR: invalid monomorphization of `simd_shuffle2` intrinsic
//~| ERROR: invalid monomorphization of `simd_shuffle4` intrinsic
//~| ERROR: invalid monomorphization of `simd_shuffle8` intrinsic
//~| ERROR: invalid monomorphization of `simd_shuffle16` intrinsic
//~| ERROR: invalid monomorphization of `simd_shuffle32` intrinsic
//~| ERROR: invalid monomorphization of `simd_shuffle64` intrinsic
//~^^^^^ ERROR: invalid monomorphization of `simd_shuffle` intrinsic
//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic
//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic
//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic
//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic
//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic
// Because the test is mostly embedded in a macro, all the errors have the same origin point.
// And unfortunately, standard comments, as in the UI test harness, disappear in macros!
fn main() {
test_shuffle_lanes!(2, u8x2, simd_shuffle2);
test_shuffle_lanes!(4, u8x4, simd_shuffle4);
test_shuffle_lanes!(8, u8x8, simd_shuffle8);
test_shuffle_lanes!(16, u8x16, simd_shuffle16);
test_shuffle_lanes!(32, u8x32, simd_shuffle32);
test_shuffle_lanes!(64, u8x64, simd_shuffle64);
test_shuffle_lanes!(2, u8x2, simd_shuffle);
test_shuffle_lanes!(4, u8x4, simd_shuffle);
test_shuffle_lanes!(8, u8x8, simd_shuffle);
test_shuffle_lanes!(16, u8x16, simd_shuffle);
test_shuffle_lanes!(32, u8x32, simd_shuffle);
test_shuffle_lanes!(64, u8x64, simd_shuffle);
extern "platform-intrinsic" {
fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;

View file

@ -1,71 +1,71 @@
error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: shuffle index #0 is out of bounds (limit 4)
--> $DIR/shuffle-not-out-of-bounds.rs:56:21
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
|
LL | $y(vec1, vec2, ARR)
| ^^^^^^^^^^^^^^^^^^^
...
LL | test_shuffle_lanes!(2, u8x2, simd_shuffle2);
| ------------------------------------------- in this macro invocation
LL | test_shuffle_lanes!(2, u8x2, simd_shuffle);
| ------------------------------------------ in this macro invocation
|
= 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_shuffle4` intrinsic: shuffle index #0 is out of bounds (limit 8)
--> $DIR/shuffle-not-out-of-bounds.rs:56:21
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
|
LL | $y(vec1, vec2, ARR)
| ^^^^^^^^^^^^^^^^^^^
...
LL | test_shuffle_lanes!(4, u8x4, simd_shuffle4);
| ------------------------------------------- in this macro invocation
LL | test_shuffle_lanes!(4, u8x4, simd_shuffle);
| ------------------------------------------ in this macro invocation
|
= 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_shuffle8` intrinsic: shuffle index #0 is out of bounds (limit 16)
--> $DIR/shuffle-not-out-of-bounds.rs:56:21
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
|
LL | $y(vec1, vec2, ARR)
| ^^^^^^^^^^^^^^^^^^^
...
LL | test_shuffle_lanes!(8, u8x8, simd_shuffle8);
| ------------------------------------------- in this macro invocation
LL | test_shuffle_lanes!(8, u8x8, simd_shuffle);
| ------------------------------------------ in this macro invocation
|
= 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_shuffle16` intrinsic: shuffle index #0 is out of bounds (limit 32)
--> $DIR/shuffle-not-out-of-bounds.rs:56:21
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
|
LL | $y(vec1, vec2, ARR)
| ^^^^^^^^^^^^^^^^^^^
...
LL | test_shuffle_lanes!(16, u8x16, simd_shuffle16);
| ---------------------------------------------- in this macro invocation
LL | test_shuffle_lanes!(16, u8x16, simd_shuffle);
| -------------------------------------------- in this macro invocation
|
= 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_shuffle32` intrinsic: shuffle index #0 is out of bounds (limit 64)
--> $DIR/shuffle-not-out-of-bounds.rs:56:21
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
|
LL | $y(vec1, vec2, ARR)
| ^^^^^^^^^^^^^^^^^^^
...
LL | test_shuffle_lanes!(32, u8x32, simd_shuffle32);
| ---------------------------------------------- in this macro invocation
LL | test_shuffle_lanes!(32, u8x32, simd_shuffle);
| -------------------------------------------- in this macro invocation
|
= 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_shuffle64` intrinsic: shuffle index #0 is out of bounds (limit 128)
--> $DIR/shuffle-not-out-of-bounds.rs:56:21
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
|
LL | $y(vec1, vec2, ARR)
| ^^^^^^^^^^^^^^^^^^^
...
LL | test_shuffle_lanes!(64, u8x64, simd_shuffle64);
| ---------------------------------------------- in this macro invocation
LL | test_shuffle_lanes!(64, u8x64, simd_shuffle);
| -------------------------------------------- in this macro invocation
|
= 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:84:23
--> $DIR/shuffle-not-out-of-bounds.rs:79:23
|
LL | let _: u8x2 = simd_shuffle(v, v, I);
| ^^^^^^^^^^^^^^^^^^^^^

View file

@ -8,7 +8,6 @@
extern "platform-intrinsic" {
fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;
fn simd_shuffle16<T, U>(x: T, y: T, idx: [u32; 16]) -> U;
}
#[derive(Copy, Clone)]
@ -16,7 +15,7 @@ extern "platform-intrinsic" {
struct Simd<T, const N: usize>([T; N]);
pub unsafe fn __shuffle_vector16<const IDX: [u32; 16], T, U>(x: T, y: T) -> U {
simd_shuffle16(x, y, IDX)
simd_shuffle(x, y, IDX)
}
fn main() {