Auto merge of #121914 - Nadrieril:rollup-ol98ncg, r=Nadrieril

Rollup of 5 pull requests

Successful merges:

 - #120761 (Add initial support for DataFlowSanitizer)
 - #121622 (Preserve same vtable pointer when cloning raw waker, to fix Waker::will_wake)
 - #121716 (match lowering: Lower bindings in a predictable order)
 - #121731 (Now that inlining, mir validation and const eval all use reveal-all, we won't be constraining hidden types here anymore)
 - #121841 (`f16` and `f128` step 2: intrinsics)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-03-02 22:59:19 +00:00
commit 0decdac390
52 changed files with 1156 additions and 144 deletions

View file

@ -1920,22 +1920,28 @@ pub struct FnSig {
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[derive(Encodable, Decodable, HashStable_Generic)]
pub enum FloatTy {
F16,
F32,
F64,
F128,
}
impl FloatTy {
pub fn name_str(self) -> &'static str {
match self {
FloatTy::F16 => "f16",
FloatTy::F32 => "f32",
FloatTy::F64 => "f64",
FloatTy::F128 => "f128",
}
}
pub fn name(self) -> Symbol {
match self {
FloatTy::F16 => sym::f16,
FloatTy::F32 => sym::f32,
FloatTy::F64 => sym::f64,
FloatTy::F128 => sym::f128,
}
}
}

View file

@ -519,12 +519,22 @@ pub(crate) unsafe fn llvm_optimize(
let pgo_sample_use_path = get_pgo_sample_use_path(config);
let is_lto = opt_stage == llvm::OptStage::ThinLTO || opt_stage == llvm::OptStage::FatLTO;
let instr_profile_output_path = get_instr_profile_output_path(config);
let sanitize_dataflow_abilist: Vec<_> = config
.sanitizer_dataflow_abilist
.iter()
.map(|file| CString::new(file.as_str()).unwrap())
.collect();
let sanitize_dataflow_abilist_ptrs: Vec<_> =
sanitize_dataflow_abilist.iter().map(|file| file.as_ptr()).collect();
// Sanitizer instrumentation is only inserted during the pre-link optimization stage.
let sanitizer_options = if !is_lto {
Some(llvm::SanitizerOptions {
sanitize_address: config.sanitizer.contains(SanitizerSet::ADDRESS),
sanitize_address_recover: config.sanitizer_recover.contains(SanitizerSet::ADDRESS),
sanitize_cfi: config.sanitizer.contains(SanitizerSet::CFI),
sanitize_dataflow: config.sanitizer.contains(SanitizerSet::DATAFLOW),
sanitize_dataflow_abilist: sanitize_dataflow_abilist_ptrs.as_ptr(),
sanitize_dataflow_abilist_len: sanitize_dataflow_abilist_ptrs.len(),
sanitize_kcfi: config.sanitizer.contains(SanitizerSet::KCFI),
sanitize_memory: config.sanitizer.contains(SanitizerSet::MEMORY),
sanitize_memory_recover: config.sanitizer_recover.contains(SanitizerSet::MEMORY),

View file

@ -685,8 +685,10 @@ impl<'ll> CodegenCx<'ll, '_> {
let t_i64 = self.type_i64();
let t_i128 = self.type_i128();
let t_isize = self.type_isize();
let t_f16 = self.type_f16();
let t_f32 = self.type_f32();
let t_f64 = self.type_f64();
let t_f128 = self.type_f128();
let t_metadata = self.type_metadata();
let t_token = self.type_token();
@ -728,69 +730,115 @@ impl<'ll> CodegenCx<'ll, '_> {
ifn!("llvm.debugtrap", fn() -> void);
ifn!("llvm.frameaddress", fn(t_i32) -> ptr);
ifn!("llvm.powi.f16", fn(t_f16, t_i32) -> t_f16);
ifn!("llvm.powi.f32", fn(t_f32, t_i32) -> t_f32);
ifn!("llvm.powi.f64", fn(t_f64, t_i32) -> t_f64);
ifn!("llvm.powi.f128", fn(t_f128, t_i32) -> t_f128);
ifn!("llvm.pow.f16", fn(t_f16, t_f16) -> t_f16);
ifn!("llvm.pow.f32", fn(t_f32, t_f32) -> t_f32);
ifn!("llvm.pow.f64", fn(t_f64, t_f64) -> t_f64);
ifn!("llvm.pow.f128", fn(t_f128, t_f128) -> t_f128);
ifn!("llvm.sqrt.f16", fn(t_f16) -> t_f16);
ifn!("llvm.sqrt.f32", fn(t_f32) -> t_f32);
ifn!("llvm.sqrt.f64", fn(t_f64) -> t_f64);
ifn!("llvm.sqrt.f128", fn(t_f128) -> t_f128);
ifn!("llvm.sin.f16", fn(t_f16) -> t_f16);
ifn!("llvm.sin.f32", fn(t_f32) -> t_f32);
ifn!("llvm.sin.f64", fn(t_f64) -> t_f64);
ifn!("llvm.sin.f128", fn(t_f128) -> t_f128);
ifn!("llvm.cos.f16", fn(t_f16) -> t_f16);
ifn!("llvm.cos.f32", fn(t_f32) -> t_f32);
ifn!("llvm.cos.f64", fn(t_f64) -> t_f64);
ifn!("llvm.cos.f128", fn(t_f128) -> t_f128);
ifn!("llvm.exp.f16", fn(t_f16) -> t_f16);
ifn!("llvm.exp.f32", fn(t_f32) -> t_f32);
ifn!("llvm.exp.f64", fn(t_f64) -> t_f64);
ifn!("llvm.exp.f128", fn(t_f128) -> t_f128);
ifn!("llvm.exp2.f16", fn(t_f16) -> t_f16);
ifn!("llvm.exp2.f32", fn(t_f32) -> t_f32);
ifn!("llvm.exp2.f64", fn(t_f64) -> t_f64);
ifn!("llvm.exp2.f128", fn(t_f128) -> t_f128);
ifn!("llvm.log.f16", fn(t_f16) -> t_f16);
ifn!("llvm.log.f32", fn(t_f32) -> t_f32);
ifn!("llvm.log.f64", fn(t_f64) -> t_f64);
ifn!("llvm.log.f128", fn(t_f128) -> t_f128);
ifn!("llvm.log10.f16", fn(t_f16) -> t_f16);
ifn!("llvm.log10.f32", fn(t_f32) -> t_f32);
ifn!("llvm.log10.f64", fn(t_f64) -> t_f64);
ifn!("llvm.log10.f128", fn(t_f128) -> t_f128);
ifn!("llvm.log2.f16", fn(t_f16) -> t_f16);
ifn!("llvm.log2.f32", fn(t_f32) -> t_f32);
ifn!("llvm.log2.f64", fn(t_f64) -> t_f64);
ifn!("llvm.log2.f128", fn(t_f128) -> t_f128);
ifn!("llvm.fma.f16", fn(t_f16, t_f16, t_f16) -> t_f16);
ifn!("llvm.fma.f32", fn(t_f32, t_f32, t_f32) -> t_f32);
ifn!("llvm.fma.f64", fn(t_f64, t_f64, t_f64) -> t_f64);
ifn!("llvm.fma.f128", fn(t_f128, t_f128, t_f128) -> t_f128);
ifn!("llvm.fabs.f16", fn(t_f16) -> t_f16);
ifn!("llvm.fabs.f32", fn(t_f32) -> t_f32);
ifn!("llvm.fabs.f64", fn(t_f64) -> t_f64);
ifn!("llvm.fabs.f128", fn(t_f128) -> t_f128);
ifn!("llvm.minnum.f16", fn(t_f16, t_f16) -> t_f16);
ifn!("llvm.minnum.f32", fn(t_f32, t_f32) -> t_f32);
ifn!("llvm.minnum.f64", fn(t_f64, t_f64) -> t_f64);
ifn!("llvm.minnum.f128", fn(t_f128, t_f128) -> t_f128);
ifn!("llvm.maxnum.f16", fn(t_f16, t_f16) -> t_f16);
ifn!("llvm.maxnum.f32", fn(t_f32, t_f32) -> t_f32);
ifn!("llvm.maxnum.f64", fn(t_f64, t_f64) -> t_f64);
ifn!("llvm.maxnum.f128", fn(t_f128, t_f128) -> t_f128);
ifn!("llvm.floor.f16", fn(t_f16) -> t_f16);
ifn!("llvm.floor.f32", fn(t_f32) -> t_f32);
ifn!("llvm.floor.f64", fn(t_f64) -> t_f64);
ifn!("llvm.floor.f128", fn(t_f128) -> t_f128);
ifn!("llvm.ceil.f16", fn(t_f16) -> t_f16);
ifn!("llvm.ceil.f32", fn(t_f32) -> t_f32);
ifn!("llvm.ceil.f64", fn(t_f64) -> t_f64);
ifn!("llvm.ceil.f128", fn(t_f128) -> t_f128);
ifn!("llvm.trunc.f16", fn(t_f16) -> t_f16);
ifn!("llvm.trunc.f32", fn(t_f32) -> t_f32);
ifn!("llvm.trunc.f64", fn(t_f64) -> t_f64);
ifn!("llvm.trunc.f128", fn(t_f128) -> t_f128);
ifn!("llvm.copysign.f16", fn(t_f16, t_f16) -> t_f16);
ifn!("llvm.copysign.f32", fn(t_f32, t_f32) -> t_f32);
ifn!("llvm.copysign.f64", fn(t_f64, t_f64) -> t_f64);
ifn!("llvm.copysign.f128", fn(t_f128, t_f128) -> t_f128);
ifn!("llvm.round.f16", fn(t_f16) -> t_f16);
ifn!("llvm.round.f32", fn(t_f32) -> t_f32);
ifn!("llvm.round.f64", fn(t_f64) -> t_f64);
ifn!("llvm.round.f128", fn(t_f128) -> t_f128);
ifn!("llvm.roundeven.f16", fn(t_f16) -> t_f16);
ifn!("llvm.roundeven.f32", fn(t_f32) -> t_f32);
ifn!("llvm.roundeven.f64", fn(t_f64) -> t_f64);
ifn!("llvm.roundeven.f128", fn(t_f128) -> t_f128);
ifn!("llvm.rint.f16", fn(t_f16) -> t_f16);
ifn!("llvm.rint.f32", fn(t_f32) -> t_f32);
ifn!("llvm.rint.f64", fn(t_f64) -> t_f64);
ifn!("llvm.rint.f128", fn(t_f128) -> t_f128);
ifn!("llvm.nearbyint.f16", fn(t_f16) -> t_f16);
ifn!("llvm.nearbyint.f32", fn(t_f32) -> t_f32);
ifn!("llvm.nearbyint.f64", fn(t_f64) -> t_f64);
ifn!("llvm.nearbyint.f128", fn(t_f128) -> t_f128);
ifn!("llvm.ctpop.i8", fn(t_i8) -> t_i8);
ifn!("llvm.ctpop.i16", fn(t_i16) -> t_i16);

View file

@ -695,7 +695,7 @@ impl MsvcBasicName for ty::UintTy {
impl MsvcBasicName for ty::FloatTy {
fn msvc_basic_name(self) -> &'static str {
// FIXME: f16 and f128 have no MSVE representation. We could improve the debuginfo.
// FIXME: f16 and f128 have no MSVC representation. We could improve the debuginfo.
// See: <https://github.com/rust-lang/rust/pull/114607/files#r1454683264>
match self {
ty::FloatTy::F16 => "half",

View file

@ -28,51 +28,118 @@ fn get_simple_intrinsic<'ll>(
name: Symbol,
) -> Option<(&'ll Type, &'ll Value)> {
let llvm_name = match name {
sym::sqrtf16 => "llvm.sqrt.f16",
sym::sqrtf32 => "llvm.sqrt.f32",
sym::sqrtf64 => "llvm.sqrt.f64",
sym::sqrtf128 => "llvm.sqrt.f128",
sym::powif16 => "llvm.powi.f16",
sym::powif32 => "llvm.powi.f32",
sym::powif64 => "llvm.powi.f64",
sym::powif128 => "llvm.powi.f128",
sym::sinf16 => "llvm.sin.f16",
sym::sinf32 => "llvm.sin.f32",
sym::sinf64 => "llvm.sin.f64",
sym::sinf128 => "llvm.sin.f128",
sym::cosf16 => "llvm.cos.f16",
sym::cosf32 => "llvm.cos.f32",
sym::cosf64 => "llvm.cos.f64",
sym::cosf128 => "llvm.cos.f128",
sym::powf16 => "llvm.pow.f16",
sym::powf32 => "llvm.pow.f32",
sym::powf64 => "llvm.pow.f64",
sym::powf128 => "llvm.pow.f128",
sym::expf16 => "llvm.exp.f16",
sym::expf32 => "llvm.exp.f32",
sym::expf64 => "llvm.exp.f64",
sym::expf128 => "llvm.exp.f128",
sym::exp2f16 => "llvm.exp2.f16",
sym::exp2f32 => "llvm.exp2.f32",
sym::exp2f64 => "llvm.exp2.f64",
sym::exp2f128 => "llvm.exp2.f128",
sym::logf16 => "llvm.log.f16",
sym::logf32 => "llvm.log.f32",
sym::logf64 => "llvm.log.f64",
sym::logf128 => "llvm.log.f128",
sym::log10f16 => "llvm.log10.f16",
sym::log10f32 => "llvm.log10.f32",
sym::log10f64 => "llvm.log10.f64",
sym::log10f128 => "llvm.log10.f128",
sym::log2f16 => "llvm.log2.f16",
sym::log2f32 => "llvm.log2.f32",
sym::log2f64 => "llvm.log2.f64",
sym::log2f128 => "llvm.log2.f128",
sym::fmaf16 => "llvm.fma.f16",
sym::fmaf32 => "llvm.fma.f32",
sym::fmaf64 => "llvm.fma.f64",
sym::fmaf128 => "llvm.fma.f128",
sym::fabsf16 => "llvm.fabs.f16",
sym::fabsf32 => "llvm.fabs.f32",
sym::fabsf64 => "llvm.fabs.f64",
sym::fabsf128 => "llvm.fabs.f128",
sym::minnumf16 => "llvm.minnum.f16",
sym::minnumf32 => "llvm.minnum.f32",
sym::minnumf64 => "llvm.minnum.f64",
sym::minnumf128 => "llvm.minnum.f128",
sym::maxnumf16 => "llvm.maxnum.f16",
sym::maxnumf32 => "llvm.maxnum.f32",
sym::maxnumf64 => "llvm.maxnum.f64",
sym::maxnumf128 => "llvm.maxnum.f128",
sym::copysignf16 => "llvm.copysign.f16",
sym::copysignf32 => "llvm.copysign.f32",
sym::copysignf64 => "llvm.copysign.f64",
sym::copysignf128 => "llvm.copysign.f128",
sym::floorf16 => "llvm.floor.f16",
sym::floorf32 => "llvm.floor.f32",
sym::floorf64 => "llvm.floor.f64",
sym::floorf128 => "llvm.floor.f128",
sym::ceilf16 => "llvm.ceil.f16",
sym::ceilf32 => "llvm.ceil.f32",
sym::ceilf64 => "llvm.ceil.f64",
sym::ceilf128 => "llvm.ceil.f128",
sym::truncf16 => "llvm.trunc.f16",
sym::truncf32 => "llvm.trunc.f32",
sym::truncf64 => "llvm.trunc.f64",
sym::truncf128 => "llvm.trunc.f128",
sym::rintf16 => "llvm.rint.f16",
sym::rintf32 => "llvm.rint.f32",
sym::rintf64 => "llvm.rint.f64",
sym::rintf128 => "llvm.rint.f128",
sym::nearbyintf16 => "llvm.nearbyint.f16",
sym::nearbyintf32 => "llvm.nearbyint.f32",
sym::nearbyintf64 => "llvm.nearbyint.f64",
sym::nearbyintf128 => "llvm.nearbyint.f128",
sym::roundf16 => "llvm.round.f16",
sym::roundf32 => "llvm.round.f32",
sym::roundf64 => "llvm.round.f64",
sym::roundf128 => "llvm.round.f128",
sym::ptr_mask => "llvm.ptrmask",
sym::roundevenf16 => "llvm.roundeven.f16",
sym::roundevenf32 => "llvm.roundeven.f32",
sym::roundevenf64 => "llvm.roundeven.f64",
sym::roundevenf128 => "llvm.roundeven.f128",
_ => return None,
};
Some(cx.get_intrinsic(llvm_name))

View file

@ -480,6 +480,9 @@ pub struct SanitizerOptions {
pub sanitize_address: bool,
pub sanitize_address_recover: bool,
pub sanitize_cfi: bool,
pub sanitize_dataflow: bool,
pub sanitize_dataflow_abilist: *const *const c_char,
pub sanitize_dataflow_abilist_len: size_t,
pub sanitize_kcfi: bool,
pub sanitize_memory: bool,
pub sanitize_memory_recover: bool,

View file

@ -1221,6 +1221,9 @@ fn add_sanitizer_libraries(
if sanitizer.contains(SanitizerSet::ADDRESS) {
link_sanitizer_runtime(sess, flavor, linker, "asan");
}
if sanitizer.contains(SanitizerSet::DATAFLOW) {
link_sanitizer_runtime(sess, flavor, linker, "dfsan");
}
if sanitizer.contains(SanitizerSet::LEAK) {
link_sanitizer_runtime(sess, flavor, linker, "lsan");
}

View file

@ -95,6 +95,7 @@ pub struct ModuleConfig {
pub sanitizer: SanitizerSet,
pub sanitizer_recover: SanitizerSet,
pub sanitizer_dataflow_abilist: Vec<String>,
pub sanitizer_memory_track_origins: usize,
// Flags indicating which outputs to produce.
@ -197,6 +198,10 @@ impl ModuleConfig {
),
sanitizer: if_regular!(sess.opts.unstable_opts.sanitizer, SanitizerSet::empty()),
sanitizer_dataflow_abilist: if_regular!(
sess.opts.unstable_opts.sanitizer_dataflow_abilist.clone(),
Vec::new()
),
sanitizer_recover: if_regular!(
sess.opts.unstable_opts.sanitizer_recover,
SanitizerSet::empty()

View file

@ -4,7 +4,7 @@
//! other areas of the compiler as well.
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::traits::{DefiningAnchor, ObligationCause};
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, Variance};
use rustc_trait_selection::traits::ObligationCtxt;
@ -33,9 +33,6 @@ pub fn is_equal_up_to_subtyping<'tcx>(
/// When validating assignments, the variance should be `Covariant`. When checking
/// during `MirPhase` >= `MirPhase::Runtime(RuntimePhase::Initial)` variance should be `Invariant`
/// because we want to check for type equality.
///
/// This mostly ignores opaque types as it can be used in constraining contexts
/// while still computing the final underlying type.
pub fn relate_types<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
@ -47,8 +44,7 @@ pub fn relate_types<'tcx>(
return true;
}
let mut builder =
tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(DefiningAnchor::Bubble);
let mut builder = tcx.infer_ctxt().ignoring_regions();
let infcx = builder.build();
let ocx = ObligationCtxt::new(&infcx);
let cause = ObligationCause::dummy();
@ -58,20 +54,5 @@ pub fn relate_types<'tcx>(
Ok(()) => {}
Err(_) => return false,
};
let errors = ocx.select_all_or_error();
// With `Reveal::All`, opaque types get normalized away, with `Reveal::UserFacing`
// we would get unification errors because we're unable to look into opaque types,
// even if they're constrained in our current function.
for (key, ty) in infcx.take_opaque_types() {
let hidden_ty = tcx.type_of(key.def_id).instantiate(tcx, key.args);
if hidden_ty != ty.hidden_type.ty {
span_bug!(
ty.hidden_type.span,
"{}, {}",
tcx.type_of(key.def_id).instantiate(tcx, key.args),
ty.hidden_type.ty
);
}
}
errors.is_empty()
ocx.select_all_or_error().is_empty()
}

View file

@ -2460,6 +2460,7 @@ impl PrimTy {
Self::Uint(UintTy::Usize),
Self::Float(FloatTy::F32),
Self::Float(FloatTy::F64),
// FIXME(f16_f128): add these when enabled below
Self::Bool,
Self::Char,
Self::Str,
@ -2509,6 +2510,10 @@ impl PrimTy {
sym::usize => Self::Uint(UintTy::Usize),
sym::f32 => Self::Float(FloatTy::F32),
sym::f64 => Self::Float(FloatTy::F64),
// FIXME(f16_f128): enabling these will open the gates of f16 and f128 being
// understood by rustc.
// sym::f16 => Self::Float(FloatTy::F16),
// sym::f128 => Self::Float(FloatTy::F128),
sym::bool => Self::Bool,
sym::char => Self::Char,
sym::str => Self::Str,

View file

@ -112,11 +112,15 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
| sym::likely
| sym::unlikely
| sym::ptr_guaranteed_cmp
| sym::minnumf16
| sym::minnumf32
| sym::minnumf64
| sym::minnumf128
| sym::maxnumf16
| sym::maxnumf32
| sym::rustc_peek
| sym::maxnumf64
| sym::maxnumf128
| sym::rustc_peek
| sym::type_name
| sym::forget
| sym::black_box
@ -302,50 +306,118 @@ pub fn check_intrinsic_type(
],
Ty::new_unit(tcx),
),
sym::sqrtf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
sym::sqrtf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
sym::sqrtf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
sym::sqrtf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
sym::powif16 => (0, 0, vec![tcx.types.f16, tcx.types.i32], tcx.types.f16),
sym::powif32 => (0, 0, vec![tcx.types.f32, tcx.types.i32], tcx.types.f32),
sym::powif64 => (0, 0, vec![tcx.types.f64, tcx.types.i32], tcx.types.f64),
sym::powif128 => (0, 0, vec![tcx.types.f128, tcx.types.i32], tcx.types.f128),
sym::sinf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
sym::sinf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
sym::sinf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
sym::sinf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
sym::cosf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
sym::cosf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
sym::cosf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
sym::cosf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
sym::powf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16),
sym::powf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
sym::powf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
sym::powf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128),
sym::expf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
sym::expf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
sym::expf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
sym::expf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
sym::exp2f16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
sym::exp2f32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
sym::exp2f64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
sym::exp2f128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
sym::logf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
sym::logf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
sym::logf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
sym::logf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
sym::log10f16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
sym::log10f32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
sym::log10f64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
sym::log10f128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
sym::log2f16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
sym::log2f32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
sym::log2f64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
sym::log2f128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
sym::fmaf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16, tcx.types.f16], tcx.types.f16),
sym::fmaf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32, tcx.types.f32], tcx.types.f32),
sym::fmaf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64, tcx.types.f64], tcx.types.f64),
sym::fmaf128 => {
(0, 0, vec![tcx.types.f128, tcx.types.f128, tcx.types.f128], tcx.types.f128)
}
sym::fabsf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
sym::fabsf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
sym::fabsf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
sym::fabsf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
sym::minnumf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16),
sym::minnumf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
sym::minnumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
sym::minnumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128),
sym::maxnumf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16),
sym::maxnumf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
sym::maxnumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
sym::maxnumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128),
sym::copysignf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16),
sym::copysignf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
sym::copysignf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
sym::copysignf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128),
sym::floorf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
sym::floorf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
sym::floorf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
sym::floorf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
sym::ceilf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
sym::ceilf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
sym::ceilf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
sym::ceilf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
sym::truncf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
sym::truncf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
sym::truncf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
sym::truncf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
sym::rintf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
sym::rintf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
sym::rintf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
sym::rintf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
sym::nearbyintf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
sym::nearbyintf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
sym::nearbyintf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
sym::nearbyintf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
sym::roundf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
sym::roundf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
sym::roundf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
sym::roundf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
sym::roundevenf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
sym::roundevenf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
sym::roundevenf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
sym::roundevenf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
sym::volatile_load | sym::unaligned_volatile_load => {
(1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(0))

View file

@ -811,6 +811,7 @@ fn test_unstable_options_tracking_hash() {
tracked!(sanitizer_cfi_canonical_jump_tables, None);
tracked!(sanitizer_cfi_generalize_pointers, Some(true));
tracked!(sanitizer_cfi_normalize_integers, Some(true));
tracked!(sanitizer_dataflow_abilist, vec![String::from("/rustc/abc")]);
tracked!(sanitizer_memory_track_origins, 2);
tracked!(sanitizer_recover, SanitizerSet::ADDRESS);
tracked!(saturating_float_casts, Some(true));

View file

@ -42,6 +42,7 @@
#endif
#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
#include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h"
#include "llvm/Support/TimeProfiler.h"
#if LLVM_VERSION_GE(19, 0)
#include "llvm/Support/PGOOptions.h"
@ -686,6 +687,9 @@ struct LLVMRustSanitizerOptions {
bool SanitizeAddress;
bool SanitizeAddressRecover;
bool SanitizeCFI;
bool SanitizeDataFlow;
char **SanitizeDataFlowABIList;
size_t SanitizeDataFlowABIListLen;
bool SanitizeKCFI;
bool SanitizeMemory;
bool SanitizeMemoryRecover;
@ -883,6 +887,18 @@ LLVMRustOptimize(
}
if (SanitizerOptions) {
if (SanitizerOptions->SanitizeDataFlow) {
std::vector<std::string> ABIListFiles(
SanitizerOptions->SanitizeDataFlowABIList,
SanitizerOptions->SanitizeDataFlowABIList +
SanitizerOptions->SanitizeDataFlowABIListLen);
OptimizerLastEPCallbacks.push_back(
[ABIListFiles](ModulePassManager &MPM, OptimizationLevel Level) {
MPM.addPass(DataFlowSanitizerPass(ABIListFiles));
}
);
}
if (SanitizerOptions->SanitizeMemory) {
MemorySanitizerOptions Options(
SanitizerOptions->SanitizeMemoryTrackOrigins,

View file

@ -1991,8 +1991,10 @@ pub fn uint_ty(uty: ast::UintTy) -> UintTy {
pub fn float_ty(fty: ast::FloatTy) -> FloatTy {
match fty {
ast::FloatTy::F16 => FloatTy::F16,
ast::FloatTy::F32 => FloatTy::F32,
ast::FloatTy::F64 => FloatTy::F64,
ast::FloatTy::F128 => FloatTy::F128,
}
}

View file

@ -701,7 +701,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.bind_pattern(
self.source_info(irrefutable_pat.span),
candidate,
&fake_borrow_temps,
fake_borrow_temps.as_slice(),
irrefutable_pat.span,
None,
false,
@ -1938,7 +1938,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let post_guard_block = self.bind_pattern(
self.source_info(pat.span),
guard_candidate,
&fake_borrow_temps,
fake_borrow_temps.as_slice(),
expr_span,
None,
false,
@ -2425,7 +2425,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let matching = this.bind_pattern(
this.source_info(pattern.span),
candidate,
&fake_borrow_temps,
fake_borrow_temps.as_slice(),
initializer_span,
None,
true,
@ -2434,7 +2434,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let failure = this.bind_pattern(
this.source_info(else_block_span),
wildcard,
&fake_borrow_temps,
fake_borrow_temps.as_slice(),
initializer_span,
None,
true,

View file

@ -41,60 +41,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// let y = x;
// }
//
// We can't just reverse the binding order, because we must preserve pattern-order
// otherwise, e.g. in `let (Some(a), Some(b)) = (x, y)`. Our rule then is: deepest-first,
// and bindings at the same depth stay in source order.
//
// To do this, every time around the loop we prepend the newly found bindings to the
// bindings we already had.
//
// example:
// candidate.bindings = [1, 2, 3]
// bindings in iter 1: [4, 5]
// bindings in iter 2: [6, 7]
//
// final bindings: [6, 7, 4, 5, 1, 2, 3]
let mut accumulated_bindings = mem::take(candidate_bindings);
let mut simplified_match_pairs = Vec::new();
// Repeatedly simplify match pairs until we're left with only unsimplifiable ones.
loop {
for mut match_pair in mem::take(match_pairs) {
if let TestCase::Irrefutable { binding, ascription } = match_pair.test_case {
if let Some(binding) = binding {
candidate_bindings.push(binding);
}
if let Some(ascription) = ascription {
candidate_ascriptions.push(ascription);
}
// Simplifiable pattern; we replace it with its subpairs and simplify further.
match_pairs.append(&mut match_pair.subpairs);
} else {
// Unsimplifiable pattern; we recursively simplify its subpairs and don't
// process it further.
self.simplify_match_pairs(
&mut match_pair.subpairs,
candidate_bindings,
candidate_ascriptions,
);
simplified_match_pairs.push(match_pair);
// We therefore lower bindings from left-to-right, except we lower the `x` in `x @ pat`
// after any bindings in `pat`. This doesn't work for or-patterns: the current structure of
// match lowering forces us to lower bindings inside or-patterns last.
for mut match_pair in mem::take(match_pairs) {
self.simplify_match_pairs(
&mut match_pair.subpairs,
candidate_bindings,
candidate_ascriptions,
);
if let TestCase::Irrefutable { binding, ascription } = match_pair.test_case {
if let Some(binding) = binding {
candidate_bindings.push(binding);
}
}
// This does: accumulated_bindings = candidate.bindings.take() ++ accumulated_bindings
candidate_bindings.extend_from_slice(&accumulated_bindings);
mem::swap(candidate_bindings, &mut accumulated_bindings);
candidate_bindings.clear();
if match_pairs.is_empty() {
break;
if let Some(ascription) = ascription {
candidate_ascriptions.push(ascription);
}
// Simplifiable pattern; we replace it with its already simplified subpairs.
match_pairs.append(&mut match_pair.subpairs);
} else {
// Unsimplifiable pattern; we keep it.
match_pairs.push(match_pair);
}
}
// Store computed bindings back in `candidate_bindings`.
mem::swap(candidate_bindings, &mut accumulated_bindings);
// Store simplified match pairs back in `match_pairs`.
mem::swap(match_pairs, &mut simplified_match_pairs);
// Move or-patterns to the end, because they can result in us
// creating additional candidates, so we want to test them as
// late as possible.

View file

@ -371,7 +371,8 @@ mod desc {
pub const parse_list: &str = "a space-separated list of strings";
pub const parse_list_with_polarity: &str =
"a comma-separated list of strings, with elements beginning with + or -";
pub const parse_opt_comma_list: &str = "a comma-separated list of strings";
pub const parse_comma_list: &str = "a comma-separated list of strings";
pub const parse_opt_comma_list: &str = parse_comma_list;
pub const parse_number: &str = "a number";
pub const parse_opt_number: &str = parse_number;
pub const parse_threads: &str = parse_number;
@ -381,7 +382,7 @@ mod desc {
pub const parse_opt_panic_strategy: &str = parse_panic_strategy;
pub const parse_oom_strategy: &str = "either `panic` or `abort`";
pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, or `thread`";
pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, or `thread`";
pub const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2";
pub const parse_cfguard: &str =
"either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`";
@ -602,6 +603,18 @@ mod parse {
}
}
pub(crate) fn parse_comma_list(slot: &mut Vec<String>, v: Option<&str>) -> bool {
match v {
Some(s) => {
let mut v: Vec<_> = s.split(',').map(|s| s.to_string()).collect();
v.sort_unstable();
*slot = v;
true
}
None => false,
}
}
pub(crate) fn parse_opt_comma_list(slot: &mut Option<Vec<String>>, v: Option<&str>) -> bool {
match v {
Some(s) => {
@ -718,6 +731,7 @@ mod parse {
*slot |= match s {
"address" => SanitizerSet::ADDRESS,
"cfi" => SanitizerSet::CFI,
"dataflow" => SanitizerSet::DATAFLOW,
"kcfi" => SanitizerSet::KCFI,
"kernel-address" => SanitizerSet::KERNELADDRESS,
"leak" => SanitizerSet::LEAK,
@ -1846,6 +1860,8 @@ written to standard error output)"),
"enable generalizing pointer types (default: no)"),
sanitizer_cfi_normalize_integers: Option<bool> = (None, parse_opt_bool, [TRACKED],
"enable normalizing integer types (default: no)"),
sanitizer_dataflow_abilist: Vec<String> = (Vec::new(), parse_comma_list, [TRACKED],
"additional ABI list files that control how shadow parameters are passed (comma separated)"),
sanitizer_memory_track_origins: usize = (0, parse_sanitizer_memory_track_origins, [TRACKED],
"enable origins tracking in MemorySanitizer"),
sanitizer_recover: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED],

View file

@ -490,6 +490,8 @@ symbols! {
catch_unwind,
cause,
cdylib,
ceilf128,
ceilf16,
ceilf32,
ceilf64,
cfg,
@ -595,6 +597,8 @@ symbols! {
copy,
copy_closures,
copy_nonoverlapping,
copysignf128,
copysignf16,
copysignf32,
copysignf64,
core,
@ -607,6 +611,8 @@ symbols! {
coroutine_resume,
coroutine_state,
coroutines,
cosf128,
cosf16,
cosf32,
cosf64,
count,
@ -737,10 +743,14 @@ symbols! {
exhaustive_integer_patterns,
exhaustive_patterns,
existential_type,
exp2f128,
exp2f16,
exp2f32,
exp2f64,
expect,
expected,
expf128,
expf16,
expf32,
expf64,
explicit_generic_args_with_impl_trait,
@ -759,7 +769,9 @@ symbols! {
external_doc,
f,
f128,
f128_nan,
f16,
f16_nan,
f16c_target_feature,
f32,
f32_legacy_const_digits,
@ -793,6 +805,8 @@ symbols! {
f64_legacy_const_neg_infinity,
f64_legacy_const_radix,
f64_nan,
fabsf128,
fabsf16,
fabsf32,
fabsf64,
fadd_algebraic,
@ -813,8 +827,12 @@ symbols! {
file,
float,
float_to_int_unchecked,
floorf128,
floorf16,
floorf32,
floorf64,
fmaf128,
fmaf16,
fmaf32,
fmaf64,
fmt,
@ -1030,11 +1048,17 @@ symbols! {
loaded_from_disk,
local,
local_inner_macros,
log10f128,
log10f16,
log10f32,
log10f64,
log2f128,
log2f16,
log2f32,
log2f64,
log_syntax,
logf128,
logf16,
logf32,
logf64,
loongarch_target_feature,
@ -1062,6 +1086,8 @@ symbols! {
match_beginning_vert,
match_default_bindings,
matches_macro,
maxnumf128,
maxnumf16,
maxnumf32,
maxnumf64,
may_dangle,
@ -1093,6 +1119,8 @@ symbols! {
min_exhaustive_patterns,
min_specialization,
min_type_alias_impl_trait,
minnumf128,
minnumf16,
minnumf32,
minnumf64,
mips_target_feature,
@ -1155,6 +1183,8 @@ symbols! {
native_link_modifiers_whole_archive,
natvis_file,
ne,
nearbyintf128,
nearbyintf16,
nearbyintf32,
nearbyintf64,
needs_allocator,
@ -1289,8 +1319,12 @@ symbols! {
poll_next,
post_dash_lto: "post-lto",
powerpc_target_feature,
powf128,
powf16,
powf32,
powf64,
powif128,
powif16,
powif32,
powif64,
pre_dash_lto: "pre-lto",
@ -1416,6 +1450,8 @@ symbols! {
return_position_impl_trait_in_trait,
return_type_notation,
rhs,
rintf128,
rintf16,
rintf32,
rintf64,
riscv_target_feature,
@ -1424,8 +1460,12 @@ symbols! {
ropi_rwpi: "ropi-rwpi",
rotate_left,
rotate_right,
roundevenf128,
roundevenf16,
roundevenf32,
roundevenf64,
roundf128,
roundf16,
roundf32,
roundf64,
rt,
@ -1630,6 +1670,8 @@ symbols! {
simd_trunc,
simd_xor,
since,
sinf128,
sinf16,
sinf32,
sinf64,
size,
@ -1647,6 +1689,8 @@ symbols! {
specialization,
speed,
spotlight,
sqrtf128,
sqrtf16,
sqrtf32,
sqrtf64,
sreg,
@ -1746,6 +1790,8 @@ symbols! {
transparent_enums,
transparent_unions,
trivial_bounds,
truncf128,
truncf16,
truncf32,
truncf64,
try_blocks,

View file

@ -464,16 +464,17 @@ fn encode_ty<'tcx>(
typeid.push_str(&s);
}
// Rust's f32 and f64 single (32-bit) and double (64-bit) precision floating-point types
// have IEEE-754 binary32 and binary64 floating-point layouts, respectively.
// Rust's f16, f32, f64, and f126 half (16-bit), single (32-bit), double (64-bit), and
// quad (128-bit) precision floating-point types have IEEE-754 binary16, binary32,
// binary64, and binary128 floating-point layouts, respectively.
//
// (See https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#fixed-width-floating-point-types.)
ty::Float(float_ty) => {
typeid.push(match float_ty {
FloatTy::F16 => unimplemented!("f16_f128"),
FloatTy::F32 => 'f',
FloatTy::F64 => 'd',
FloatTy::F128 => unimplemented!("f16_f128"),
typeid.push_str(match float_ty {
FloatTy::F16 => "Dh",
FloatTy::F32 => "f",
FloatTy::F64 => "d",
FloatTy::F128 => "g",
});
}
@ -557,7 +558,7 @@ fn encode_ty<'tcx>(
// https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-compression).
let builtin_types = [
"v", "w", "b", "c", "a", "h", "s", "t", "i", "j", "l", "m", "x", "y",
"n", "o", "f", "d", "e", "g", "z",
"n", "o", "f", "d", "e", "g", "z", "Dh",
];
if !builtin_types.contains(&str) {
compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);

View file

@ -320,8 +320,11 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
ty::Uint(UintTy::U64) => "y",
ty::Uint(UintTy::U128) => "o",
ty::Uint(UintTy::Usize) => "j",
// FIXME(f16_f128): update these once `rustc-demangle` supports the new types
ty::Float(FloatTy::F16) => unimplemented!("f16_f128"),
ty::Float(FloatTy::F32) => "f",
ty::Float(FloatTy::F64) => "d",
ty::Float(FloatTy::F128) => unimplemented!("f16_f128"),
ty::Never => "z",
// Placeholders (should be demangled as `_`).

View file

@ -1221,6 +1221,7 @@ bitflags::bitflags! {
const KCFI = 1 << 8;
const KERNELADDRESS = 1 << 9;
const SAFESTACK = 1 << 10;
const DATAFLOW = 1 << 11;
}
}
rustc_data_structures::external_bitflags_debug! { SanitizerSet }
@ -1233,6 +1234,7 @@ impl SanitizerSet {
Some(match self {
SanitizerSet::ADDRESS => "address",
SanitizerSet::CFI => "cfi",
SanitizerSet::DATAFLOW => "dataflow",
SanitizerSet::KCFI => "kcfi",
SanitizerSet::KERNELADDRESS => "kernel-address",
SanitizerSet::LEAK => "leak",
@ -2790,6 +2792,7 @@ impl Target {
base.$key_name |= match s.as_str() {
Some("address") => SanitizerSet::ADDRESS,
Some("cfi") => SanitizerSet::CFI,
Some("dataflow") => SanitizerSet::DATAFLOW,
Some("kcfi") => SanitizerSet::KCFI,
Some("kernel-address") => SanitizerSet::KERNELADDRESS,
Some("leak") => SanitizerSet::LEAK,

View file

@ -10,6 +10,7 @@ pub fn target() -> Target {
base.static_position_independent_executables = true;
base.supported_sanitizers = SanitizerSet::ADDRESS
| SanitizerSet::CFI
| SanitizerSet::DATAFLOW
| SanitizerSet::LEAK
| SanitizerSet::MEMORY
| SanitizerSet::SAFESTACK