Auto merge of #118780 - GuillaumeGomez:rollup-nd0syaf, r=GuillaumeGomez
Rollup of 6 pull requests Successful merges: - #117953 (Add more SIMD platform-intrinsics) - #118057 (dedup for duplicate suggestions) - #118638 (More `rustc_mir_dataflow` cleanups) - #118702 (Strengthen well known check-cfg names and values test) - #118734 (Unescaping cleanups) - #118766 (Lower some forgotten spans) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
08587a56f1
35 changed files with 1115 additions and 299 deletions
|
@ -634,7 +634,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// Resume argument type: `ResumeTy`
|
||||
let unstable_span = self.mark_span_with_reason(
|
||||
DesugaringKind::Async,
|
||||
span,
|
||||
self.lower_span(span),
|
||||
Some(self.allow_gen_future.clone()),
|
||||
);
|
||||
let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span);
|
||||
|
@ -766,7 +766,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// Resume argument type: `ResumeTy`
|
||||
let unstable_span = self.mark_span_with_reason(
|
||||
DesugaringKind::Async,
|
||||
span,
|
||||
self.lower_span(span),
|
||||
Some(self.allow_gen_future.clone()),
|
||||
);
|
||||
let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span);
|
||||
|
|
|
@ -1382,6 +1382,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let host_param_parts = if let Const::Yes(span) = constness
|
||||
&& self.tcx.features().effects
|
||||
{
|
||||
let span = self.lower_span(span);
|
||||
let param_node_id = self.next_node_id();
|
||||
let hir_id = self.next_id();
|
||||
let def_id = self.create_def(
|
||||
|
|
|
@ -1679,7 +1679,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
duplicated_lifetime_node_id,
|
||||
lifetime.ident.name,
|
||||
DefKind::LifetimeParam,
|
||||
lifetime.ident.span,
|
||||
self.lower_span(lifetime.ident.span),
|
||||
);
|
||||
captured_to_synthesized_mapping.insert(old_def_id, duplicated_lifetime_def_id);
|
||||
// FIXME: Instead of doing this, we could move this whole loop
|
||||
|
@ -1688,7 +1688,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
synthesized_lifetime_definitions.push((
|
||||
duplicated_lifetime_node_id,
|
||||
duplicated_lifetime_def_id,
|
||||
lifetime.ident,
|
||||
self.lower_ident(lifetime.ident),
|
||||
));
|
||||
|
||||
// Now make an arg that we can use for the generic params of the opaque tykind.
|
||||
|
@ -2253,7 +2253,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
match c.value.kind {
|
||||
ExprKind::Underscore => {
|
||||
if self.tcx.features().generic_arg_infer {
|
||||
hir::ArrayLen::Infer(self.lower_node_id(c.id), c.value.span)
|
||||
hir::ArrayLen::Infer(self.lower_node_id(c.id), self.lower_span(c.value.span))
|
||||
} else {
|
||||
feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
|
|
|
@ -11,101 +11,88 @@ use rustc_middle::ty::TyCtxt;
|
|||
use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces};
|
||||
use rustc_mir_dataflow::ResultsVisitable;
|
||||
use rustc_mir_dataflow::{self, fmt::DebugWithContext, GenKill};
|
||||
use rustc_mir_dataflow::{Analysis, Direction, Results};
|
||||
use rustc_mir_dataflow::{Analysis, AnalysisDomain, Results};
|
||||
use std::fmt;
|
||||
|
||||
use crate::{places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext};
|
||||
|
||||
/// A tuple with named fields that can hold either the results or the transient state of the
|
||||
/// dataflow analyses used by the borrow checker.
|
||||
#[derive(Debug)]
|
||||
pub struct BorrowckAnalyses<B, U, E> {
|
||||
pub borrows: B,
|
||||
pub uninits: U,
|
||||
pub ever_inits: E,
|
||||
}
|
||||
|
||||
/// The results of the dataflow analyses used by the borrow checker.
|
||||
pub type BorrowckResults<'mir, 'tcx> = BorrowckAnalyses<
|
||||
Results<'tcx, Borrows<'mir, 'tcx>>,
|
||||
Results<'tcx, MaybeUninitializedPlaces<'mir, 'tcx>>,
|
||||
Results<'tcx, EverInitializedPlaces<'mir, 'tcx>>,
|
||||
>;
|
||||
pub struct BorrowckResults<'mir, 'tcx> {
|
||||
pub(crate) borrows: Results<'tcx, Borrows<'mir, 'tcx>>,
|
||||
pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'mir, 'tcx>>,
|
||||
pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'mir, 'tcx>>,
|
||||
}
|
||||
|
||||
/// The transient state of the dataflow analyses used by the borrow checker.
|
||||
pub type BorrowckFlowState<'mir, 'tcx> =
|
||||
<BorrowckResults<'mir, 'tcx> as ResultsVisitable<'tcx>>::FlowState;
|
||||
|
||||
macro_rules! impl_visitable {
|
||||
( $(
|
||||
$T:ident { $( $field:ident : $A:ident ),* $(,)? }
|
||||
)* ) => { $(
|
||||
impl<'tcx, $($A),*, D: Direction> ResultsVisitable<'tcx> for $T<$( Results<'tcx, $A> ),*>
|
||||
where
|
||||
$( $A: Analysis<'tcx, Direction = D>, )*
|
||||
{
|
||||
type Direction = D;
|
||||
type FlowState = $T<$( $A::Domain ),*>;
|
||||
|
||||
fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
|
||||
$T {
|
||||
$( $field: self.$field.analysis.bottom_value(body) ),*
|
||||
}
|
||||
}
|
||||
|
||||
fn reset_to_block_entry(
|
||||
&self,
|
||||
state: &mut Self::FlowState,
|
||||
block: BasicBlock,
|
||||
) {
|
||||
$( state.$field.clone_from(&self.$field.entry_set_for_block(block)); )*
|
||||
}
|
||||
|
||||
fn reconstruct_before_statement_effect(
|
||||
&mut self,
|
||||
state: &mut Self::FlowState,
|
||||
stmt: &mir::Statement<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
$( self.$field.analysis
|
||||
.apply_before_statement_effect(&mut state.$field, stmt, loc); )*
|
||||
}
|
||||
|
||||
fn reconstruct_statement_effect(
|
||||
&mut self,
|
||||
state: &mut Self::FlowState,
|
||||
stmt: &mir::Statement<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
$( self.$field.analysis
|
||||
.apply_statement_effect(&mut state.$field, stmt, loc); )*
|
||||
}
|
||||
|
||||
fn reconstruct_before_terminator_effect(
|
||||
&mut self,
|
||||
state: &mut Self::FlowState,
|
||||
term: &mir::Terminator<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
$( self.$field.analysis
|
||||
.apply_before_terminator_effect(&mut state.$field, term, loc); )*
|
||||
}
|
||||
|
||||
fn reconstruct_terminator_effect(
|
||||
&mut self,
|
||||
state: &mut Self::FlowState,
|
||||
term: &mir::Terminator<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
$( self.$field.analysis
|
||||
.apply_terminator_effect(&mut state.$field, term, loc); )*
|
||||
}
|
||||
}
|
||||
)* }
|
||||
#[derive(Debug)]
|
||||
pub struct BorrowckFlowState<'mir, 'tcx> {
|
||||
pub(crate) borrows: <Borrows<'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
|
||||
pub(crate) uninits: <MaybeUninitializedPlaces<'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
|
||||
pub(crate) ever_inits: <EverInitializedPlaces<'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
|
||||
}
|
||||
|
||||
impl_visitable! {
|
||||
BorrowckAnalyses { borrows: B, uninits: U, ever_inits: E }
|
||||
impl<'mir, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'mir, 'tcx> {
|
||||
// All three analyses are forward, but we have to use just one here.
|
||||
type Direction = <Borrows<'mir, 'tcx> as AnalysisDomain<'tcx>>::Direction;
|
||||
type FlowState = BorrowckFlowState<'mir, 'tcx>;
|
||||
|
||||
fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
|
||||
BorrowckFlowState {
|
||||
borrows: self.borrows.analysis.bottom_value(body),
|
||||
uninits: self.uninits.analysis.bottom_value(body),
|
||||
ever_inits: self.ever_inits.analysis.bottom_value(body),
|
||||
}
|
||||
}
|
||||
|
||||
fn reset_to_block_entry(&self, state: &mut Self::FlowState, block: BasicBlock) {
|
||||
state.borrows.clone_from(&self.borrows.entry_set_for_block(block));
|
||||
state.uninits.clone_from(&self.uninits.entry_set_for_block(block));
|
||||
state.ever_inits.clone_from(&self.ever_inits.entry_set_for_block(block));
|
||||
}
|
||||
|
||||
fn reconstruct_before_statement_effect(
|
||||
&mut self,
|
||||
state: &mut Self::FlowState,
|
||||
stmt: &mir::Statement<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
self.borrows.analysis.apply_before_statement_effect(&mut state.borrows, stmt, loc);
|
||||
self.uninits.analysis.apply_before_statement_effect(&mut state.uninits, stmt, loc);
|
||||
self.ever_inits.analysis.apply_before_statement_effect(&mut state.ever_inits, stmt, loc);
|
||||
}
|
||||
|
||||
fn reconstruct_statement_effect(
|
||||
&mut self,
|
||||
state: &mut Self::FlowState,
|
||||
stmt: &mir::Statement<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
self.borrows.analysis.apply_statement_effect(&mut state.borrows, stmt, loc);
|
||||
self.uninits.analysis.apply_statement_effect(&mut state.uninits, stmt, loc);
|
||||
self.ever_inits.analysis.apply_statement_effect(&mut state.ever_inits, stmt, loc);
|
||||
}
|
||||
|
||||
fn reconstruct_before_terminator_effect(
|
||||
&mut self,
|
||||
state: &mut Self::FlowState,
|
||||
term: &mir::Terminator<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
self.borrows.analysis.apply_before_terminator_effect(&mut state.borrows, term, loc);
|
||||
self.uninits.analysis.apply_before_terminator_effect(&mut state.uninits, term, loc);
|
||||
self.ever_inits.analysis.apply_before_terminator_effect(&mut state.ever_inits, term, loc);
|
||||
}
|
||||
|
||||
fn reconstruct_terminator_effect(
|
||||
&mut self,
|
||||
state: &mut Self::FlowState,
|
||||
term: &mir::Terminator<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
self.borrows.analysis.apply_terminator_effect(&mut state.borrows, term, loc);
|
||||
self.uninits.analysis.apply_terminator_effect(&mut state.uninits, term, loc);
|
||||
self.ever_inits.analysis.apply_terminator_effect(&mut state.ever_inits, term, loc);
|
||||
}
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
|
@ -598,7 +585,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
|
|||
|
||||
fn before_terminator_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
trans: &mut Self::Domain,
|
||||
_terminator: &mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
|
@ -625,7 +612,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
|
|||
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
_trans: &mut impl GenKill<Self::Idx>,
|
||||
_trans: &mut Self::Domain,
|
||||
_block: mir::BasicBlock,
|
||||
_return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//! Codegen `extern "platform-intrinsic"` intrinsics.
|
||||
|
||||
use cranelift_codegen::ir::immediates::Offset32;
|
||||
use rustc_middle::ty::GenericArgsRef;
|
||||
use rustc_span::Symbol;
|
||||
use rustc_target::abi::Endian;
|
||||
|
@ -1008,8 +1009,57 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
sym::simd_masked_load => {
|
||||
intrinsic_args!(fx, args => (mask, ptr, val); intrinsic);
|
||||
|
||||
let (val_lane_count, val_lane_ty) = val.layout().ty.simd_size_and_type(fx.tcx);
|
||||
let (mask_lane_count, _mask_lane_ty) = mask.layout().ty.simd_size_and_type(fx.tcx);
|
||||
let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
|
||||
assert_eq!(val_lane_count, mask_lane_count);
|
||||
assert_eq!(val_lane_count, ret_lane_count);
|
||||
|
||||
let lane_clif_ty = fx.clif_type(val_lane_ty).unwrap();
|
||||
let ret_lane_layout = fx.layout_of(ret_lane_ty);
|
||||
let ptr_val = ptr.load_scalar(fx);
|
||||
|
||||
for lane_idx in 0..ret_lane_count {
|
||||
let val_lane = val.value_lane(fx, lane_idx).load_scalar(fx);
|
||||
let mask_lane = mask.value_lane(fx, lane_idx).load_scalar(fx);
|
||||
|
||||
let if_enabled = fx.bcx.create_block();
|
||||
let if_disabled = fx.bcx.create_block();
|
||||
let next = fx.bcx.create_block();
|
||||
let res_lane = fx.bcx.append_block_param(next, lane_clif_ty);
|
||||
|
||||
fx.bcx.ins().brif(mask_lane, if_enabled, &[], if_disabled, &[]);
|
||||
fx.bcx.seal_block(if_enabled);
|
||||
fx.bcx.seal_block(if_disabled);
|
||||
|
||||
fx.bcx.switch_to_block(if_enabled);
|
||||
let offset = lane_idx as i32 * lane_clif_ty.bytes() as i32;
|
||||
let res = fx.bcx.ins().load(
|
||||
lane_clif_ty,
|
||||
MemFlags::trusted(),
|
||||
ptr_val,
|
||||
Offset32::new(offset),
|
||||
);
|
||||
fx.bcx.ins().jump(next, &[res]);
|
||||
|
||||
fx.bcx.switch_to_block(if_disabled);
|
||||
fx.bcx.ins().jump(next, &[val_lane]);
|
||||
|
||||
fx.bcx.seal_block(next);
|
||||
fx.bcx.switch_to_block(next);
|
||||
|
||||
fx.bcx.ins().nop();
|
||||
|
||||
ret.place_lane(fx, lane_idx)
|
||||
.write_cvalue(fx, CValue::by_val(res_lane, ret_lane_layout));
|
||||
}
|
||||
}
|
||||
|
||||
sym::simd_scatter => {
|
||||
intrinsic_args!(fx, args => (val, ptr, mask); intrinsic);
|
||||
intrinsic_args!(fx, args => (mask, ptr, val); intrinsic);
|
||||
|
||||
let (val_lane_count, _val_lane_ty) = val.layout().ty.simd_size_and_type(fx.tcx);
|
||||
let (ptr_lane_count, _ptr_lane_ty) = ptr.layout().ty.simd_size_and_type(fx.tcx);
|
||||
|
|
|
@ -1492,6 +1492,198 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
return Ok(v);
|
||||
}
|
||||
|
||||
if name == sym::simd_masked_load {
|
||||
// simd_masked_load(mask: <N x i{M}>, pointer: *_ T, values: <N x T>) -> <N x T>
|
||||
// * N: number of elements in the input vectors
|
||||
// * T: type of the element to load
|
||||
// * M: any integer width is supported, will be truncated to i1
|
||||
// Loads contiguous elements from memory behind `pointer`, but only for
|
||||
// those lanes whose `mask` bit is enabled.
|
||||
// The memory addresses corresponding to the “off” lanes are not accessed.
|
||||
|
||||
// The element type of the "mask" argument must be a signed integer type of any width
|
||||
let mask_ty = in_ty;
|
||||
let (mask_len, mask_elem) = (in_len, in_elem);
|
||||
|
||||
// The second argument must be a pointer matching the element type
|
||||
let pointer_ty = arg_tys[1];
|
||||
|
||||
// The last argument is a passthrough vector providing values for disabled lanes
|
||||
let values_ty = arg_tys[2];
|
||||
let (values_len, values_elem) = require_simd!(values_ty, SimdThird);
|
||||
|
||||
require_simd!(ret_ty, SimdReturn);
|
||||
|
||||
// Of the same length:
|
||||
require!(
|
||||
values_len == mask_len,
|
||||
InvalidMonomorphization::ThirdArgumentLength {
|
||||
span,
|
||||
name,
|
||||
in_len: mask_len,
|
||||
in_ty: mask_ty,
|
||||
arg_ty: values_ty,
|
||||
out_len: values_len
|
||||
}
|
||||
);
|
||||
|
||||
// The return type must match the last argument type
|
||||
require!(
|
||||
ret_ty == values_ty,
|
||||
InvalidMonomorphization::ExpectedReturnType { span, name, in_ty: values_ty, ret_ty }
|
||||
);
|
||||
|
||||
require!(
|
||||
matches!(
|
||||
pointer_ty.kind(),
|
||||
ty::RawPtr(p) if p.ty == values_elem && p.ty.kind() == values_elem.kind()
|
||||
),
|
||||
InvalidMonomorphization::ExpectedElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: values_elem,
|
||||
second_arg: pointer_ty,
|
||||
in_elem: values_elem,
|
||||
in_ty: values_ty,
|
||||
mutability: ExpectedPointerMutability::Not,
|
||||
}
|
||||
);
|
||||
|
||||
require!(
|
||||
matches!(mask_elem.kind(), ty::Int(_)),
|
||||
InvalidMonomorphization::ThirdArgElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: values_elem,
|
||||
third_arg: mask_ty,
|
||||
}
|
||||
);
|
||||
|
||||
// Alignment of T, must be a constant integer value:
|
||||
let alignment_ty = bx.type_i32();
|
||||
let alignment = bx.const_i32(bx.align_of(values_ty).bytes() as i32);
|
||||
|
||||
// Truncate the mask vector to a vector of i1s:
|
||||
let (mask, mask_ty) = {
|
||||
let i1 = bx.type_i1();
|
||||
let i1xn = bx.type_vector(i1, mask_len);
|
||||
(bx.trunc(args[0].immediate(), i1xn), i1xn)
|
||||
};
|
||||
|
||||
let llvm_pointer = bx.type_ptr();
|
||||
|
||||
// Type of the vector of elements:
|
||||
let llvm_elem_vec_ty = llvm_vector_ty(bx, values_elem, values_len);
|
||||
let llvm_elem_vec_str = llvm_vector_str(bx, values_elem, values_len);
|
||||
|
||||
let llvm_intrinsic = format!("llvm.masked.load.{llvm_elem_vec_str}.p0");
|
||||
let fn_ty = bx
|
||||
.type_func(&[llvm_pointer, alignment_ty, mask_ty, llvm_elem_vec_ty], llvm_elem_vec_ty);
|
||||
let f = bx.declare_cfn(&llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty);
|
||||
let v = bx.call(
|
||||
fn_ty,
|
||||
None,
|
||||
None,
|
||||
f,
|
||||
&[args[1].immediate(), alignment, mask, args[2].immediate()],
|
||||
None,
|
||||
);
|
||||
return Ok(v);
|
||||
}
|
||||
|
||||
if name == sym::simd_masked_store {
|
||||
// simd_masked_store(mask: <N x i{M}>, pointer: *mut T, values: <N x T>) -> ()
|
||||
// * N: number of elements in the input vectors
|
||||
// * T: type of the element to load
|
||||
// * M: any integer width is supported, will be truncated to i1
|
||||
// Stores contiguous elements to memory behind `pointer`, but only for
|
||||
// those lanes whose `mask` bit is enabled.
|
||||
// The memory addresses corresponding to the “off” lanes are not accessed.
|
||||
|
||||
// The element type of the "mask" argument must be a signed integer type of any width
|
||||
let mask_ty = in_ty;
|
||||
let (mask_len, mask_elem) = (in_len, in_elem);
|
||||
|
||||
// The second argument must be a pointer matching the element type
|
||||
let pointer_ty = arg_tys[1];
|
||||
|
||||
// The last argument specifies the values to store to memory
|
||||
let values_ty = arg_tys[2];
|
||||
let (values_len, values_elem) = require_simd!(values_ty, SimdThird);
|
||||
|
||||
// Of the same length:
|
||||
require!(
|
||||
values_len == mask_len,
|
||||
InvalidMonomorphization::ThirdArgumentLength {
|
||||
span,
|
||||
name,
|
||||
in_len: mask_len,
|
||||
in_ty: mask_ty,
|
||||
arg_ty: values_ty,
|
||||
out_len: values_len
|
||||
}
|
||||
);
|
||||
|
||||
// The second argument must be a mutable pointer type matching the element type
|
||||
require!(
|
||||
matches!(
|
||||
pointer_ty.kind(),
|
||||
ty::RawPtr(p) if p.ty == values_elem && p.ty.kind() == values_elem.kind() && p.mutbl.is_mut()
|
||||
),
|
||||
InvalidMonomorphization::ExpectedElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: values_elem,
|
||||
second_arg: pointer_ty,
|
||||
in_elem: values_elem,
|
||||
in_ty: values_ty,
|
||||
mutability: ExpectedPointerMutability::Mut,
|
||||
}
|
||||
);
|
||||
|
||||
require!(
|
||||
matches!(mask_elem.kind(), ty::Int(_)),
|
||||
InvalidMonomorphization::ThirdArgElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: values_elem,
|
||||
third_arg: mask_ty,
|
||||
}
|
||||
);
|
||||
|
||||
// Alignment of T, must be a constant integer value:
|
||||
let alignment_ty = bx.type_i32();
|
||||
let alignment = bx.const_i32(bx.align_of(values_elem).bytes() as i32);
|
||||
|
||||
// Truncate the mask vector to a vector of i1s:
|
||||
let (mask, mask_ty) = {
|
||||
let i1 = bx.type_i1();
|
||||
let i1xn = bx.type_vector(i1, in_len);
|
||||
(bx.trunc(args[0].immediate(), i1xn), i1xn)
|
||||
};
|
||||
|
||||
let ret_t = bx.type_void();
|
||||
|
||||
let llvm_pointer = bx.type_ptr();
|
||||
|
||||
// Type of the vector of elements:
|
||||
let llvm_elem_vec_ty = llvm_vector_ty(bx, values_elem, values_len);
|
||||
let llvm_elem_vec_str = llvm_vector_str(bx, values_elem, values_len);
|
||||
|
||||
let llvm_intrinsic = format!("llvm.masked.store.{llvm_elem_vec_str}.p0");
|
||||
let fn_ty = bx.type_func(&[llvm_elem_vec_ty, llvm_pointer, alignment_ty, mask_ty], ret_t);
|
||||
let f = bx.declare_cfn(&llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty);
|
||||
let v = bx.call(
|
||||
fn_ty,
|
||||
None,
|
||||
None,
|
||||
f,
|
||||
&[args[2].immediate(), args[1].immediate(), alignment, mask],
|
||||
None,
|
||||
);
|
||||
return Ok(v);
|
||||
}
|
||||
|
||||
if name == sym::simd_scatter {
|
||||
// simd_scatter(values: <N x T>, pointers: <N x *mut T>,
|
||||
// mask: <N x i{M}>) -> ()
|
||||
|
|
|
@ -591,17 +591,18 @@ impl Diagnostic {
|
|||
pub fn multipart_suggestion_with_style(
|
||||
&mut self,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestion: Vec<(Span, String)>,
|
||||
mut suggestion: Vec<(Span, String)>,
|
||||
applicability: Applicability,
|
||||
style: SuggestionStyle,
|
||||
) -> &mut Self {
|
||||
let mut parts = suggestion
|
||||
suggestion.sort_unstable();
|
||||
suggestion.dedup();
|
||||
|
||||
let parts = suggestion
|
||||
.into_iter()
|
||||
.map(|(span, snippet)| SubstitutionPart { snippet, span })
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
parts.sort_unstable_by_key(|part| part.span);
|
||||
|
||||
assert!(!parts.is_empty());
|
||||
debug_assert_eq!(
|
||||
parts.iter().find(|part| part.span.is_empty() && part.snippet.is_empty()),
|
||||
|
|
|
@ -521,6 +521,8 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
|
|||
sym::simd_fpowi => (1, 0, vec![param(0), tcx.types.i32], param(0)),
|
||||
sym::simd_fma => (1, 0, vec![param(0), param(0), param(0)], param(0)),
|
||||
sym::simd_gather => (3, 0, vec![param(0), param(1), param(2)], param(0)),
|
||||
sym::simd_masked_load => (3, 0, vec![param(0), param(1), param(2)], param(2)),
|
||||
sym::simd_masked_store => (3, 0, vec![param(0), param(1), param(2)], Ty::new_unit(tcx)),
|
||||
sym::simd_scatter => (3, 0, vec![param(0), param(1), param(2)], Ty::new_unit(tcx)),
|
||||
sym::simd_insert => (2, 0, vec![param(0), tcx.types.u32, param(1)], param(0)),
|
||||
sym::simd_extract => (2, 0, vec![param(0), tcx.types.u32], param(1)),
|
||||
|
|
|
@ -4,10 +4,14 @@
|
|||
use std::ops::Range;
|
||||
use std::str::Chars;
|
||||
|
||||
use Mode::*;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// Errors and warnings that can occur during string unescaping.
|
||||
/// Errors and warnings that can occur during string unescaping. They mostly
|
||||
/// relate to malformed escape sequences, but there are a few that are about
|
||||
/// other problems.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum EscapeError {
|
||||
/// Expected 1 char, but 0 were found.
|
||||
|
@ -73,25 +77,24 @@ impl EscapeError {
|
|||
}
|
||||
}
|
||||
|
||||
/// Takes a contents of a literal (without quotes) and produces a
|
||||
/// sequence of escaped characters or errors.
|
||||
/// Values are returned through invoking of the provided callback.
|
||||
/// Takes a contents of a literal (without quotes) and produces a sequence of
|
||||
/// escaped characters or errors.
|
||||
///
|
||||
/// Values are returned by invoking `callback`. For `Char` and `Byte` modes,
|
||||
/// the callback will be called exactly once.
|
||||
pub fn unescape_literal<F>(src: &str, mode: Mode, callback: &mut F)
|
||||
where
|
||||
F: FnMut(Range<usize>, Result<char, EscapeError>),
|
||||
{
|
||||
match mode {
|
||||
Mode::Char | Mode::Byte => {
|
||||
Char | Byte => {
|
||||
let mut chars = src.chars();
|
||||
let res = unescape_char_or_byte(&mut chars, mode == Mode::Byte);
|
||||
let res = unescape_char_or_byte(&mut chars, mode);
|
||||
callback(0..(src.len() - chars.as_str().len()), res);
|
||||
}
|
||||
Mode::Str | Mode::ByteStr => unescape_str_common(src, mode, callback),
|
||||
|
||||
Mode::RawStr | Mode::RawByteStr => {
|
||||
unescape_raw_str_or_raw_byte_str(src, mode == Mode::RawByteStr, callback)
|
||||
}
|
||||
Mode::CStr | Mode::RawCStr => unreachable!(),
|
||||
Str | ByteStr => unescape_str_common(src, mode, callback),
|
||||
RawStr | RawByteStr => unescape_raw_str_or_raw_byte_str(src, mode, callback),
|
||||
CStr | RawCStr => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,38 +120,44 @@ pub fn unescape_c_string<F>(src: &str, mode: Mode, callback: &mut F)
|
|||
where
|
||||
F: FnMut(Range<usize>, Result<CStrUnit, EscapeError>),
|
||||
{
|
||||
if mode == Mode::RawCStr {
|
||||
unescape_raw_str_or_raw_byte_str(
|
||||
src,
|
||||
mode.characters_should_be_ascii(),
|
||||
&mut |r, result| callback(r, result.map(CStrUnit::Char)),
|
||||
);
|
||||
} else {
|
||||
unescape_str_common(src, mode, callback);
|
||||
match mode {
|
||||
CStr => {
|
||||
unescape_str_common(src, mode, callback);
|
||||
}
|
||||
RawCStr => {
|
||||
unescape_raw_str_or_raw_byte_str(src, mode, &mut |r, result| {
|
||||
callback(r, result.map(CStrUnit::Char))
|
||||
});
|
||||
}
|
||||
Char | Byte | Str | RawStr | ByteStr | RawByteStr => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes a contents of a char literal (without quotes), and returns an
|
||||
/// unescaped char or an error.
|
||||
pub fn unescape_char(src: &str) -> Result<char, EscapeError> {
|
||||
unescape_char_or_byte(&mut src.chars(), false)
|
||||
unescape_char_or_byte(&mut src.chars(), Char)
|
||||
}
|
||||
|
||||
/// Takes a contents of a byte literal (without quotes), and returns an
|
||||
/// unescaped byte or an error.
|
||||
pub fn unescape_byte(src: &str) -> Result<u8, EscapeError> {
|
||||
unescape_char_or_byte(&mut src.chars(), true).map(byte_from_char)
|
||||
unescape_char_or_byte(&mut src.chars(), Byte).map(byte_from_char)
|
||||
}
|
||||
|
||||
/// What kind of literal do we parse.
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum Mode {
|
||||
Char,
|
||||
Str,
|
||||
|
||||
Byte,
|
||||
ByteStr,
|
||||
|
||||
Str,
|
||||
RawStr,
|
||||
|
||||
ByteStr,
|
||||
RawByteStr,
|
||||
|
||||
CStr,
|
||||
RawCStr,
|
||||
}
|
||||
|
@ -156,45 +165,42 @@ pub enum Mode {
|
|||
impl Mode {
|
||||
pub fn in_double_quotes(self) -> bool {
|
||||
match self {
|
||||
Mode::Str
|
||||
| Mode::ByteStr
|
||||
| Mode::RawStr
|
||||
| Mode::RawByteStr
|
||||
| Mode::CStr
|
||||
| Mode::RawCStr => true,
|
||||
Mode::Char | Mode::Byte => false,
|
||||
Str | RawStr | ByteStr | RawByteStr | CStr | RawCStr => true,
|
||||
Char | Byte => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Non-byte literals should have `\xXX` escapes that are within the ASCII range.
|
||||
pub fn ascii_escapes_should_be_ascii(self) -> bool {
|
||||
fn ascii_escapes_should_be_ascii(self) -> bool {
|
||||
match self {
|
||||
Mode::Char | Mode::Str | Mode::RawStr => true,
|
||||
Mode::Byte | Mode::ByteStr | Mode::RawByteStr | Mode::CStr | Mode::RawCStr => false,
|
||||
Char | Str => true,
|
||||
Byte | ByteStr | CStr => false,
|
||||
RawStr | RawByteStr | RawCStr => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether characters within the literal must be within the ASCII range
|
||||
pub fn characters_should_be_ascii(self) -> bool {
|
||||
/// Whether characters within the literal must be within the ASCII range.
|
||||
#[inline]
|
||||
fn chars_should_be_ascii(self) -> bool {
|
||||
match self {
|
||||
Mode::Byte | Mode::ByteStr | Mode::RawByteStr => true,
|
||||
Mode::Char | Mode::Str | Mode::RawStr | Mode::CStr | Mode::RawCStr => false,
|
||||
Byte | ByteStr | RawByteStr => true,
|
||||
Char | Str | RawStr | CStr | RawCStr => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Byte literals do not allow unicode escape.
|
||||
pub fn is_unicode_escape_disallowed(self) -> bool {
|
||||
fn is_unicode_escape_disallowed(self) -> bool {
|
||||
match self {
|
||||
Mode::Byte | Mode::ByteStr | Mode::RawByteStr => true,
|
||||
Mode::Char | Mode::Str | Mode::RawStr | Mode::CStr | Mode::RawCStr => false,
|
||||
Byte | ByteStr | RawByteStr => true,
|
||||
Char | Str | RawStr | CStr | RawCStr => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prefix_noraw(self) -> &'static str {
|
||||
match self {
|
||||
Mode::Byte | Mode::ByteStr | Mode::RawByteStr => "b",
|
||||
Mode::CStr | Mode::RawCStr => "c",
|
||||
Mode::Char | Mode::Str | Mode::RawStr => "",
|
||||
Char | Str | RawStr => "",
|
||||
Byte | ByteStr | RawByteStr => "b",
|
||||
CStr | RawCStr => "c",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -294,22 +300,21 @@ fn scan_unicode(
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn ascii_check(c: char, characters_should_be_ascii: bool) -> Result<char, EscapeError> {
|
||||
if characters_should_be_ascii && !c.is_ascii() {
|
||||
// Byte literal can't be a non-ascii character.
|
||||
fn ascii_check(c: char, chars_should_be_ascii: bool) -> Result<char, EscapeError> {
|
||||
if chars_should_be_ascii && !c.is_ascii() {
|
||||
Err(EscapeError::NonAsciiCharInByte)
|
||||
} else {
|
||||
Ok(c)
|
||||
}
|
||||
}
|
||||
|
||||
fn unescape_char_or_byte(chars: &mut Chars<'_>, is_byte: bool) -> Result<char, EscapeError> {
|
||||
fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> {
|
||||
let c = chars.next().ok_or(EscapeError::ZeroChars)?;
|
||||
let res = match c {
|
||||
'\\' => scan_escape(chars, if is_byte { Mode::Byte } else { Mode::Char }),
|
||||
'\\' => scan_escape(chars, mode),
|
||||
'\n' | '\t' | '\'' => Err(EscapeError::EscapeOnlyChar),
|
||||
'\r' => Err(EscapeError::BareCarriageReturn),
|
||||
_ => ascii_check(c, is_byte),
|
||||
_ => ascii_check(c, mode.chars_should_be_ascii()),
|
||||
}?;
|
||||
if chars.next().is_some() {
|
||||
return Err(EscapeError::MoreThanOneChar);
|
||||
|
@ -324,6 +329,7 @@ where
|
|||
F: FnMut(Range<usize>, Result<T, EscapeError>),
|
||||
{
|
||||
let mut chars = src.chars();
|
||||
let chars_should_be_ascii = mode.chars_should_be_ascii(); // get this outside the loop
|
||||
|
||||
// The `start` and `end` computation here is complicated because
|
||||
// `skip_ascii_whitespace` makes us to skip over chars without counting
|
||||
|
@ -346,14 +352,12 @@ where
|
|||
_ => scan_escape::<T>(&mut chars, mode),
|
||||
}
|
||||
}
|
||||
'\n' => Ok(b'\n'.into()),
|
||||
'\t' => Ok(b'\t'.into()),
|
||||
'"' => Err(EscapeError::EscapeOnlyChar),
|
||||
'\r' => Err(EscapeError::BareCarriageReturn),
|
||||
_ => ascii_check(c, mode.characters_should_be_ascii()).map(Into::into),
|
||||
_ => ascii_check(c, chars_should_be_ascii).map(Into::into),
|
||||
};
|
||||
let end = src.len() - chars.as_str().len();
|
||||
callback(start..end, res.map(Into::into));
|
||||
callback(start..end, res);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -387,20 +391,21 @@ where
|
|||
/// sequence of characters or errors.
|
||||
/// NOTE: Raw strings do not perform any explicit character escaping, here we
|
||||
/// only produce errors on bare CR.
|
||||
fn unescape_raw_str_or_raw_byte_str<F>(src: &str, is_byte: bool, callback: &mut F)
|
||||
fn unescape_raw_str_or_raw_byte_str<F>(src: &str, mode: Mode, callback: &mut F)
|
||||
where
|
||||
F: FnMut(Range<usize>, Result<char, EscapeError>),
|
||||
{
|
||||
let mut chars = src.chars();
|
||||
let chars_should_be_ascii = mode.chars_should_be_ascii(); // get this outside the loop
|
||||
|
||||
// The `start` and `end` computation here matches the one in
|
||||
// `unescape_str_or_byte_str` for consistency, even though this function
|
||||
// `unescape_str_common` for consistency, even though this function
|
||||
// doesn't have to worry about skipping any chars.
|
||||
while let Some(c) = chars.next() {
|
||||
let start = src.len() - chars.as_str().len() - c.len_utf8();
|
||||
let res = match c {
|
||||
'\r' => Err(EscapeError::BareCarriageReturnInRawString),
|
||||
_ => ascii_check(c, is_byte),
|
||||
_ => ascii_check(c, chars_should_be_ascii),
|
||||
};
|
||||
let end = src.len() - chars.as_str().len();
|
||||
callback(start..end, res);
|
||||
|
@ -410,7 +415,7 @@ where
|
|||
#[inline]
|
||||
pub fn byte_from_char(c: char) -> u8 {
|
||||
let res = c as u32;
|
||||
debug_assert!(res <= u8::MAX as u32, "guaranteed because of Mode::ByteStr");
|
||||
debug_assert!(res <= u8::MAX as u32, "guaranteed because of ByteStr");
|
||||
res as u8
|
||||
}
|
||||
|
||||
|
|
|
@ -196,7 +196,7 @@ impl Direction for Backward {
|
|||
{
|
||||
results.reset_to_block_entry(state, block);
|
||||
|
||||
vis.visit_block_end(results, state, block_data, block);
|
||||
vis.visit_block_end(state);
|
||||
|
||||
// Terminator
|
||||
let loc = Location { block, statement_index: block_data.statements.len() };
|
||||
|
@ -214,7 +214,7 @@ impl Direction for Backward {
|
|||
vis.visit_statement_after_primary_effect(results, state, stmt, loc);
|
||||
}
|
||||
|
||||
vis.visit_block_start(results, state, block_data, block);
|
||||
vis.visit_block_start(state);
|
||||
}
|
||||
|
||||
fn join_state_into_successors_of<'tcx, A>(
|
||||
|
@ -449,7 +449,7 @@ impl Direction for Forward {
|
|||
{
|
||||
results.reset_to_block_entry(state, block);
|
||||
|
||||
vis.visit_block_start(results, state, block_data, block);
|
||||
vis.visit_block_start(state);
|
||||
|
||||
for (statement_index, stmt) in block_data.statements.iter().enumerate() {
|
||||
let loc = Location { block, statement_index };
|
||||
|
@ -466,7 +466,7 @@ impl Direction for Forward {
|
|||
results.reconstruct_terminator_effect(state, term, loc);
|
||||
vis.visit_terminator_after_primary_effect(results, state, term, loc);
|
||||
|
||||
vis.visit_block_end(results, state, block_data, block);
|
||||
vis.visit_block_end(state);
|
||||
}
|
||||
|
||||
fn join_state_into_successors_of<'tcx, A>(
|
||||
|
|
|
@ -545,25 +545,13 @@ where
|
|||
{
|
||||
type FlowState = A::Domain;
|
||||
|
||||
fn visit_block_start(
|
||||
&mut self,
|
||||
_results: &mut Results<'tcx, A>,
|
||||
state: &Self::FlowState,
|
||||
_block_data: &mir::BasicBlockData<'tcx>,
|
||||
_block: BasicBlock,
|
||||
) {
|
||||
fn visit_block_start(&mut self, state: &Self::FlowState) {
|
||||
if A::Direction::IS_FORWARD {
|
||||
self.prev_state.clone_from(state);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_block_end(
|
||||
&mut self,
|
||||
_results: &mut Results<'tcx, A>,
|
||||
state: &Self::FlowState,
|
||||
_block_data: &mir::BasicBlockData<'tcx>,
|
||||
_block: BasicBlock,
|
||||
) {
|
||||
fn visit_block_end(&mut self, state: &Self::FlowState) {
|
||||
if A::Direction::IS_BACKWARD {
|
||||
self.prev_state.clone_from(state);
|
||||
}
|
||||
|
|
|
@ -248,18 +248,19 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
|
|||
|
||||
/// A gen/kill dataflow problem.
|
||||
///
|
||||
/// Each method in this trait has a corresponding one in `Analysis`. However, these methods only
|
||||
/// allow modification of the dataflow state via "gen" and "kill" operations. By defining transfer
|
||||
/// functions for each statement in this way, the transfer function for an entire basic block can
|
||||
/// be computed efficiently.
|
||||
/// Each method in this trait has a corresponding one in `Analysis`. However, the first two methods
|
||||
/// here only allow modification of the dataflow state via "gen" and "kill" operations. By defining
|
||||
/// transfer functions for each statement in this way, the transfer function for an entire basic
|
||||
/// block can be computed efficiently. The remaining methods match up with `Analysis` exactly.
|
||||
///
|
||||
/// `Analysis` is automatically implemented for all implementers of `GenKillAnalysis`.
|
||||
/// `Analysis` is automatically implemented for all implementers of `GenKillAnalysis` via a blanket
|
||||
/// impl below.
|
||||
pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
|
||||
type Idx: Idx;
|
||||
|
||||
fn domain_size(&self, body: &mir::Body<'tcx>) -> usize;
|
||||
|
||||
/// See `Analysis::apply_statement_effect`.
|
||||
/// See `Analysis::apply_statement_effect`. Note how the second arg differs.
|
||||
fn statement_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
|
@ -267,7 +268,8 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
|
|||
location: Location,
|
||||
);
|
||||
|
||||
/// See `Analysis::apply_before_statement_effect`.
|
||||
/// See `Analysis::apply_before_statement_effect`. Note how the second arg
|
||||
/// differs.
|
||||
fn before_statement_effect(
|
||||
&mut self,
|
||||
_trans: &mut impl GenKill<Self::Idx>,
|
||||
|
@ -287,7 +289,7 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
|
|||
/// See `Analysis::apply_before_terminator_effect`.
|
||||
fn before_terminator_effect(
|
||||
&mut self,
|
||||
_trans: &mut impl GenKill<Self::Idx>,
|
||||
_trans: &mut Self::Domain,
|
||||
_terminator: &mir::Terminator<'tcx>,
|
||||
_location: Location,
|
||||
) {
|
||||
|
@ -298,7 +300,7 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
|
|||
/// See `Analysis::apply_call_return_effect`.
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
trans: &mut Self::Domain,
|
||||
block: BasicBlock,
|
||||
return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
);
|
||||
|
@ -313,6 +315,7 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
// Blanket impl: any impl of `GenKillAnalysis` automatically impls `Analysis`.
|
||||
impl<'tcx, A> Analysis<'tcx> for A
|
||||
where
|
||||
A: GenKillAnalysis<'tcx>,
|
||||
|
|
|
@ -31,14 +31,7 @@ pub fn visit_results<'mir, 'tcx, F, R>(
|
|||
pub trait ResultsVisitor<'mir, 'tcx, R> {
|
||||
type FlowState;
|
||||
|
||||
fn visit_block_start(
|
||||
&mut self,
|
||||
_results: &mut R,
|
||||
_state: &Self::FlowState,
|
||||
_block_data: &'mir mir::BasicBlockData<'tcx>,
|
||||
_block: BasicBlock,
|
||||
) {
|
||||
}
|
||||
fn visit_block_start(&mut self, _state: &Self::FlowState) {}
|
||||
|
||||
/// Called with the `before_statement_effect` of the given statement applied to `state` but not
|
||||
/// its `statement_effect`.
|
||||
|
@ -86,20 +79,13 @@ pub trait ResultsVisitor<'mir, 'tcx, R> {
|
|||
) {
|
||||
}
|
||||
|
||||
fn visit_block_end(
|
||||
&mut self,
|
||||
_results: &mut R,
|
||||
_state: &Self::FlowState,
|
||||
_block_data: &'mir mir::BasicBlockData<'tcx>,
|
||||
_block: BasicBlock,
|
||||
) {
|
||||
}
|
||||
fn visit_block_end(&mut self, _state: &Self::FlowState) {}
|
||||
}
|
||||
|
||||
/// Things that can be visited by a `ResultsVisitor`.
|
||||
///
|
||||
/// This trait exists so that we can visit the results of multiple dataflow analyses simultaneously.
|
||||
/// DO NOT IMPLEMENT MANUALLY. Instead, use the `impl_visitable` macro below.
|
||||
/// This trait exists so that we can visit the results of one or more dataflow analyses
|
||||
/// simultaneously.
|
||||
pub trait ResultsVisitable<'tcx> {
|
||||
type Direction: Direction;
|
||||
type FlowState;
|
||||
|
|
|
@ -62,7 +62,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeBorrowedLocals {
|
|||
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
_trans: &mut impl GenKill<Self::Idx>,
|
||||
_trans: &mut Self::Domain,
|
||||
_block: BasicBlock,
|
||||
_return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
|
|
|
@ -376,7 +376,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
|
|||
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
trans: &mut Self::Domain,
|
||||
_block: mir::BasicBlock,
|
||||
return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
|
@ -499,7 +499,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
|
|||
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
trans: &mut Self::Domain,
|
||||
_block: mir::BasicBlock,
|
||||
return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
|
@ -617,7 +617,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> {
|
|||
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
trans: &mut Self::Domain,
|
||||
_block: mir::BasicBlock,
|
||||
return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
|
@ -712,7 +712,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
|
|||
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
trans: &mut Self::Domain,
|
||||
block: mir::BasicBlock,
|
||||
_return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
|
|
|
@ -69,7 +69,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeLiveLocals {
|
|||
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
trans: &mut Self::Domain,
|
||||
_block: mir::BasicBlock,
|
||||
return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
|
|
|
@ -72,7 +72,7 @@ impl<'tcx, 'a> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> {
|
|||
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
_trans: &mut impl GenKill<Self::Idx>,
|
||||
_trans: &mut Self::Domain,
|
||||
_block: BasicBlock,
|
||||
_return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
|
@ -144,7 +144,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageDead {
|
|||
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
_trans: &mut impl GenKill<Self::Idx>,
|
||||
_trans: &mut Self::Domain,
|
||||
_block: BasicBlock,
|
||||
_return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
|
@ -238,7 +238,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
|
|||
|
||||
fn before_terminator_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
trans: &mut Self::Domain,
|
||||
terminator: &Terminator<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
|
@ -334,7 +334,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
|
|||
|
||||
fn call_return_effect(
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
trans: &mut Self::Domain,
|
||||
_block: BasicBlock,
|
||||
return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
|
|
|
@ -1422,6 +1422,9 @@ impl CheckCfg {
|
|||
};
|
||||
|
||||
// NOTE: This should be kept in sync with `default_configuration`
|
||||
//
|
||||
// When adding a new config here you should also update
|
||||
// `tests/ui/check-cfg/well-known-values.rs`.
|
||||
|
||||
let panic_values = &PanicStrategy::all();
|
||||
|
||||
|
|
|
@ -1516,6 +1516,8 @@ symbols! {
|
|||
simd_insert,
|
||||
simd_le,
|
||||
simd_lt,
|
||||
simd_masked_load,
|
||||
simd_masked_store,
|
||||
simd_mul,
|
||||
simd_ne,
|
||||
simd_neg,
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// compile-flags: -C no-prepopulate-passes
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
#![feature(repr_simd, platform_intrinsics)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub struct Vec2<T>(pub T, pub T);
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub struct Vec4<T>(pub T, pub T, pub T, pub T);
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
fn simd_masked_load<M, P, T>(mask: M, pointer: P, values: T) -> T;
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @load_f32x2
|
||||
#[no_mangle]
|
||||
pub unsafe fn load_f32x2(mask: Vec2<i32>, pointer: *const f32,
|
||||
values: Vec2<f32>) -> Vec2<f32> {
|
||||
// CHECK: call <2 x float> @llvm.masked.load.v2f32.p0(ptr {{.*}}, i32 {{.*}}, <2 x i1> {{.*}}, <2 x float> {{.*}})
|
||||
simd_masked_load(mask, pointer, values)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @load_pf32x4
|
||||
#[no_mangle]
|
||||
pub unsafe fn load_pf32x4(mask: Vec4<i32>, pointer: *const *const f32,
|
||||
values: Vec4<*const f32>) -> Vec4<*const f32> {
|
||||
// CHECK: call <4 x ptr> @llvm.masked.load.v4p0.p0(ptr {{.*}}, i32 {{.*}}, <4 x i1> {{.*}}, <4 x ptr> {{.*}})
|
||||
simd_masked_load(mask, pointer, values)
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
// compile-flags: -C no-prepopulate-passes
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
#![feature(repr_simd, platform_intrinsics)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub struct Vec2<T>(pub T, pub T);
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub struct Vec4<T>(pub T, pub T, pub T, pub T);
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
fn simd_masked_store<M, P, T>(mask: M, pointer: P, values: T) -> ();
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @store_f32x2
|
||||
#[no_mangle]
|
||||
pub unsafe fn store_f32x2(mask: Vec2<i32>, pointer: *mut f32, values: Vec2<f32>) {
|
||||
// CHECK: call void @llvm.masked.store.v2f32.p0(<2 x float> {{.*}}, ptr {{.*}}, i32 {{.*}}, <2 x i1> {{.*}})
|
||||
simd_masked_store(mask, pointer, values)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @store_pf32x4
|
||||
#[no_mangle]
|
||||
pub unsafe fn store_pf32x4(mask: Vec4<i32>, pointer: *mut *const f32, values: Vec4<*const f32>) {
|
||||
// CHECK: call void @llvm.masked.store.v4p0.p0(<4 x ptr> {{.*}}, ptr {{.*}}, i32 {{.*}}, <4 x i1> {{.*}})
|
||||
simd_masked_store(mask, pointer, values)
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
#[cfg(target(os = "linux", arch = "arm"))]
|
||||
pub fn expected() {}
|
||||
|
||||
#[cfg(target(os = "linux", arch = "X"))]
|
||||
#[cfg(target(os = "linux", pointer_width = "X"))]
|
||||
//~^ WARNING unexpected `cfg` condition value
|
||||
pub fn unexpected() {}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
warning: unexpected `cfg` condition value: `X`
|
||||
--> $DIR/compact-values.rs:11:28
|
||||
|
|
||||
LL | #[cfg(target(os = "linux", arch = "X"))]
|
||||
| ^^^^^^^^^^
|
||||
LL | #[cfg(target(os = "linux", pointer_width = "X"))]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `target_arch` are: `aarch64`, `arm`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64`
|
||||
= note: expected values for `target_pointer_width` are: `16`, `32`, `64`
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
|
||||
#[cfg(target_os = "linuz")]
|
||||
//~^ WARNING unexpected `cfg` condition value
|
||||
fn target_os_linux_misspell() {}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn target_os_linux() {}
|
||||
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
warning: unexpected `cfg` condition value: `linuz`
|
||||
--> $DIR/values-target-json.rs:13:7
|
||||
|
|
||||
LL | #[cfg(target_os = "linuz")]
|
||||
| ^^^^^^^^^^^^-------
|
||||
| |
|
||||
| help: there is a expected value with a similar name: `"linux"`
|
||||
|
|
||||
= note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `ericos`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
|
@ -1,41 +1,104 @@
|
|||
// This test check that we lint on non well known values and that we don't lint on well known
|
||||
// values
|
||||
// This test check that we recognize all the well known config names
|
||||
// and that we correctly lint on unexpected values.
|
||||
//
|
||||
// This test also serve as an "anti-regression" for the well known
|
||||
// values since the suggestion shows them.
|
||||
//
|
||||
// check-pass
|
||||
// compile-flags: --check-cfg=cfg() -Z unstable-options
|
||||
|
||||
#[cfg(target_os = "linuz")]
|
||||
#![feature(cfg_overflow_checks)]
|
||||
#![feature(cfg_relocation_model)]
|
||||
#![feature(cfg_sanitize)]
|
||||
#![feature(cfg_target_abi)]
|
||||
#![feature(cfg_target_has_atomic)]
|
||||
#![feature(cfg_target_has_atomic_equal_alignment)]
|
||||
#![feature(cfg_target_thread_local)]
|
||||
|
||||
// This part makes sure that none of the well known names are
|
||||
// unexpected.
|
||||
//
|
||||
// BUT to make sure that no expected values changes without
|
||||
// being noticed we pass them a obviously wrong value so the
|
||||
// diagnostic prints the list of expected values.
|
||||
#[cfg(any(
|
||||
// tidy-alphabetical-start
|
||||
debug_assertions = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
doc = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
doctest = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
miri = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
overflow_checks = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
panic = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
proc_macro = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
relocation_model = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
sanitize = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
target_abi = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
target_arch = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
target_endian = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
target_env = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
target_family = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
target_feature = "_UNEXPECTED_VALUE", // currently *any* values are "expected"
|
||||
target_has_atomic = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
target_has_atomic_load_store = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
target_os = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
target_pointer_width = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
target_thread_local = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
target_vendor = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
test = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
unix = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
windows = "_UNEXPECTED_VALUE",
|
||||
//~^ WARN unexpected `cfg` condition value
|
||||
// tidy-alphabetical-end
|
||||
))]
|
||||
fn unexpected_values() {}
|
||||
|
||||
#[cfg(target_os = "linuz")] // testing that we suggest `linux`
|
||||
//~^ WARNING unexpected `cfg` condition value
|
||||
fn target_os_linux_misspell() {}
|
||||
|
||||
// The #[cfg]s below serve as a safeguard to make sure we
|
||||
// don't lint when using an expected well-known name and
|
||||
// value, only a small subset of all possible expected
|
||||
// configs are tested, since we already test the names
|
||||
// above and don't need to test all values, just different
|
||||
// combinations (without value, with value, both...).
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn target_os_linux() {}
|
||||
|
||||
#[cfg(target_has_atomic = "0")]
|
||||
//~^ WARNING unexpected `cfg` condition value
|
||||
fn target_has_atomic_invalid() {}
|
||||
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
fn target_has_atomic() {}
|
||||
fn target_has_atomic_8() {}
|
||||
|
||||
#[cfg(unix = "aa")]
|
||||
//~^ WARNING unexpected `cfg` condition value
|
||||
fn unix_with_value() {}
|
||||
#[cfg(target_has_atomic)]
|
||||
fn target_has_atomic() {}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn unix() {}
|
||||
|
||||
#[cfg(miri = "miri")]
|
||||
//~^ WARNING unexpected `cfg` condition value
|
||||
fn miri_with_value() {}
|
||||
|
||||
#[cfg(miri)]
|
||||
fn miri() {}
|
||||
|
||||
#[cfg(doc = "linux")]
|
||||
//~^ WARNING unexpected `cfg` condition value
|
||||
fn doc_with_value() {}
|
||||
|
||||
#[cfg(doc)]
|
||||
fn doc() {}
|
||||
|
||||
|
|
|
@ -1,53 +1,225 @@
|
|||
warning: unexpected `cfg` condition value: `linuz`
|
||||
--> $DIR/well-known-values.rs:7:7
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:26:5
|
||||
|
|
||||
LL | #[cfg(target_os = "linuz")]
|
||||
LL | debug_assertions = "_UNEXPECTED_VALUE",
|
||||
| ^^^^^^^^^^^^^^^^----------------------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `debug_assertions`
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:28:5
|
||||
|
|
||||
LL | doc = "_UNEXPECTED_VALUE",
|
||||
| ^^^----------------------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `doc`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:30:5
|
||||
|
|
||||
LL | doctest = "_UNEXPECTED_VALUE",
|
||||
| ^^^^^^^----------------------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `doctest`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:32:5
|
||||
|
|
||||
LL | miri = "_UNEXPECTED_VALUE",
|
||||
| ^^^^----------------------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `miri`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:34:5
|
||||
|
|
||||
LL | overflow_checks = "_UNEXPECTED_VALUE",
|
||||
| ^^^^^^^^^^^^^^^----------------------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `overflow_checks`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:36:5
|
||||
|
|
||||
LL | panic = "_UNEXPECTED_VALUE",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `panic` are: `abort`, `unwind`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:38:5
|
||||
|
|
||||
LL | proc_macro = "_UNEXPECTED_VALUE",
|
||||
| ^^^^^^^^^^----------------------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `proc_macro`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:40:5
|
||||
|
|
||||
LL | relocation_model = "_UNEXPECTED_VALUE",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `relocation_model` are: `dynamic-no-pic`, `pic`, `pie`, `ropi`, `ropi-rwpi`, `rwpi`, `static`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:42:5
|
||||
|
|
||||
LL | sanitize = "_UNEXPECTED_VALUE",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `sanitize` are: `address`, `cfi`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, `thread`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:44:5
|
||||
|
|
||||
LL | target_abi = "_UNEXPECTED_VALUE",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `target_abi` are: ``, `abi64`, `abiv2`, `abiv2hf`, `eabi`, `eabihf`, `elf`, `fortanix`, `ilp32`, `llvm`, `macabi`, `sim`, `softfloat`, `spe`, `uwp`, `vec-extabi`, `x32`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:46:5
|
||||
|
|
||||
LL | target_arch = "_UNEXPECTED_VALUE",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `target_arch` are: `aarch64`, `arm`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:48:5
|
||||
|
|
||||
LL | target_endian = "_UNEXPECTED_VALUE",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `target_endian` are: `big`, `little`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:50:5
|
||||
|
|
||||
LL | target_env = "_UNEXPECTED_VALUE",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `target_env` are: ``, `eabihf`, `gnu`, `gnueabihf`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `ohos`, `psx`, `relibc`, `sgx`, `uclibc`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:52:5
|
||||
|
|
||||
LL | target_family = "_UNEXPECTED_VALUE",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `target_family` are: `unix`, `wasm`, `windows`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:55:5
|
||||
|
|
||||
LL | target_has_atomic = "_UNEXPECTED_VALUE",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `target_has_atomic` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:57:5
|
||||
|
|
||||
LL | target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `target_has_atomic_equal_alignment` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:59:5
|
||||
|
|
||||
LL | target_has_atomic_load_store = "_UNEXPECTED_VALUE",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `target_has_atomic_load_store` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:61:5
|
||||
|
|
||||
LL | target_os = "_UNEXPECTED_VALUE",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:63:5
|
||||
|
|
||||
LL | target_pointer_width = "_UNEXPECTED_VALUE",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `target_pointer_width` are: `16`, `32`, `64`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:65:5
|
||||
|
|
||||
LL | target_thread_local = "_UNEXPECTED_VALUE",
|
||||
| ^^^^^^^^^^^^^^^^^^^----------------------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `target_thread_local`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:67:5
|
||||
|
|
||||
LL | target_vendor = "_UNEXPECTED_VALUE",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `target_vendor` are: `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `nintendo`, `nvidia`, `pc`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, `wrs`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:69:5
|
||||
|
|
||||
LL | test = "_UNEXPECTED_VALUE",
|
||||
| ^^^^----------------------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `test`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:71:5
|
||||
|
|
||||
LL | unix = "_UNEXPECTED_VALUE",
|
||||
| ^^^^----------------------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `unix`
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
--> $DIR/well-known-values.rs:73:5
|
||||
|
|
||||
LL | windows = "_UNEXPECTED_VALUE",
|
||||
| ^^^^^^^----------------------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `windows`
|
||||
|
||||
warning: unexpected `cfg` condition value: `linuz`
|
||||
--> $DIR/well-known-values.rs:79:7
|
||||
|
|
||||
LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux`
|
||||
| ^^^^^^^^^^^^-------
|
||||
| |
|
||||
| help: there is a expected value with a similar name: `"linux"`
|
||||
|
|
||||
= note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: unexpected `cfg` condition value: `0`
|
||||
--> $DIR/well-known-values.rs:14:7
|
||||
|
|
||||
LL | #[cfg(target_has_atomic = "0")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^---
|
||||
| |
|
||||
| help: there is a expected value with a similar name: `"8"`
|
||||
|
|
||||
= note: expected values for `target_has_atomic` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr`
|
||||
|
||||
warning: unexpected `cfg` condition value: `aa`
|
||||
--> $DIR/well-known-values.rs:21:7
|
||||
|
|
||||
LL | #[cfg(unix = "aa")]
|
||||
| ^^^^-------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `unix`
|
||||
|
||||
warning: unexpected `cfg` condition value: `miri`
|
||||
--> $DIR/well-known-values.rs:28:7
|
||||
|
|
||||
LL | #[cfg(miri = "miri")]
|
||||
| ^^^^---------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `miri`
|
||||
|
||||
warning: unexpected `cfg` condition value: `linux`
|
||||
--> $DIR/well-known-values.rs:35:7
|
||||
|
|
||||
LL | #[cfg(doc = "linux")]
|
||||
| ^^^----------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `doc`
|
||||
|
||||
warning: 5 warnings emitted
|
||||
warning: 25 warnings emitted
|
||||
|
||||
|
|
10
tests/ui/macros/issue-118048.rs
Normal file
10
tests/ui/macros/issue-118048.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
macro_rules! foo {
|
||||
($ty:ty) => {
|
||||
fn foo(_: $ty, _: $ty) {}
|
||||
}
|
||||
}
|
||||
|
||||
foo!(_);
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
|
||||
|
||||
fn main() {}
|
21
tests/ui/macros/issue-118048.stderr
Normal file
21
tests/ui/macros/issue-118048.stderr
Normal file
|
@ -0,0 +1,21 @@
|
|||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/issue-118048.rs:7:6
|
||||
|
|
||||
LL | foo!(_);
|
||||
| ^
|
||||
| |
|
||||
| not allowed in type signatures
|
||||
| not allowed in type signatures
|
||||
|
|
||||
help: use type parameters instead
|
||||
|
|
||||
LL ~ fn foo<T>(_: $ty, _: $ty) {}
|
||||
LL | }
|
||||
LL | }
|
||||
LL |
|
||||
LL ~ foo!(T);
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0121`.
|
Binary file not shown.
74
tests/ui/simd/masked-load-store-build-fail.rs
Normal file
74
tests/ui/simd/masked-load-store-build-fail.rs
Normal file
|
@ -0,0 +1,74 @@
|
|||
// build-fail
|
||||
#![feature(repr_simd, platform_intrinsics)]
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
fn simd_masked_load<M, P, T>(mask: M, pointer: P, values: T) -> T;
|
||||
fn simd_masked_store<M, P, T>(mask: M, pointer: P, values: T) -> ();
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(simd)]
|
||||
struct Simd<T, const N: usize>([T; N]);
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let mut arr = [4u8, 5, 6, 7];
|
||||
let default = Simd::<u8, 4>([9; 4]);
|
||||
|
||||
simd_masked_load(
|
||||
Simd::<i8, 8>([-1, 0, -1, -1, 0, 0, 0, 0]),
|
||||
arr.as_ptr(),
|
||||
default
|
||||
);
|
||||
//~^^^^^ ERROR expected third argument with length 8 (same as input type `Simd<i8, 8>`), found `Simd<u8, 4>` with length 4
|
||||
|
||||
simd_masked_load(
|
||||
Simd::<i8, 4>([-1, 0, -1, -1]),
|
||||
arr.as_ptr() as *const i8,
|
||||
default
|
||||
);
|
||||
//~^^^^^ ERROR expected element type `u8` of second argument `*const i8` to be a pointer to the element type `u8` of the first argument `Simd<u8, 4>`, found `u8` != `*_ u8`
|
||||
|
||||
simd_masked_load(
|
||||
Simd::<i8, 4>([-1, 0, -1, -1]),
|
||||
arr.as_ptr(),
|
||||
Simd::<u32, 4>([9; 4])
|
||||
);
|
||||
//~^^^^^ ERROR expected element type `u32` of second argument `*const u8` to be a pointer to the element type `u32` of the first argument `Simd<u32, 4>`, found `u32` != `*_ u32`
|
||||
|
||||
simd_masked_load(
|
||||
Simd::<u8, 4>([1, 0, 1, 1]),
|
||||
arr.as_ptr(),
|
||||
default
|
||||
);
|
||||
//~^^^^^ ERROR expected element type `u8` of third argument `Simd<u8, 4>` to be a signed integer type
|
||||
|
||||
simd_masked_store(
|
||||
Simd([-1i8; 4]),
|
||||
arr.as_ptr(),
|
||||
Simd([5u32; 4])
|
||||
);
|
||||
//~^^^^^ ERROR expected element type `u32` of second argument `*const u8` to be a pointer to the element type `u32` of the first argument `Simd<u32, 4>`, found `u32` != `*mut u32`
|
||||
|
||||
simd_masked_store(
|
||||
Simd([-1i8; 4]),
|
||||
arr.as_ptr(),
|
||||
Simd([5u8; 4])
|
||||
);
|
||||
//~^^^^^ ERROR expected element type `u8` of second argument `*const u8` to be a pointer to the element type `u8` of the first argument `Simd<u8, 4>`, found `u8` != `*mut u8`
|
||||
|
||||
simd_masked_store(
|
||||
Simd([-1i8; 4]),
|
||||
arr.as_mut_ptr(),
|
||||
Simd([5u8; 2])
|
||||
);
|
||||
//~^^^^^ ERROR expected third argument with length 4 (same as input type `Simd<i8, 4>`), found `Simd<u8, 2>` with length 2
|
||||
|
||||
simd_masked_store(
|
||||
Simd([1u32; 4]),
|
||||
arr.as_mut_ptr(),
|
||||
Simd([5u8; 4])
|
||||
);
|
||||
//~^^^^^ ERROR expected element type `u8` of third argument `Simd<u32, 4>` to be a signed integer type
|
||||
}
|
||||
}
|
83
tests/ui/simd/masked-load-store-build-fail.stderr
Normal file
83
tests/ui/simd/masked-load-store-build-fail.stderr
Normal file
|
@ -0,0 +1,83 @@
|
|||
error[E0511]: invalid monomorphization of `simd_masked_load` intrinsic: expected third argument with length 8 (same as input type `Simd<i8, 8>`), found `Simd<u8, 4>` with length 4
|
||||
--> $DIR/masked-load-store-build-fail.rs:18:9
|
||||
|
|
||||
LL | / simd_masked_load(
|
||||
LL | | Simd::<i8, 8>([-1, 0, -1, -1, 0, 0, 0, 0]),
|
||||
LL | | arr.as_ptr(),
|
||||
LL | | default
|
||||
LL | | );
|
||||
| |_________^
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_masked_load` intrinsic: expected element type `u8` of second argument `*const i8` to be a pointer to the element type `u8` of the first argument `Simd<u8, 4>`, found `u8` != `*_ u8`
|
||||
--> $DIR/masked-load-store-build-fail.rs:25:9
|
||||
|
|
||||
LL | / simd_masked_load(
|
||||
LL | | Simd::<i8, 4>([-1, 0, -1, -1]),
|
||||
LL | | arr.as_ptr() as *const i8,
|
||||
LL | | default
|
||||
LL | | );
|
||||
| |_________^
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_masked_load` intrinsic: expected element type `u32` of second argument `*const u8` to be a pointer to the element type `u32` of the first argument `Simd<u32, 4>`, found `u32` != `*_ u32`
|
||||
--> $DIR/masked-load-store-build-fail.rs:32:9
|
||||
|
|
||||
LL | / simd_masked_load(
|
||||
LL | | Simd::<i8, 4>([-1, 0, -1, -1]),
|
||||
LL | | arr.as_ptr(),
|
||||
LL | | Simd::<u32, 4>([9; 4])
|
||||
LL | | );
|
||||
| |_________^
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_masked_load` intrinsic: expected element type `u8` of third argument `Simd<u8, 4>` to be a signed integer type
|
||||
--> $DIR/masked-load-store-build-fail.rs:39:9
|
||||
|
|
||||
LL | / simd_masked_load(
|
||||
LL | | Simd::<u8, 4>([1, 0, 1, 1]),
|
||||
LL | | arr.as_ptr(),
|
||||
LL | | default
|
||||
LL | | );
|
||||
| |_________^
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_masked_store` intrinsic: expected element type `u32` of second argument `*const u8` to be a pointer to the element type `u32` of the first argument `Simd<u32, 4>`, found `u32` != `*mut u32`
|
||||
--> $DIR/masked-load-store-build-fail.rs:46:9
|
||||
|
|
||||
LL | / simd_masked_store(
|
||||
LL | | Simd([-1i8; 4]),
|
||||
LL | | arr.as_ptr(),
|
||||
LL | | Simd([5u32; 4])
|
||||
LL | | );
|
||||
| |_________^
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_masked_store` intrinsic: expected element type `u8` of second argument `*const u8` to be a pointer to the element type `u8` of the first argument `Simd<u8, 4>`, found `u8` != `*mut u8`
|
||||
--> $DIR/masked-load-store-build-fail.rs:53:9
|
||||
|
|
||||
LL | / simd_masked_store(
|
||||
LL | | Simd([-1i8; 4]),
|
||||
LL | | arr.as_ptr(),
|
||||
LL | | Simd([5u8; 4])
|
||||
LL | | );
|
||||
| |_________^
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_masked_store` intrinsic: expected third argument with length 4 (same as input type `Simd<i8, 4>`), found `Simd<u8, 2>` with length 2
|
||||
--> $DIR/masked-load-store-build-fail.rs:60:9
|
||||
|
|
||||
LL | / simd_masked_store(
|
||||
LL | | Simd([-1i8; 4]),
|
||||
LL | | arr.as_mut_ptr(),
|
||||
LL | | Simd([5u8; 2])
|
||||
LL | | );
|
||||
| |_________^
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_masked_store` intrinsic: expected element type `u8` of third argument `Simd<u32, 4>` to be a signed integer type
|
||||
--> $DIR/masked-load-store-build-fail.rs:67:9
|
||||
|
|
||||
LL | / simd_masked_store(
|
||||
LL | | Simd([1u32; 4]),
|
||||
LL | | arr.as_mut_ptr(),
|
||||
LL | | Simd([5u8; 4])
|
||||
LL | | );
|
||||
| |_________^
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0511`.
|
32
tests/ui/simd/masked-load-store-check-fail.rs
Normal file
32
tests/ui/simd/masked-load-store-check-fail.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
// check-fail
|
||||
#![feature(repr_simd, platform_intrinsics)]
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
fn simd_masked_load<M, P, T>(mask: M, pointer: P, values: T) -> T;
|
||||
fn simd_masked_store<M, P, T>(mask: M, pointer: P, values: T) -> ();
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(simd)]
|
||||
struct Simd<T, const N: usize>([T; N]);
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let mut arr = [4u8, 5, 6, 7];
|
||||
let default = Simd::<u8, 4>([9; 4]);
|
||||
|
||||
let _x: Simd<u8, 2> = simd_masked_load(
|
||||
Simd::<i8, 4>([-1, 0, -1, -1]),
|
||||
arr.as_ptr(),
|
||||
Simd::<u8, 4>([9; 4])
|
||||
);
|
||||
//~^^ ERROR mismatched types
|
||||
|
||||
let _x: Simd<u32, 4> = simd_masked_load(
|
||||
Simd::<u8, 4>([1, 0, 1, 1]),
|
||||
arr.as_ptr(),
|
||||
default
|
||||
);
|
||||
//~^^ ERROR mismatched types
|
||||
}
|
||||
}
|
59
tests/ui/simd/masked-load-store-check-fail.stderr
Normal file
59
tests/ui/simd/masked-load-store-check-fail.stderr
Normal file
|
@ -0,0 +1,59 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/masked-load-store-check-fail.rs:21:13
|
||||
|
|
||||
LL | let _x: Simd<u8, 2> = simd_masked_load(
|
||||
| ---------------- arguments to this function are incorrect
|
||||
...
|
||||
LL | Simd::<u8, 4>([9; 4])
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ expected `2`, found `4`
|
||||
|
|
||||
= note: expected struct `Simd<_, 2>`
|
||||
found struct `Simd<_, 4>`
|
||||
help: the return type of this call is `Simd<u8, 4>` due to the type of the argument passed
|
||||
--> $DIR/masked-load-store-check-fail.rs:18:31
|
||||
|
|
||||
LL | let _x: Simd<u8, 2> = simd_masked_load(
|
||||
| _______________________________^
|
||||
LL | | Simd::<i8, 4>([-1, 0, -1, -1]),
|
||||
LL | | arr.as_ptr(),
|
||||
LL | | Simd::<u8, 4>([9; 4])
|
||||
| | --------------------- this argument influences the return type of `simd_masked_load`
|
||||
LL | | );
|
||||
| |_________^
|
||||
note: function defined here
|
||||
--> $DIR/masked-load-store-check-fail.rs:5:8
|
||||
|
|
||||
LL | fn simd_masked_load<M, P, T>(mask: M, pointer: P, values: T) -> T;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/masked-load-store-check-fail.rs:28:13
|
||||
|
|
||||
LL | let _x: Simd<u32, 4> = simd_masked_load(
|
||||
| ---------------- arguments to this function are incorrect
|
||||
...
|
||||
LL | default
|
||||
| ^^^^^^^ expected `Simd<u32, 4>`, found `Simd<u8, 4>`
|
||||
|
|
||||
= note: expected struct `Simd<u32, _>`
|
||||
found struct `Simd<u8, _>`
|
||||
help: the return type of this call is `Simd<u8, 4>` due to the type of the argument passed
|
||||
--> $DIR/masked-load-store-check-fail.rs:25:32
|
||||
|
|
||||
LL | let _x: Simd<u32, 4> = simd_masked_load(
|
||||
| ________________________________^
|
||||
LL | | Simd::<u8, 4>([1, 0, 1, 1]),
|
||||
LL | | arr.as_ptr(),
|
||||
LL | | default
|
||||
| | ------- this argument influences the return type of `simd_masked_load`
|
||||
LL | | );
|
||||
| |_________^
|
||||
note: function defined here
|
||||
--> $DIR/masked-load-store-check-fail.rs:5:8
|
||||
|
|
||||
LL | fn simd_masked_load<M, P, T>(mask: M, pointer: P, values: T) -> T;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
33
tests/ui/simd/masked-load-store.rs
Normal file
33
tests/ui/simd/masked-load-store.rs
Normal file
|
@ -0,0 +1,33 @@
|
|||
// run-pass
|
||||
#![feature(repr_simd, platform_intrinsics)]
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
fn simd_masked_load<M, P, T>(mask: M, pointer: P, values: T) -> T;
|
||||
fn simd_masked_store<M, P, T>(mask: M, pointer: P, values: T) -> ();
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(simd)]
|
||||
struct Simd<T, const N: usize>([T; N]);
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let a = Simd::<u8, 4>([0, 1, 2, 3]);
|
||||
let b_src = [4u8, 5, 6, 7];
|
||||
let b_default = Simd::<u8, 4>([9; 4]);
|
||||
let b: Simd::<u8, 4> = simd_masked_load(
|
||||
Simd::<i8, 4>([-1, 0, -1, -1]),
|
||||
b_src.as_ptr(),
|
||||
b_default
|
||||
);
|
||||
|
||||
assert_eq!(&b.0, &[4, 9, 6, 7]);
|
||||
|
||||
let mut output = [u8::MAX; 5];
|
||||
|
||||
simd_masked_store(Simd::<i8, 4>([-1, -1, -1, 0]), output.as_mut_ptr(), a);
|
||||
assert_eq!(&output, &[0, 1, 2, u8::MAX, u8::MAX]);
|
||||
simd_masked_store(Simd::<i8, 4>([0, -1, -1, 0]), output[1..].as_mut_ptr(), b);
|
||||
assert_eq!(&output, &[0, 1, 9, 6, u8::MAX]);
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue