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:
@@ -1920,22 +1920,28 @@ pub struct FnSig {
|
|||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||||
#[derive(Encodable, Decodable, HashStable_Generic)]
|
#[derive(Encodable, Decodable, HashStable_Generic)]
|
||||||
pub enum FloatTy {
|
pub enum FloatTy {
|
||||||
|
F16,
|
||||||
F32,
|
F32,
|
||||||
F64,
|
F64,
|
||||||
|
F128,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FloatTy {
|
impl FloatTy {
|
||||||
pub fn name_str(self) -> &'static str {
|
pub fn name_str(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
|
FloatTy::F16 => "f16",
|
||||||
FloatTy::F32 => "f32",
|
FloatTy::F32 => "f32",
|
||||||
FloatTy::F64 => "f64",
|
FloatTy::F64 => "f64",
|
||||||
|
FloatTy::F128 => "f128",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(self) -> Symbol {
|
pub fn name(self) -> Symbol {
|
||||||
match self {
|
match self {
|
||||||
|
FloatTy::F16 => sym::f16,
|
||||||
FloatTy::F32 => sym::f32,
|
FloatTy::F32 => sym::f32,
|
||||||
FloatTy::F64 => sym::f64,
|
FloatTy::F64 => sym::f64,
|
||||||
|
FloatTy::F128 => sym::f128,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -519,12 +519,22 @@ pub(crate) unsafe fn llvm_optimize(
|
|||||||
let pgo_sample_use_path = get_pgo_sample_use_path(config);
|
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 is_lto = opt_stage == llvm::OptStage::ThinLTO || opt_stage == llvm::OptStage::FatLTO;
|
||||||
let instr_profile_output_path = get_instr_profile_output_path(config);
|
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.
|
// Sanitizer instrumentation is only inserted during the pre-link optimization stage.
|
||||||
let sanitizer_options = if !is_lto {
|
let sanitizer_options = if !is_lto {
|
||||||
Some(llvm::SanitizerOptions {
|
Some(llvm::SanitizerOptions {
|
||||||
sanitize_address: config.sanitizer.contains(SanitizerSet::ADDRESS),
|
sanitize_address: config.sanitizer.contains(SanitizerSet::ADDRESS),
|
||||||
sanitize_address_recover: config.sanitizer_recover.contains(SanitizerSet::ADDRESS),
|
sanitize_address_recover: config.sanitizer_recover.contains(SanitizerSet::ADDRESS),
|
||||||
sanitize_cfi: config.sanitizer.contains(SanitizerSet::CFI),
|
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_kcfi: config.sanitizer.contains(SanitizerSet::KCFI),
|
||||||
sanitize_memory: config.sanitizer.contains(SanitizerSet::MEMORY),
|
sanitize_memory: config.sanitizer.contains(SanitizerSet::MEMORY),
|
||||||
sanitize_memory_recover: config.sanitizer_recover.contains(SanitizerSet::MEMORY),
|
sanitize_memory_recover: config.sanitizer_recover.contains(SanitizerSet::MEMORY),
|
||||||
|
|||||||
@@ -685,8 +685,10 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||||||
let t_i64 = self.type_i64();
|
let t_i64 = self.type_i64();
|
||||||
let t_i128 = self.type_i128();
|
let t_i128 = self.type_i128();
|
||||||
let t_isize = self.type_isize();
|
let t_isize = self.type_isize();
|
||||||
|
let t_f16 = self.type_f16();
|
||||||
let t_f32 = self.type_f32();
|
let t_f32 = self.type_f32();
|
||||||
let t_f64 = self.type_f64();
|
let t_f64 = self.type_f64();
|
||||||
|
let t_f128 = self.type_f128();
|
||||||
let t_metadata = self.type_metadata();
|
let t_metadata = self.type_metadata();
|
||||||
let t_token = self.type_token();
|
let t_token = self.type_token();
|
||||||
|
|
||||||
@@ -728,69 +730,115 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||||||
ifn!("llvm.debugtrap", fn() -> void);
|
ifn!("llvm.debugtrap", fn() -> void);
|
||||||
ifn!("llvm.frameaddress", fn(t_i32) -> ptr);
|
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.f32", fn(t_f32, t_i32) -> t_f32);
|
||||||
ifn!("llvm.powi.f64", fn(t_f64, t_i32) -> t_f64);
|
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.f32", fn(t_f32, t_f32) -> t_f32);
|
||||||
ifn!("llvm.pow.f64", fn(t_f64, t_f64) -> t_f64);
|
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.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.sqrt.f64", fn(t_f64) -> t_f64);
|
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.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.sin.f64", fn(t_f64) -> t_f64);
|
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.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.cos.f64", fn(t_f64) -> t_f64);
|
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.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.exp.f64", fn(t_f64) -> t_f64);
|
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.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.exp2.f64", fn(t_f64) -> t_f64);
|
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.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.log.f64", fn(t_f64) -> t_f64);
|
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.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.log10.f64", fn(t_f64) -> t_f64);
|
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.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.log2.f64", fn(t_f64) -> t_f64);
|
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.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.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.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.fabs.f64", fn(t_f64) -> t_f64);
|
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.f32", fn(t_f32, t_f32) -> t_f32);
|
||||||
ifn!("llvm.minnum.f64", fn(t_f64, t_f64) -> t_f64);
|
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.f32", fn(t_f32, t_f32) -> t_f32);
|
||||||
ifn!("llvm.maxnum.f64", fn(t_f64, t_f64) -> t_f64);
|
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.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.floor.f64", fn(t_f64) -> t_f64);
|
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.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.ceil.f64", fn(t_f64) -> t_f64);
|
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.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.trunc.f64", fn(t_f64) -> t_f64);
|
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.f32", fn(t_f32, t_f32) -> t_f32);
|
||||||
ifn!("llvm.copysign.f64", fn(t_f64, t_f64) -> t_f64);
|
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.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.round.f64", fn(t_f64) -> t_f64);
|
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.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.roundeven.f64", fn(t_f64) -> t_f64);
|
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.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.rint.f64", fn(t_f64) -> t_f64);
|
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.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.nearbyint.f64", fn(t_f64) -> t_f64);
|
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.i8", fn(t_i8) -> t_i8);
|
||||||
ifn!("llvm.ctpop.i16", fn(t_i16) -> t_i16);
|
ifn!("llvm.ctpop.i16", fn(t_i16) -> t_i16);
|
||||||
|
|||||||
@@ -695,7 +695,7 @@ impl MsvcBasicName for ty::UintTy {
|
|||||||
|
|
||||||
impl MsvcBasicName for ty::FloatTy {
|
impl MsvcBasicName for ty::FloatTy {
|
||||||
fn msvc_basic_name(self) -> &'static str {
|
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>
|
// See: <https://github.com/rust-lang/rust/pull/114607/files#r1454683264>
|
||||||
match self {
|
match self {
|
||||||
ty::FloatTy::F16 => "half",
|
ty::FloatTy::F16 => "half",
|
||||||
|
|||||||
@@ -28,51 +28,118 @@ fn get_simple_intrinsic<'ll>(
|
|||||||
name: Symbol,
|
name: Symbol,
|
||||||
) -> Option<(&'ll Type, &'ll Value)> {
|
) -> Option<(&'ll Type, &'ll Value)> {
|
||||||
let llvm_name = match name {
|
let llvm_name = match name {
|
||||||
|
sym::sqrtf16 => "llvm.sqrt.f16",
|
||||||
sym::sqrtf32 => "llvm.sqrt.f32",
|
sym::sqrtf32 => "llvm.sqrt.f32",
|
||||||
sym::sqrtf64 => "llvm.sqrt.f64",
|
sym::sqrtf64 => "llvm.sqrt.f64",
|
||||||
|
sym::sqrtf128 => "llvm.sqrt.f128",
|
||||||
|
|
||||||
|
sym::powif16 => "llvm.powi.f16",
|
||||||
sym::powif32 => "llvm.powi.f32",
|
sym::powif32 => "llvm.powi.f32",
|
||||||
sym::powif64 => "llvm.powi.f64",
|
sym::powif64 => "llvm.powi.f64",
|
||||||
|
sym::powif128 => "llvm.powi.f128",
|
||||||
|
|
||||||
|
sym::sinf16 => "llvm.sin.f16",
|
||||||
sym::sinf32 => "llvm.sin.f32",
|
sym::sinf32 => "llvm.sin.f32",
|
||||||
sym::sinf64 => "llvm.sin.f64",
|
sym::sinf64 => "llvm.sin.f64",
|
||||||
|
sym::sinf128 => "llvm.sin.f128",
|
||||||
|
|
||||||
|
sym::cosf16 => "llvm.cos.f16",
|
||||||
sym::cosf32 => "llvm.cos.f32",
|
sym::cosf32 => "llvm.cos.f32",
|
||||||
sym::cosf64 => "llvm.cos.f64",
|
sym::cosf64 => "llvm.cos.f64",
|
||||||
|
sym::cosf128 => "llvm.cos.f128",
|
||||||
|
|
||||||
|
sym::powf16 => "llvm.pow.f16",
|
||||||
sym::powf32 => "llvm.pow.f32",
|
sym::powf32 => "llvm.pow.f32",
|
||||||
sym::powf64 => "llvm.pow.f64",
|
sym::powf64 => "llvm.pow.f64",
|
||||||
|
sym::powf128 => "llvm.pow.f128",
|
||||||
|
|
||||||
|
sym::expf16 => "llvm.exp.f16",
|
||||||
sym::expf32 => "llvm.exp.f32",
|
sym::expf32 => "llvm.exp.f32",
|
||||||
sym::expf64 => "llvm.exp.f64",
|
sym::expf64 => "llvm.exp.f64",
|
||||||
|
sym::expf128 => "llvm.exp.f128",
|
||||||
|
|
||||||
|
sym::exp2f16 => "llvm.exp2.f16",
|
||||||
sym::exp2f32 => "llvm.exp2.f32",
|
sym::exp2f32 => "llvm.exp2.f32",
|
||||||
sym::exp2f64 => "llvm.exp2.f64",
|
sym::exp2f64 => "llvm.exp2.f64",
|
||||||
|
sym::exp2f128 => "llvm.exp2.f128",
|
||||||
|
|
||||||
|
sym::logf16 => "llvm.log.f16",
|
||||||
sym::logf32 => "llvm.log.f32",
|
sym::logf32 => "llvm.log.f32",
|
||||||
sym::logf64 => "llvm.log.f64",
|
sym::logf64 => "llvm.log.f64",
|
||||||
|
sym::logf128 => "llvm.log.f128",
|
||||||
|
|
||||||
|
sym::log10f16 => "llvm.log10.f16",
|
||||||
sym::log10f32 => "llvm.log10.f32",
|
sym::log10f32 => "llvm.log10.f32",
|
||||||
sym::log10f64 => "llvm.log10.f64",
|
sym::log10f64 => "llvm.log10.f64",
|
||||||
|
sym::log10f128 => "llvm.log10.f128",
|
||||||
|
|
||||||
|
sym::log2f16 => "llvm.log2.f16",
|
||||||
sym::log2f32 => "llvm.log2.f32",
|
sym::log2f32 => "llvm.log2.f32",
|
||||||
sym::log2f64 => "llvm.log2.f64",
|
sym::log2f64 => "llvm.log2.f64",
|
||||||
|
sym::log2f128 => "llvm.log2.f128",
|
||||||
|
|
||||||
|
sym::fmaf16 => "llvm.fma.f16",
|
||||||
sym::fmaf32 => "llvm.fma.f32",
|
sym::fmaf32 => "llvm.fma.f32",
|
||||||
sym::fmaf64 => "llvm.fma.f64",
|
sym::fmaf64 => "llvm.fma.f64",
|
||||||
|
sym::fmaf128 => "llvm.fma.f128",
|
||||||
|
|
||||||
|
sym::fabsf16 => "llvm.fabs.f16",
|
||||||
sym::fabsf32 => "llvm.fabs.f32",
|
sym::fabsf32 => "llvm.fabs.f32",
|
||||||
sym::fabsf64 => "llvm.fabs.f64",
|
sym::fabsf64 => "llvm.fabs.f64",
|
||||||
|
sym::fabsf128 => "llvm.fabs.f128",
|
||||||
|
|
||||||
|
sym::minnumf16 => "llvm.minnum.f16",
|
||||||
sym::minnumf32 => "llvm.minnum.f32",
|
sym::minnumf32 => "llvm.minnum.f32",
|
||||||
sym::minnumf64 => "llvm.minnum.f64",
|
sym::minnumf64 => "llvm.minnum.f64",
|
||||||
|
sym::minnumf128 => "llvm.minnum.f128",
|
||||||
|
|
||||||
|
sym::maxnumf16 => "llvm.maxnum.f16",
|
||||||
sym::maxnumf32 => "llvm.maxnum.f32",
|
sym::maxnumf32 => "llvm.maxnum.f32",
|
||||||
sym::maxnumf64 => "llvm.maxnum.f64",
|
sym::maxnumf64 => "llvm.maxnum.f64",
|
||||||
|
sym::maxnumf128 => "llvm.maxnum.f128",
|
||||||
|
|
||||||
|
sym::copysignf16 => "llvm.copysign.f16",
|
||||||
sym::copysignf32 => "llvm.copysign.f32",
|
sym::copysignf32 => "llvm.copysign.f32",
|
||||||
sym::copysignf64 => "llvm.copysign.f64",
|
sym::copysignf64 => "llvm.copysign.f64",
|
||||||
|
sym::copysignf128 => "llvm.copysign.f128",
|
||||||
|
|
||||||
|
sym::floorf16 => "llvm.floor.f16",
|
||||||
sym::floorf32 => "llvm.floor.f32",
|
sym::floorf32 => "llvm.floor.f32",
|
||||||
sym::floorf64 => "llvm.floor.f64",
|
sym::floorf64 => "llvm.floor.f64",
|
||||||
|
sym::floorf128 => "llvm.floor.f128",
|
||||||
|
|
||||||
|
sym::ceilf16 => "llvm.ceil.f16",
|
||||||
sym::ceilf32 => "llvm.ceil.f32",
|
sym::ceilf32 => "llvm.ceil.f32",
|
||||||
sym::ceilf64 => "llvm.ceil.f64",
|
sym::ceilf64 => "llvm.ceil.f64",
|
||||||
|
sym::ceilf128 => "llvm.ceil.f128",
|
||||||
|
|
||||||
|
sym::truncf16 => "llvm.trunc.f16",
|
||||||
sym::truncf32 => "llvm.trunc.f32",
|
sym::truncf32 => "llvm.trunc.f32",
|
||||||
sym::truncf64 => "llvm.trunc.f64",
|
sym::truncf64 => "llvm.trunc.f64",
|
||||||
|
sym::truncf128 => "llvm.trunc.f128",
|
||||||
|
|
||||||
|
sym::rintf16 => "llvm.rint.f16",
|
||||||
sym::rintf32 => "llvm.rint.f32",
|
sym::rintf32 => "llvm.rint.f32",
|
||||||
sym::rintf64 => "llvm.rint.f64",
|
sym::rintf64 => "llvm.rint.f64",
|
||||||
|
sym::rintf128 => "llvm.rint.f128",
|
||||||
|
|
||||||
|
sym::nearbyintf16 => "llvm.nearbyint.f16",
|
||||||
sym::nearbyintf32 => "llvm.nearbyint.f32",
|
sym::nearbyintf32 => "llvm.nearbyint.f32",
|
||||||
sym::nearbyintf64 => "llvm.nearbyint.f64",
|
sym::nearbyintf64 => "llvm.nearbyint.f64",
|
||||||
|
sym::nearbyintf128 => "llvm.nearbyint.f128",
|
||||||
|
|
||||||
|
sym::roundf16 => "llvm.round.f16",
|
||||||
sym::roundf32 => "llvm.round.f32",
|
sym::roundf32 => "llvm.round.f32",
|
||||||
sym::roundf64 => "llvm.round.f64",
|
sym::roundf64 => "llvm.round.f64",
|
||||||
|
sym::roundf128 => "llvm.round.f128",
|
||||||
|
|
||||||
sym::ptr_mask => "llvm.ptrmask",
|
sym::ptr_mask => "llvm.ptrmask",
|
||||||
|
|
||||||
|
sym::roundevenf16 => "llvm.roundeven.f16",
|
||||||
sym::roundevenf32 => "llvm.roundeven.f32",
|
sym::roundevenf32 => "llvm.roundeven.f32",
|
||||||
sym::roundevenf64 => "llvm.roundeven.f64",
|
sym::roundevenf64 => "llvm.roundeven.f64",
|
||||||
|
sym::roundevenf128 => "llvm.roundeven.f128",
|
||||||
|
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
Some(cx.get_intrinsic(llvm_name))
|
Some(cx.get_intrinsic(llvm_name))
|
||||||
|
|||||||
@@ -480,6 +480,9 @@ pub struct SanitizerOptions {
|
|||||||
pub sanitize_address: bool,
|
pub sanitize_address: bool,
|
||||||
pub sanitize_address_recover: bool,
|
pub sanitize_address_recover: bool,
|
||||||
pub sanitize_cfi: 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_kcfi: bool,
|
||||||
pub sanitize_memory: bool,
|
pub sanitize_memory: bool,
|
||||||
pub sanitize_memory_recover: bool,
|
pub sanitize_memory_recover: bool,
|
||||||
|
|||||||
@@ -1221,6 +1221,9 @@ fn add_sanitizer_libraries(
|
|||||||
if sanitizer.contains(SanitizerSet::ADDRESS) {
|
if sanitizer.contains(SanitizerSet::ADDRESS) {
|
||||||
link_sanitizer_runtime(sess, flavor, linker, "asan");
|
link_sanitizer_runtime(sess, flavor, linker, "asan");
|
||||||
}
|
}
|
||||||
|
if sanitizer.contains(SanitizerSet::DATAFLOW) {
|
||||||
|
link_sanitizer_runtime(sess, flavor, linker, "dfsan");
|
||||||
|
}
|
||||||
if sanitizer.contains(SanitizerSet::LEAK) {
|
if sanitizer.contains(SanitizerSet::LEAK) {
|
||||||
link_sanitizer_runtime(sess, flavor, linker, "lsan");
|
link_sanitizer_runtime(sess, flavor, linker, "lsan");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ pub struct ModuleConfig {
|
|||||||
|
|
||||||
pub sanitizer: SanitizerSet,
|
pub sanitizer: SanitizerSet,
|
||||||
pub sanitizer_recover: SanitizerSet,
|
pub sanitizer_recover: SanitizerSet,
|
||||||
|
pub sanitizer_dataflow_abilist: Vec<String>,
|
||||||
pub sanitizer_memory_track_origins: usize,
|
pub sanitizer_memory_track_origins: usize,
|
||||||
|
|
||||||
// Flags indicating which outputs to produce.
|
// Flags indicating which outputs to produce.
|
||||||
@@ -197,6 +198,10 @@ impl ModuleConfig {
|
|||||||
),
|
),
|
||||||
|
|
||||||
sanitizer: if_regular!(sess.opts.unstable_opts.sanitizer, SanitizerSet::empty()),
|
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!(
|
sanitizer_recover: if_regular!(
|
||||||
sess.opts.unstable_opts.sanitizer_recover,
|
sess.opts.unstable_opts.sanitizer_recover,
|
||||||
SanitizerSet::empty()
|
SanitizerSet::empty()
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
//! other areas of the compiler as well.
|
//! other areas of the compiler as well.
|
||||||
|
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
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_middle::ty::{ParamEnv, Ty, TyCtxt, Variance};
|
||||||
use rustc_trait_selection::traits::ObligationCtxt;
|
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
|
/// When validating assignments, the variance should be `Covariant`. When checking
|
||||||
/// during `MirPhase` >= `MirPhase::Runtime(RuntimePhase::Initial)` variance should be `Invariant`
|
/// during `MirPhase` >= `MirPhase::Runtime(RuntimePhase::Initial)` variance should be `Invariant`
|
||||||
/// because we want to check for type equality.
|
/// 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>(
|
pub fn relate_types<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ParamEnv<'tcx>,
|
param_env: ParamEnv<'tcx>,
|
||||||
@@ -47,8 +44,7 @@ pub fn relate_types<'tcx>(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut builder =
|
let mut builder = tcx.infer_ctxt().ignoring_regions();
|
||||||
tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(DefiningAnchor::Bubble);
|
|
||||||
let infcx = builder.build();
|
let infcx = builder.build();
|
||||||
let ocx = ObligationCtxt::new(&infcx);
|
let ocx = ObligationCtxt::new(&infcx);
|
||||||
let cause = ObligationCause::dummy();
|
let cause = ObligationCause::dummy();
|
||||||
@@ -58,20 +54,5 @@ pub fn relate_types<'tcx>(
|
|||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
Err(_) => return false,
|
Err(_) => return false,
|
||||||
};
|
};
|
||||||
let errors = ocx.select_all_or_error();
|
ocx.select_all_or_error().is_empty()
|
||||||
// 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()
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2460,6 +2460,7 @@ impl PrimTy {
|
|||||||
Self::Uint(UintTy::Usize),
|
Self::Uint(UintTy::Usize),
|
||||||
Self::Float(FloatTy::F32),
|
Self::Float(FloatTy::F32),
|
||||||
Self::Float(FloatTy::F64),
|
Self::Float(FloatTy::F64),
|
||||||
|
// FIXME(f16_f128): add these when enabled below
|
||||||
Self::Bool,
|
Self::Bool,
|
||||||
Self::Char,
|
Self::Char,
|
||||||
Self::Str,
|
Self::Str,
|
||||||
@@ -2509,6 +2510,10 @@ impl PrimTy {
|
|||||||
sym::usize => Self::Uint(UintTy::Usize),
|
sym::usize => Self::Uint(UintTy::Usize),
|
||||||
sym::f32 => Self::Float(FloatTy::F32),
|
sym::f32 => Self::Float(FloatTy::F32),
|
||||||
sym::f64 => Self::Float(FloatTy::F64),
|
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::bool => Self::Bool,
|
||||||
sym::char => Self::Char,
|
sym::char => Self::Char,
|
||||||
sym::str => Self::Str,
|
sym::str => Self::Str,
|
||||||
|
|||||||
@@ -112,11 +112,15 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
|
|||||||
| sym::likely
|
| sym::likely
|
||||||
| sym::unlikely
|
| sym::unlikely
|
||||||
| sym::ptr_guaranteed_cmp
|
| sym::ptr_guaranteed_cmp
|
||||||
|
| sym::minnumf16
|
||||||
| sym::minnumf32
|
| sym::minnumf32
|
||||||
| sym::minnumf64
|
| sym::minnumf64
|
||||||
|
| sym::minnumf128
|
||||||
|
| sym::maxnumf16
|
||||||
| sym::maxnumf32
|
| sym::maxnumf32
|
||||||
| sym::rustc_peek
|
|
||||||
| sym::maxnumf64
|
| sym::maxnumf64
|
||||||
|
| sym::maxnumf128
|
||||||
|
| sym::rustc_peek
|
||||||
| sym::type_name
|
| sym::type_name
|
||||||
| sym::forget
|
| sym::forget
|
||||||
| sym::black_box
|
| sym::black_box
|
||||||
@@ -302,50 +306,118 @@ pub fn check_intrinsic_type(
|
|||||||
],
|
],
|
||||||
Ty::new_unit(tcx),
|
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::sqrtf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
sym::sqrtf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
|
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::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::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::sinf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
sym::sinf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
|
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::cosf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
sym::cosf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
|
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::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::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::expf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
sym::expf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
|
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::exp2f32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
sym::exp2f64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
|
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::logf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
sym::logf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
|
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::log10f32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
sym::log10f64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
|
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::log2f32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
sym::log2f64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
|
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::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::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::fabsf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
sym::fabsf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
|
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::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::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::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::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::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::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::floorf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
sym::floorf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
|
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::ceilf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
sym::ceilf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
|
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::truncf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
sym::truncf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
|
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::rintf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
sym::rintf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
|
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::nearbyintf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
sym::nearbyintf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
|
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::roundf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
sym::roundf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
|
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::roundevenf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
sym::roundevenf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
|
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 => {
|
sym::volatile_load | sym::unaligned_volatile_load => {
|
||||||
(1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(0))
|
(1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(0))
|
||||||
|
|||||||
@@ -811,6 +811,7 @@ fn test_unstable_options_tracking_hash() {
|
|||||||
tracked!(sanitizer_cfi_canonical_jump_tables, None);
|
tracked!(sanitizer_cfi_canonical_jump_tables, None);
|
||||||
tracked!(sanitizer_cfi_generalize_pointers, Some(true));
|
tracked!(sanitizer_cfi_generalize_pointers, Some(true));
|
||||||
tracked!(sanitizer_cfi_normalize_integers, 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_memory_track_origins, 2);
|
||||||
tracked!(sanitizer_recover, SanitizerSet::ADDRESS);
|
tracked!(sanitizer_recover, SanitizerSet::ADDRESS);
|
||||||
tracked!(saturating_float_casts, Some(true));
|
tracked!(saturating_float_casts, Some(true));
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "llvm/Transforms/Instrumentation.h"
|
#include "llvm/Transforms/Instrumentation.h"
|
||||||
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
|
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
|
||||||
|
#include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h"
|
||||||
#include "llvm/Support/TimeProfiler.h"
|
#include "llvm/Support/TimeProfiler.h"
|
||||||
#if LLVM_VERSION_GE(19, 0)
|
#if LLVM_VERSION_GE(19, 0)
|
||||||
#include "llvm/Support/PGOOptions.h"
|
#include "llvm/Support/PGOOptions.h"
|
||||||
@@ -686,6 +687,9 @@ struct LLVMRustSanitizerOptions {
|
|||||||
bool SanitizeAddress;
|
bool SanitizeAddress;
|
||||||
bool SanitizeAddressRecover;
|
bool SanitizeAddressRecover;
|
||||||
bool SanitizeCFI;
|
bool SanitizeCFI;
|
||||||
|
bool SanitizeDataFlow;
|
||||||
|
char **SanitizeDataFlowABIList;
|
||||||
|
size_t SanitizeDataFlowABIListLen;
|
||||||
bool SanitizeKCFI;
|
bool SanitizeKCFI;
|
||||||
bool SanitizeMemory;
|
bool SanitizeMemory;
|
||||||
bool SanitizeMemoryRecover;
|
bool SanitizeMemoryRecover;
|
||||||
@@ -883,6 +887,18 @@ LLVMRustOptimize(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (SanitizerOptions) {
|
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) {
|
if (SanitizerOptions->SanitizeMemory) {
|
||||||
MemorySanitizerOptions Options(
|
MemorySanitizerOptions Options(
|
||||||
SanitizerOptions->SanitizeMemoryTrackOrigins,
|
SanitizerOptions->SanitizeMemoryTrackOrigins,
|
||||||
|
|||||||
@@ -1991,8 +1991,10 @@ pub fn uint_ty(uty: ast::UintTy) -> UintTy {
|
|||||||
|
|
||||||
pub fn float_ty(fty: ast::FloatTy) -> FloatTy {
|
pub fn float_ty(fty: ast::FloatTy) -> FloatTy {
|
||||||
match fty {
|
match fty {
|
||||||
|
ast::FloatTy::F16 => FloatTy::F16,
|
||||||
ast::FloatTy::F32 => FloatTy::F32,
|
ast::FloatTy::F32 => FloatTy::F32,
|
||||||
ast::FloatTy::F64 => FloatTy::F64,
|
ast::FloatTy::F64 => FloatTy::F64,
|
||||||
|
ast::FloatTy::F128 => FloatTy::F128,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -701,7 +701,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
self.bind_pattern(
|
self.bind_pattern(
|
||||||
self.source_info(irrefutable_pat.span),
|
self.source_info(irrefutable_pat.span),
|
||||||
candidate,
|
candidate,
|
||||||
&fake_borrow_temps,
|
fake_borrow_temps.as_slice(),
|
||||||
irrefutable_pat.span,
|
irrefutable_pat.span,
|
||||||
None,
|
None,
|
||||||
false,
|
false,
|
||||||
@@ -1938,7 +1938,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
let post_guard_block = self.bind_pattern(
|
let post_guard_block = self.bind_pattern(
|
||||||
self.source_info(pat.span),
|
self.source_info(pat.span),
|
||||||
guard_candidate,
|
guard_candidate,
|
||||||
&fake_borrow_temps,
|
fake_borrow_temps.as_slice(),
|
||||||
expr_span,
|
expr_span,
|
||||||
None,
|
None,
|
||||||
false,
|
false,
|
||||||
@@ -2425,7 +2425,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
let matching = this.bind_pattern(
|
let matching = this.bind_pattern(
|
||||||
this.source_info(pattern.span),
|
this.source_info(pattern.span),
|
||||||
candidate,
|
candidate,
|
||||||
&fake_borrow_temps,
|
fake_borrow_temps.as_slice(),
|
||||||
initializer_span,
|
initializer_span,
|
||||||
None,
|
None,
|
||||||
true,
|
true,
|
||||||
@@ -2434,7 +2434,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
let failure = this.bind_pattern(
|
let failure = this.bind_pattern(
|
||||||
this.source_info(else_block_span),
|
this.source_info(else_block_span),
|
||||||
wildcard,
|
wildcard,
|
||||||
&fake_borrow_temps,
|
fake_borrow_temps.as_slice(),
|
||||||
initializer_span,
|
initializer_span,
|
||||||
None,
|
None,
|
||||||
true,
|
true,
|
||||||
|
|||||||
@@ -41,24 +41,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
// let y = x;
|
// let y = x;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// We can't just reverse the binding order, because we must preserve pattern-order
|
// We therefore lower bindings from left-to-right, except we lower the `x` in `x @ pat`
|
||||||
// otherwise, e.g. in `let (Some(a), Some(b)) = (x, y)`. Our rule then is: deepest-first,
|
// after any bindings in `pat`. This doesn't work for or-patterns: the current structure of
|
||||||
// and bindings at the same depth stay in source order.
|
// match lowering forces us to lower bindings inside or-patterns last.
|
||||||
//
|
|
||||||
// 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) {
|
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 TestCase::Irrefutable { binding, ascription } = match_pair.test_case {
|
||||||
if let Some(binding) = binding {
|
if let Some(binding) = binding {
|
||||||
candidate_bindings.push(binding);
|
candidate_bindings.push(binding);
|
||||||
@@ -66,35 +57,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
if let Some(ascription) = ascription {
|
if let Some(ascription) = ascription {
|
||||||
candidate_ascriptions.push(ascription);
|
candidate_ascriptions.push(ascription);
|
||||||
}
|
}
|
||||||
// Simplifiable pattern; we replace it with its subpairs and simplify further.
|
// Simplifiable pattern; we replace it with its already simplified subpairs.
|
||||||
match_pairs.append(&mut match_pair.subpairs);
|
match_pairs.append(&mut match_pair.subpairs);
|
||||||
} else {
|
} else {
|
||||||
// Unsimplifiable pattern; we recursively simplify its subpairs and don't
|
// Unsimplifiable pattern; we keep it.
|
||||||
// process it further.
|
match_pairs.push(match_pair);
|
||||||
self.simplify_match_pairs(
|
|
||||||
&mut match_pair.subpairs,
|
|
||||||
candidate_bindings,
|
|
||||||
candidate_ascriptions,
|
|
||||||
);
|
|
||||||
simplified_match_pairs.push(match_pair);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
// Move or-patterns to the end, because they can result in us
|
||||||
// creating additional candidates, so we want to test them as
|
// creating additional candidates, so we want to test them as
|
||||||
// late as possible.
|
// late as possible.
|
||||||
|
|||||||
@@ -371,7 +371,8 @@ mod desc {
|
|||||||
pub const parse_list: &str = "a space-separated list of strings";
|
pub const parse_list: &str = "a space-separated list of strings";
|
||||||
pub const parse_list_with_polarity: &str =
|
pub const parse_list_with_polarity: &str =
|
||||||
"a comma-separated list of strings, with elements beginning with + or -";
|
"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_number: &str = "a number";
|
||||||
pub const parse_opt_number: &str = parse_number;
|
pub const parse_opt_number: &str = parse_number;
|
||||||
pub const parse_threads: &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_opt_panic_strategy: &str = parse_panic_strategy;
|
||||||
pub const parse_oom_strategy: &str = "either `panic` or `abort`";
|
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_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_sanitizer_memory_track_origins: &str = "0, 1, or 2";
|
||||||
pub const parse_cfguard: &str =
|
pub const parse_cfguard: &str =
|
||||||
"either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`";
|
"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 {
|
pub(crate) fn parse_opt_comma_list(slot: &mut Option<Vec<String>>, v: Option<&str>) -> bool {
|
||||||
match v {
|
match v {
|
||||||
Some(s) => {
|
Some(s) => {
|
||||||
@@ -718,6 +731,7 @@ mod parse {
|
|||||||
*slot |= match s {
|
*slot |= match s {
|
||||||
"address" => SanitizerSet::ADDRESS,
|
"address" => SanitizerSet::ADDRESS,
|
||||||
"cfi" => SanitizerSet::CFI,
|
"cfi" => SanitizerSet::CFI,
|
||||||
|
"dataflow" => SanitizerSet::DATAFLOW,
|
||||||
"kcfi" => SanitizerSet::KCFI,
|
"kcfi" => SanitizerSet::KCFI,
|
||||||
"kernel-address" => SanitizerSet::KERNELADDRESS,
|
"kernel-address" => SanitizerSet::KERNELADDRESS,
|
||||||
"leak" => SanitizerSet::LEAK,
|
"leak" => SanitizerSet::LEAK,
|
||||||
@@ -1846,6 +1860,8 @@ written to standard error output)"),
|
|||||||
"enable generalizing pointer types (default: no)"),
|
"enable generalizing pointer types (default: no)"),
|
||||||
sanitizer_cfi_normalize_integers: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
sanitizer_cfi_normalize_integers: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||||
"enable normalizing integer types (default: no)"),
|
"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],
|
sanitizer_memory_track_origins: usize = (0, parse_sanitizer_memory_track_origins, [TRACKED],
|
||||||
"enable origins tracking in MemorySanitizer"),
|
"enable origins tracking in MemorySanitizer"),
|
||||||
sanitizer_recover: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED],
|
sanitizer_recover: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED],
|
||||||
|
|||||||
@@ -490,6 +490,8 @@ symbols! {
|
|||||||
catch_unwind,
|
catch_unwind,
|
||||||
cause,
|
cause,
|
||||||
cdylib,
|
cdylib,
|
||||||
|
ceilf128,
|
||||||
|
ceilf16,
|
||||||
ceilf32,
|
ceilf32,
|
||||||
ceilf64,
|
ceilf64,
|
||||||
cfg,
|
cfg,
|
||||||
@@ -595,6 +597,8 @@ symbols! {
|
|||||||
copy,
|
copy,
|
||||||
copy_closures,
|
copy_closures,
|
||||||
copy_nonoverlapping,
|
copy_nonoverlapping,
|
||||||
|
copysignf128,
|
||||||
|
copysignf16,
|
||||||
copysignf32,
|
copysignf32,
|
||||||
copysignf64,
|
copysignf64,
|
||||||
core,
|
core,
|
||||||
@@ -607,6 +611,8 @@ symbols! {
|
|||||||
coroutine_resume,
|
coroutine_resume,
|
||||||
coroutine_state,
|
coroutine_state,
|
||||||
coroutines,
|
coroutines,
|
||||||
|
cosf128,
|
||||||
|
cosf16,
|
||||||
cosf32,
|
cosf32,
|
||||||
cosf64,
|
cosf64,
|
||||||
count,
|
count,
|
||||||
@@ -737,10 +743,14 @@ symbols! {
|
|||||||
exhaustive_integer_patterns,
|
exhaustive_integer_patterns,
|
||||||
exhaustive_patterns,
|
exhaustive_patterns,
|
||||||
existential_type,
|
existential_type,
|
||||||
|
exp2f128,
|
||||||
|
exp2f16,
|
||||||
exp2f32,
|
exp2f32,
|
||||||
exp2f64,
|
exp2f64,
|
||||||
expect,
|
expect,
|
||||||
expected,
|
expected,
|
||||||
|
expf128,
|
||||||
|
expf16,
|
||||||
expf32,
|
expf32,
|
||||||
expf64,
|
expf64,
|
||||||
explicit_generic_args_with_impl_trait,
|
explicit_generic_args_with_impl_trait,
|
||||||
@@ -759,7 +769,9 @@ symbols! {
|
|||||||
external_doc,
|
external_doc,
|
||||||
f,
|
f,
|
||||||
f128,
|
f128,
|
||||||
|
f128_nan,
|
||||||
f16,
|
f16,
|
||||||
|
f16_nan,
|
||||||
f16c_target_feature,
|
f16c_target_feature,
|
||||||
f32,
|
f32,
|
||||||
f32_legacy_const_digits,
|
f32_legacy_const_digits,
|
||||||
@@ -793,6 +805,8 @@ symbols! {
|
|||||||
f64_legacy_const_neg_infinity,
|
f64_legacy_const_neg_infinity,
|
||||||
f64_legacy_const_radix,
|
f64_legacy_const_radix,
|
||||||
f64_nan,
|
f64_nan,
|
||||||
|
fabsf128,
|
||||||
|
fabsf16,
|
||||||
fabsf32,
|
fabsf32,
|
||||||
fabsf64,
|
fabsf64,
|
||||||
fadd_algebraic,
|
fadd_algebraic,
|
||||||
@@ -813,8 +827,12 @@ symbols! {
|
|||||||
file,
|
file,
|
||||||
float,
|
float,
|
||||||
float_to_int_unchecked,
|
float_to_int_unchecked,
|
||||||
|
floorf128,
|
||||||
|
floorf16,
|
||||||
floorf32,
|
floorf32,
|
||||||
floorf64,
|
floorf64,
|
||||||
|
fmaf128,
|
||||||
|
fmaf16,
|
||||||
fmaf32,
|
fmaf32,
|
||||||
fmaf64,
|
fmaf64,
|
||||||
fmt,
|
fmt,
|
||||||
@@ -1030,11 +1048,17 @@ symbols! {
|
|||||||
loaded_from_disk,
|
loaded_from_disk,
|
||||||
local,
|
local,
|
||||||
local_inner_macros,
|
local_inner_macros,
|
||||||
|
log10f128,
|
||||||
|
log10f16,
|
||||||
log10f32,
|
log10f32,
|
||||||
log10f64,
|
log10f64,
|
||||||
|
log2f128,
|
||||||
|
log2f16,
|
||||||
log2f32,
|
log2f32,
|
||||||
log2f64,
|
log2f64,
|
||||||
log_syntax,
|
log_syntax,
|
||||||
|
logf128,
|
||||||
|
logf16,
|
||||||
logf32,
|
logf32,
|
||||||
logf64,
|
logf64,
|
||||||
loongarch_target_feature,
|
loongarch_target_feature,
|
||||||
@@ -1062,6 +1086,8 @@ symbols! {
|
|||||||
match_beginning_vert,
|
match_beginning_vert,
|
||||||
match_default_bindings,
|
match_default_bindings,
|
||||||
matches_macro,
|
matches_macro,
|
||||||
|
maxnumf128,
|
||||||
|
maxnumf16,
|
||||||
maxnumf32,
|
maxnumf32,
|
||||||
maxnumf64,
|
maxnumf64,
|
||||||
may_dangle,
|
may_dangle,
|
||||||
@@ -1093,6 +1119,8 @@ symbols! {
|
|||||||
min_exhaustive_patterns,
|
min_exhaustive_patterns,
|
||||||
min_specialization,
|
min_specialization,
|
||||||
min_type_alias_impl_trait,
|
min_type_alias_impl_trait,
|
||||||
|
minnumf128,
|
||||||
|
minnumf16,
|
||||||
minnumf32,
|
minnumf32,
|
||||||
minnumf64,
|
minnumf64,
|
||||||
mips_target_feature,
|
mips_target_feature,
|
||||||
@@ -1155,6 +1183,8 @@ symbols! {
|
|||||||
native_link_modifiers_whole_archive,
|
native_link_modifiers_whole_archive,
|
||||||
natvis_file,
|
natvis_file,
|
||||||
ne,
|
ne,
|
||||||
|
nearbyintf128,
|
||||||
|
nearbyintf16,
|
||||||
nearbyintf32,
|
nearbyintf32,
|
||||||
nearbyintf64,
|
nearbyintf64,
|
||||||
needs_allocator,
|
needs_allocator,
|
||||||
@@ -1289,8 +1319,12 @@ symbols! {
|
|||||||
poll_next,
|
poll_next,
|
||||||
post_dash_lto: "post-lto",
|
post_dash_lto: "post-lto",
|
||||||
powerpc_target_feature,
|
powerpc_target_feature,
|
||||||
|
powf128,
|
||||||
|
powf16,
|
||||||
powf32,
|
powf32,
|
||||||
powf64,
|
powf64,
|
||||||
|
powif128,
|
||||||
|
powif16,
|
||||||
powif32,
|
powif32,
|
||||||
powif64,
|
powif64,
|
||||||
pre_dash_lto: "pre-lto",
|
pre_dash_lto: "pre-lto",
|
||||||
@@ -1416,6 +1450,8 @@ symbols! {
|
|||||||
return_position_impl_trait_in_trait,
|
return_position_impl_trait_in_trait,
|
||||||
return_type_notation,
|
return_type_notation,
|
||||||
rhs,
|
rhs,
|
||||||
|
rintf128,
|
||||||
|
rintf16,
|
||||||
rintf32,
|
rintf32,
|
||||||
rintf64,
|
rintf64,
|
||||||
riscv_target_feature,
|
riscv_target_feature,
|
||||||
@@ -1424,8 +1460,12 @@ symbols! {
|
|||||||
ropi_rwpi: "ropi-rwpi",
|
ropi_rwpi: "ropi-rwpi",
|
||||||
rotate_left,
|
rotate_left,
|
||||||
rotate_right,
|
rotate_right,
|
||||||
|
roundevenf128,
|
||||||
|
roundevenf16,
|
||||||
roundevenf32,
|
roundevenf32,
|
||||||
roundevenf64,
|
roundevenf64,
|
||||||
|
roundf128,
|
||||||
|
roundf16,
|
||||||
roundf32,
|
roundf32,
|
||||||
roundf64,
|
roundf64,
|
||||||
rt,
|
rt,
|
||||||
@@ -1630,6 +1670,8 @@ symbols! {
|
|||||||
simd_trunc,
|
simd_trunc,
|
||||||
simd_xor,
|
simd_xor,
|
||||||
since,
|
since,
|
||||||
|
sinf128,
|
||||||
|
sinf16,
|
||||||
sinf32,
|
sinf32,
|
||||||
sinf64,
|
sinf64,
|
||||||
size,
|
size,
|
||||||
@@ -1647,6 +1689,8 @@ symbols! {
|
|||||||
specialization,
|
specialization,
|
||||||
speed,
|
speed,
|
||||||
spotlight,
|
spotlight,
|
||||||
|
sqrtf128,
|
||||||
|
sqrtf16,
|
||||||
sqrtf32,
|
sqrtf32,
|
||||||
sqrtf64,
|
sqrtf64,
|
||||||
sreg,
|
sreg,
|
||||||
@@ -1746,6 +1790,8 @@ symbols! {
|
|||||||
transparent_enums,
|
transparent_enums,
|
||||||
transparent_unions,
|
transparent_unions,
|
||||||
trivial_bounds,
|
trivial_bounds,
|
||||||
|
truncf128,
|
||||||
|
truncf16,
|
||||||
truncf32,
|
truncf32,
|
||||||
truncf64,
|
truncf64,
|
||||||
try_blocks,
|
try_blocks,
|
||||||
|
|||||||
@@ -464,16 +464,17 @@ fn encode_ty<'tcx>(
|
|||||||
typeid.push_str(&s);
|
typeid.push_str(&s);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rust's f32 and f64 single (32-bit) and double (64-bit) precision floating-point types
|
// Rust's f16, f32, f64, and f126 half (16-bit), single (32-bit), double (64-bit), and
|
||||||
// have IEEE-754 binary32 and binary64 floating-point layouts, respectively.
|
// 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.)
|
// (See https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#fixed-width-floating-point-types.)
|
||||||
ty::Float(float_ty) => {
|
ty::Float(float_ty) => {
|
||||||
typeid.push(match float_ty {
|
typeid.push_str(match float_ty {
|
||||||
FloatTy::F16 => unimplemented!("f16_f128"),
|
FloatTy::F16 => "Dh",
|
||||||
FloatTy::F32 => 'f',
|
FloatTy::F32 => "f",
|
||||||
FloatTy::F64 => 'd',
|
FloatTy::F64 => "d",
|
||||||
FloatTy::F128 => unimplemented!("f16_f128"),
|
FloatTy::F128 => "g",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -557,7 +558,7 @@ fn encode_ty<'tcx>(
|
|||||||
// https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-compression).
|
// https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-compression).
|
||||||
let builtin_types = [
|
let builtin_types = [
|
||||||
"v", "w", "b", "c", "a", "h", "s", "t", "i", "j", "l", "m", "x", "y",
|
"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) {
|
if !builtin_types.contains(&str) {
|
||||||
compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
|
compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
|
||||||
|
|||||||
@@ -320,8 +320,11 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
|||||||
ty::Uint(UintTy::U64) => "y",
|
ty::Uint(UintTy::U64) => "y",
|
||||||
ty::Uint(UintTy::U128) => "o",
|
ty::Uint(UintTy::U128) => "o",
|
||||||
ty::Uint(UintTy::Usize) => "j",
|
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::F32) => "f",
|
||||||
ty::Float(FloatTy::F64) => "d",
|
ty::Float(FloatTy::F64) => "d",
|
||||||
|
ty::Float(FloatTy::F128) => unimplemented!("f16_f128"),
|
||||||
ty::Never => "z",
|
ty::Never => "z",
|
||||||
|
|
||||||
// Placeholders (should be demangled as `_`).
|
// Placeholders (should be demangled as `_`).
|
||||||
|
|||||||
@@ -1221,6 +1221,7 @@ bitflags::bitflags! {
|
|||||||
const KCFI = 1 << 8;
|
const KCFI = 1 << 8;
|
||||||
const KERNELADDRESS = 1 << 9;
|
const KERNELADDRESS = 1 << 9;
|
||||||
const SAFESTACK = 1 << 10;
|
const SAFESTACK = 1 << 10;
|
||||||
|
const DATAFLOW = 1 << 11;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rustc_data_structures::external_bitflags_debug! { SanitizerSet }
|
rustc_data_structures::external_bitflags_debug! { SanitizerSet }
|
||||||
@@ -1233,6 +1234,7 @@ impl SanitizerSet {
|
|||||||
Some(match self {
|
Some(match self {
|
||||||
SanitizerSet::ADDRESS => "address",
|
SanitizerSet::ADDRESS => "address",
|
||||||
SanitizerSet::CFI => "cfi",
|
SanitizerSet::CFI => "cfi",
|
||||||
|
SanitizerSet::DATAFLOW => "dataflow",
|
||||||
SanitizerSet::KCFI => "kcfi",
|
SanitizerSet::KCFI => "kcfi",
|
||||||
SanitizerSet::KERNELADDRESS => "kernel-address",
|
SanitizerSet::KERNELADDRESS => "kernel-address",
|
||||||
SanitizerSet::LEAK => "leak",
|
SanitizerSet::LEAK => "leak",
|
||||||
@@ -2790,6 +2792,7 @@ impl Target {
|
|||||||
base.$key_name |= match s.as_str() {
|
base.$key_name |= match s.as_str() {
|
||||||
Some("address") => SanitizerSet::ADDRESS,
|
Some("address") => SanitizerSet::ADDRESS,
|
||||||
Some("cfi") => SanitizerSet::CFI,
|
Some("cfi") => SanitizerSet::CFI,
|
||||||
|
Some("dataflow") => SanitizerSet::DATAFLOW,
|
||||||
Some("kcfi") => SanitizerSet::KCFI,
|
Some("kcfi") => SanitizerSet::KCFI,
|
||||||
Some("kernel-address") => SanitizerSet::KERNELADDRESS,
|
Some("kernel-address") => SanitizerSet::KERNELADDRESS,
|
||||||
Some("leak") => SanitizerSet::LEAK,
|
Some("leak") => SanitizerSet::LEAK,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ pub fn target() -> Target {
|
|||||||
base.static_position_independent_executables = true;
|
base.static_position_independent_executables = true;
|
||||||
base.supported_sanitizers = SanitizerSet::ADDRESS
|
base.supported_sanitizers = SanitizerSet::ADDRESS
|
||||||
| SanitizerSet::CFI
|
| SanitizerSet::CFI
|
||||||
|
| SanitizerSet::DATAFLOW
|
||||||
| SanitizerSet::LEAK
|
| SanitizerSet::LEAK
|
||||||
| SanitizerSet::MEMORY
|
| SanitizerSet::MEMORY
|
||||||
| SanitizerSet::SAFESTACK
|
| SanitizerSet::SAFESTACK
|
||||||
|
|||||||
@@ -136,6 +136,15 @@ impl<W: Wake + Send + Sync + 'static> From<Arc<W>> for RawWaker {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn raw_waker<W: Wake + Send + Sync + 'static>(waker: Arc<W>) -> RawWaker {
|
fn raw_waker<W: Wake + Send + Sync + 'static>(waker: Arc<W>) -> RawWaker {
|
||||||
// Increment the reference count of the arc to clone it.
|
// Increment the reference count of the arc to clone it.
|
||||||
|
//
|
||||||
|
// The #[inline(always)] is to ensure that raw_waker and clone_waker are
|
||||||
|
// always generated in the same code generation unit as one another, and
|
||||||
|
// therefore that the structurally identical const-promoted RawWakerVTable
|
||||||
|
// within both functions is deduplicated at LLVM IR code generation time.
|
||||||
|
// This allows optimizing Waker::will_wake to a single pointer comparison of
|
||||||
|
// the vtable pointers, rather than comparing all four function pointers
|
||||||
|
// within the vtables.
|
||||||
|
#[inline(always)]
|
||||||
unsafe fn clone_waker<W: Wake + Send + Sync + 'static>(waker: *const ()) -> RawWaker {
|
unsafe fn clone_waker<W: Wake + Send + Sync + 'static>(waker: *const ()) -> RawWaker {
|
||||||
unsafe { Arc::increment_strong_count(waker as *const W) };
|
unsafe { Arc::increment_strong_count(waker as *const W) };
|
||||||
RawWaker::new(
|
RawWaker::new(
|
||||||
@@ -304,6 +313,10 @@ impl<W: LocalWake + 'static> From<Rc<W>> for RawWaker {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn local_raw_waker<W: LocalWake + 'static>(waker: Rc<W>) -> RawWaker {
|
fn local_raw_waker<W: LocalWake + 'static>(waker: Rc<W>) -> RawWaker {
|
||||||
// Increment the reference count of the Rc to clone it.
|
// Increment the reference count of the Rc to clone it.
|
||||||
|
//
|
||||||
|
// Refer to the comment on raw_waker's clone_waker regarding why this is
|
||||||
|
// always inline.
|
||||||
|
#[inline(always)]
|
||||||
unsafe fn clone_waker<W: LocalWake + 'static>(waker: *const ()) -> RawWaker {
|
unsafe fn clone_waker<W: LocalWake + 'static>(waker: *const ()) -> RawWaker {
|
||||||
unsafe { Rc::increment_strong_count(waker as *const W) };
|
unsafe { Rc::increment_strong_count(waker as *const W) };
|
||||||
RawWaker::new(
|
RawWaker::new(
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
#![feature(thin_box)]
|
#![feature(thin_box)]
|
||||||
#![feature(strict_provenance)]
|
#![feature(strict_provenance)]
|
||||||
#![feature(drain_keep_rest)]
|
#![feature(drain_keep_rest)]
|
||||||
|
#![feature(local_waker)]
|
||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
#![deny(fuzzy_provenance_casts)]
|
#![deny(fuzzy_provenance_casts)]
|
||||||
#![deny(unsafe_op_in_unsafe_fn)]
|
#![deny(unsafe_op_in_unsafe_fn)]
|
||||||
@@ -62,6 +63,7 @@ mod rc;
|
|||||||
mod slice;
|
mod slice;
|
||||||
mod str;
|
mod str;
|
||||||
mod string;
|
mod string;
|
||||||
|
mod task;
|
||||||
mod thin_box;
|
mod thin_box;
|
||||||
mod vec;
|
mod vec;
|
||||||
mod vec_deque;
|
mod vec_deque;
|
||||||
|
|||||||
34
library/alloc/tests/task.rs
Normal file
34
library/alloc/tests/task.rs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
use alloc::rc::Rc;
|
||||||
|
use alloc::sync::Arc;
|
||||||
|
use alloc::task::{LocalWake, Wake};
|
||||||
|
use core::task::{LocalWaker, Waker};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_waker_will_wake_clone() {
|
||||||
|
struct NoopWaker;
|
||||||
|
|
||||||
|
impl Wake for NoopWaker {
|
||||||
|
fn wake(self: Arc<Self>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let waker = Waker::from(Arc::new(NoopWaker));
|
||||||
|
let clone = waker.clone();
|
||||||
|
|
||||||
|
assert!(waker.will_wake(&clone));
|
||||||
|
assert!(clone.will_wake(&waker));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_local_waker_will_wake_clone() {
|
||||||
|
struct NoopWaker;
|
||||||
|
|
||||||
|
impl LocalWake for NoopWaker {
|
||||||
|
fn wake(self: Rc<Self>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let waker = LocalWaker::from(Rc::new(NoopWaker));
|
||||||
|
let clone = waker.clone();
|
||||||
|
|
||||||
|
assert!(waker.will_wake(&clone));
|
||||||
|
assert!(clone.will_wake(&waker));
|
||||||
|
}
|
||||||
@@ -48,7 +48,7 @@ o("codegen-tests", "rust.codegen-tests", "run the tests/codegen tests")
|
|||||||
o("ninja", "llvm.ninja", "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)")
|
o("ninja", "llvm.ninja", "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)")
|
||||||
o("locked-deps", "build.locked-deps", "force Cargo.lock to be up to date")
|
o("locked-deps", "build.locked-deps", "force Cargo.lock to be up to date")
|
||||||
o("vendor", "build.vendor", "enable usage of vendored Rust crates")
|
o("vendor", "build.vendor", "enable usage of vendored Rust crates")
|
||||||
o("sanitizers", "build.sanitizers", "build the sanitizer runtimes (asan, lsan, msan, tsan, hwasan)")
|
o("sanitizers", "build.sanitizers", "build the sanitizer runtimes (asan, dfsan, lsan, msan, tsan, hwasan)")
|
||||||
o("dist-src", "rust.dist-src", "when building tarballs enables building a source tarball")
|
o("dist-src", "rust.dist-src", "when building tarballs enables building a source tarball")
|
||||||
o("cargo-native-static", "build.cargo-native-static", "static native libraries in cargo")
|
o("cargo-native-static", "build.cargo-native-static", "static native libraries in cargo")
|
||||||
o("profiler", "build.profiler", "build the profiler runtime")
|
o("profiler", "build.profiler", "build the profiler runtime")
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Change this file to make users of the `download-ci-llvm` configuration download
|
Change this file to make users of the `download-ci-llvm` configuration download
|
||||||
a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
|
a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
|
||||||
|
|
||||||
Last change is for: https://github.com/rust-lang/rust/pull/116881
|
Last change is for: https://github.com/rust-lang/rust/pull/120761
|
||||||
|
|||||||
@@ -1088,7 +1088,7 @@ fn supported_sanitizers(
|
|||||||
"x86_64-unknown-illumos" => common_libs("illumos", "x86_64", &["asan"]),
|
"x86_64-unknown-illumos" => common_libs("illumos", "x86_64", &["asan"]),
|
||||||
"x86_64-pc-solaris" => common_libs("solaris", "x86_64", &["asan"]),
|
"x86_64-pc-solaris" => common_libs("solaris", "x86_64", &["asan"]),
|
||||||
"x86_64-unknown-linux-gnu" => {
|
"x86_64-unknown-linux-gnu" => {
|
||||||
common_libs("linux", "x86_64", &["asan", "lsan", "msan", "safestack", "tsan"])
|
common_libs("linux", "x86_64", &["asan", "dfsan", "lsan", "msan", "safestack", "tsan"])
|
||||||
}
|
}
|
||||||
"x86_64-unknown-linux-musl" => {
|
"x86_64-unknown-linux-musl" => {
|
||||||
common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"])
|
common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"])
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ This feature allows for use of one of following sanitizers:
|
|||||||
* Those that apart from testing, may be used in production:
|
* Those that apart from testing, may be used in production:
|
||||||
* [ControlFlowIntegrity](#controlflowintegrity) LLVM Control Flow Integrity
|
* [ControlFlowIntegrity](#controlflowintegrity) LLVM Control Flow Integrity
|
||||||
(CFI) provides forward-edge control flow protection.
|
(CFI) provides forward-edge control flow protection.
|
||||||
|
* [DataFlowSanitizer](#dataflowsanitizer) a generic dynamic data flow analysis
|
||||||
|
framework.
|
||||||
* [KernelControlFlowIntegrity](#kernelcontrolflowintegrity) LLVM Kernel
|
* [KernelControlFlowIntegrity](#kernelcontrolflowintegrity) LLVM Kernel
|
||||||
Control Flow Integrity (KCFI) provides forward-edge control flow protection
|
Control Flow Integrity (KCFI) provides forward-edge control flow protection
|
||||||
for operating systems kernels.
|
for operating systems kernels.
|
||||||
@@ -39,14 +41,21 @@ This feature allows for use of one of following sanitizers:
|
|||||||
* [ShadowCallStack](#shadowcallstack) provides backward-edge control flow
|
* [ShadowCallStack](#shadowcallstack) provides backward-edge control flow
|
||||||
protection (aarch64 only).
|
protection (aarch64 only).
|
||||||
|
|
||||||
To enable a sanitizer compile with `-Zsanitizer=address`,`-Zsanitizer=cfi`,
|
To enable a sanitizer compile with `-Zsanitizer=address`, `-Zsanitizer=cfi`,
|
||||||
`-Zsanitizer=hwaddress`, `-Zsanitizer=leak`, `-Zsanitizer=memory`,
|
`-Zsanitizer=dataflow`,`-Zsanitizer=hwaddress`, `-Zsanitizer=leak`,
|
||||||
`-Zsanitizer=memtag`, `-Zsanitizer=shadow-call-stack`, or `-Zsanitizer=thread`.
|
`-Zsanitizer=memory`, `-Zsanitizer=memtag`, `-Zsanitizer=shadow-call-stack`, or
|
||||||
You might also need the `--target` and `build-std` flags. Example:
|
`-Zsanitizer=thread`. You might also need the `--target` and `build-std` flags.
|
||||||
|
|
||||||
|
Example:
|
||||||
```shell
|
```shell
|
||||||
$ RUSTFLAGS=-Zsanitizer=address cargo build -Zbuild-std --target x86_64-unknown-linux-gnu
|
$ RUSTFLAGS=-Zsanitizer=address cargo build -Zbuild-std --target x86_64-unknown-linux-gnu
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Additional options for sanitizers can be passed to LLVM command line argument
|
||||||
|
processor via LLVM arguments using `llvm-args` codegen option (e.g.,
|
||||||
|
`-Cllvm-args=-dfsan-combine-pointer-labels-on-load=false`). See the sanitizer
|
||||||
|
documentation for more information about additional options.
|
||||||
|
|
||||||
# AddressSanitizer
|
# AddressSanitizer
|
||||||
|
|
||||||
AddressSanitizer is a memory error detector. It can detect the following types
|
AddressSanitizer is a memory error detector. It can detect the following types
|
||||||
@@ -639,6 +648,21 @@ LLVM KCFI is supported on the following targets:
|
|||||||
See the [Clang KernelControlFlowIntegrity documentation][clang-kcfi] for more
|
See the [Clang KernelControlFlowIntegrity documentation][clang-kcfi] for more
|
||||||
details.
|
details.
|
||||||
|
|
||||||
|
# DataFlowSanitizer
|
||||||
|
|
||||||
|
DataFlowSanitizer is a generalised dynamic data flow analysis.
|
||||||
|
|
||||||
|
Unlike other Sanitizer tools, this tool is not designed to detect a specific
|
||||||
|
class of bugs on its own. Instead, it provides a generic dynamic data flow
|
||||||
|
analysis framework to be used by clients to help detect application-specific
|
||||||
|
issues within their own code.
|
||||||
|
|
||||||
|
DataFlowSanitizer is supported on the following targets:
|
||||||
|
|
||||||
|
* `x86_64-unknown-linux-gnu`
|
||||||
|
|
||||||
|
See the [Clang DataFlowSanitizer documentation][clang-dataflow] for more details.
|
||||||
|
|
||||||
# KernelAddressSanitizer
|
# KernelAddressSanitizer
|
||||||
|
|
||||||
KernelAddressSanitizer (KASAN) is a freestanding version of AddressSanitizer
|
KernelAddressSanitizer (KASAN) is a freestanding version of AddressSanitizer
|
||||||
@@ -849,6 +873,7 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT
|
|||||||
* [Sanitizers project page](https://github.com/google/sanitizers/wiki/)
|
* [Sanitizers project page](https://github.com/google/sanitizers/wiki/)
|
||||||
* [AddressSanitizer in Clang][clang-asan]
|
* [AddressSanitizer in Clang][clang-asan]
|
||||||
* [ControlFlowIntegrity in Clang][clang-cfi]
|
* [ControlFlowIntegrity in Clang][clang-cfi]
|
||||||
|
* [DataFlowSanitizer in Clang][clang-dataflow]
|
||||||
* [HWAddressSanitizer in Clang][clang-hwasan]
|
* [HWAddressSanitizer in Clang][clang-hwasan]
|
||||||
* [Linux Kernel's KernelAddressSanitizer documentation][linux-kasan]
|
* [Linux Kernel's KernelAddressSanitizer documentation][linux-kasan]
|
||||||
* [LeakSanitizer in Clang][clang-lsan]
|
* [LeakSanitizer in Clang][clang-lsan]
|
||||||
@@ -858,6 +883,7 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT
|
|||||||
|
|
||||||
[clang-asan]: https://clang.llvm.org/docs/AddressSanitizer.html
|
[clang-asan]: https://clang.llvm.org/docs/AddressSanitizer.html
|
||||||
[clang-cfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html
|
[clang-cfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html
|
||||||
|
[clang-dataflow]: https://clang.llvm.org/docs/DataFlowSanitizer.html
|
||||||
[clang-hwasan]: https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html
|
[clang-hwasan]: https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html
|
||||||
[clang-kcfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html#fsanitize-kcfi
|
[clang-kcfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html#fsanitize-kcfi
|
||||||
[clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html
|
[clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html
|
||||||
|
|||||||
@@ -1777,8 +1777,10 @@ impl PrimitiveType {
|
|||||||
hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
|
hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
|
||||||
hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
|
hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
|
||||||
hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
|
hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
|
||||||
|
hir::PrimTy::Float(FloatTy::F16) => PrimitiveType::F16,
|
||||||
hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
|
hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
|
||||||
hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
|
hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
|
||||||
|
hir::PrimTy::Float(FloatTy::F128) => PrimitiveType::F128,
|
||||||
hir::PrimTy::Str => PrimitiveType::Str,
|
hir::PrimTy::Str => PrimitiveType::Str,
|
||||||
hir::PrimTy::Bool => PrimitiveType::Bool,
|
hir::PrimTy::Bool => PrimitiveType::Bool,
|
||||||
hir::PrimTy::Char => PrimitiveType::Char,
|
hir::PrimTy::Char => PrimitiveType::Char,
|
||||||
@@ -1977,8 +1979,10 @@ impl From<ast::UintTy> for PrimitiveType {
|
|||||||
impl From<ast::FloatTy> for PrimitiveType {
|
impl From<ast::FloatTy> for PrimitiveType {
|
||||||
fn from(float_ty: ast::FloatTy) -> PrimitiveType {
|
fn from(float_ty: ast::FloatTy) -> PrimitiveType {
|
||||||
match float_ty {
|
match float_ty {
|
||||||
|
ast::FloatTy::F16 => PrimitiveType::F16,
|
||||||
ast::FloatTy::F32 => PrimitiveType::F32,
|
ast::FloatTy::F32 => PrimitiveType::F32,
|
||||||
ast::FloatTy::F64 => PrimitiveType::F64,
|
ast::FloatTy::F64 => PrimitiveType::F64,
|
||||||
|
ast::FloatTy::F128 => PrimitiveType::F128,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,9 +75,12 @@ impl ApproxConstant {
|
|||||||
fn check_lit(&self, cx: &LateContext<'_>, lit: &LitKind, e: &Expr<'_>) {
|
fn check_lit(&self, cx: &LateContext<'_>, lit: &LitKind, e: &Expr<'_>) {
|
||||||
match *lit {
|
match *lit {
|
||||||
LitKind::Float(s, LitFloatType::Suffixed(fty)) => match fty {
|
LitKind::Float(s, LitFloatType::Suffixed(fty)) => match fty {
|
||||||
|
FloatTy::F16 => self.check_known_consts(cx, e, s, "f16"),
|
||||||
FloatTy::F32 => self.check_known_consts(cx, e, s, "f32"),
|
FloatTy::F32 => self.check_known_consts(cx, e, s, "f32"),
|
||||||
FloatTy::F64 => self.check_known_consts(cx, e, s, "f64"),
|
FloatTy::F64 => self.check_known_consts(cx, e, s, "f64"),
|
||||||
|
FloatTy::F128 => self.check_known_consts(cx, e, s, "f128"),
|
||||||
},
|
},
|
||||||
|
// FIXME(f16_f128): add `f16` and `f128` when these types become stable.
|
||||||
LitKind::Float(s, LitFloatType::Unsuffixed) => self.check_known_consts(cx, e, s, "f{32, 64}"),
|
LitKind::Float(s, LitFloatType::Unsuffixed) => self.check_known_consts(cx, e, s, "f{32, 64}"),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,8 +76,10 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
|
|||||||
let digits = count_digits(sym_str);
|
let digits = count_digits(sym_str);
|
||||||
let max = max_digits(fty);
|
let max = max_digits(fty);
|
||||||
let type_suffix = match lit_float_ty {
|
let type_suffix = match lit_float_ty {
|
||||||
|
LitFloatType::Suffixed(ast::FloatTy::F16) => Some("f16"),
|
||||||
LitFloatType::Suffixed(ast::FloatTy::F32) => Some("f32"),
|
LitFloatType::Suffixed(ast::FloatTy::F32) => Some("f32"),
|
||||||
LitFloatType::Suffixed(ast::FloatTy::F64) => Some("f64"),
|
LitFloatType::Suffixed(ast::FloatTy::F64) => Some("f64"),
|
||||||
|
LitFloatType::Suffixed(ast::FloatTy::F128) => Some("f128"),
|
||||||
LitFloatType::Unsuffixed => None,
|
LitFloatType::Unsuffixed => None,
|
||||||
};
|
};
|
||||||
let (is_whole, is_inf, mut float_str) = match fty {
|
let (is_whole, is_inf, mut float_str) = match fty {
|
||||||
|
|||||||
@@ -277,12 +277,16 @@ pub fn lit_to_mir_constant<'tcx>(lit: &LitKind, ty: Option<Ty<'tcx>>) -> Constan
|
|||||||
LitKind::Char(c) => Constant::Char(c),
|
LitKind::Char(c) => Constant::Char(c),
|
||||||
LitKind::Int(n, _) => Constant::Int(n.get()),
|
LitKind::Int(n, _) => Constant::Int(n.get()),
|
||||||
LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty {
|
LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty {
|
||||||
|
ast::FloatTy::F16 => unimplemented!("f16_f128"),
|
||||||
ast::FloatTy::F32 => Constant::F32(is.as_str().parse().unwrap()),
|
ast::FloatTy::F32 => Constant::F32(is.as_str().parse().unwrap()),
|
||||||
ast::FloatTy::F64 => Constant::F64(is.as_str().parse().unwrap()),
|
ast::FloatTy::F64 => Constant::F64(is.as_str().parse().unwrap()),
|
||||||
|
ast::FloatTy::F128 => unimplemented!("f16_f128"),
|
||||||
},
|
},
|
||||||
LitKind::Float(ref is, LitFloatType::Unsuffixed) => match ty.expect("type of float is known").kind() {
|
LitKind::Float(ref is, LitFloatType::Unsuffixed) => match ty.expect("type of float is known").kind() {
|
||||||
|
ty::Float(FloatTy::F16) => unimplemented!("f16_f128"),
|
||||||
ty::Float(FloatTy::F32) => Constant::F32(is.as_str().parse().unwrap()),
|
ty::Float(FloatTy::F32) => Constant::F32(is.as_str().parse().unwrap()),
|
||||||
ty::Float(FloatTy::F64) => Constant::F64(is.as_str().parse().unwrap()),
|
ty::Float(FloatTy::F64) => Constant::F64(is.as_str().parse().unwrap()),
|
||||||
|
ty::Float(FloatTy::F128) => unimplemented!("f16_f128"),
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
},
|
},
|
||||||
LitKind::Bool(b) => Constant::Bool(b),
|
LitKind::Bool(b) => Constant::Bool(b),
|
||||||
|
|||||||
@@ -156,6 +156,7 @@ impl PanicStrategy {
|
|||||||
pub enum Sanitizer {
|
pub enum Sanitizer {
|
||||||
Address,
|
Address,
|
||||||
Cfi,
|
Cfi,
|
||||||
|
Dataflow,
|
||||||
Kcfi,
|
Kcfi,
|
||||||
KernelAddress,
|
KernelAddress,
|
||||||
Leak,
|
Leak,
|
||||||
|
|||||||
@@ -29,6 +29,11 @@ pub(super) fn handle_needs(
|
|||||||
condition: cache.sanitizer_cfi,
|
condition: cache.sanitizer_cfi,
|
||||||
ignore_reason: "ignored on targets without CFI sanitizer",
|
ignore_reason: "ignored on targets without CFI sanitizer",
|
||||||
},
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-sanitizer-dataflow",
|
||||||
|
condition: cache.sanitizer_dataflow,
|
||||||
|
ignore_reason: "ignored on targets without dataflow sanitizer",
|
||||||
|
},
|
||||||
Need {
|
Need {
|
||||||
name: "needs-sanitizer-kcfi",
|
name: "needs-sanitizer-kcfi",
|
||||||
condition: cache.sanitizer_kcfi,
|
condition: cache.sanitizer_kcfi,
|
||||||
@@ -190,6 +195,7 @@ pub(super) struct CachedNeedsConditions {
|
|||||||
sanitizer_support: bool,
|
sanitizer_support: bool,
|
||||||
sanitizer_address: bool,
|
sanitizer_address: bool,
|
||||||
sanitizer_cfi: bool,
|
sanitizer_cfi: bool,
|
||||||
|
sanitizer_dataflow: bool,
|
||||||
sanitizer_kcfi: bool,
|
sanitizer_kcfi: bool,
|
||||||
sanitizer_kasan: bool,
|
sanitizer_kasan: bool,
|
||||||
sanitizer_leak: bool,
|
sanitizer_leak: bool,
|
||||||
@@ -229,6 +235,7 @@ impl CachedNeedsConditions {
|
|||||||
sanitizer_support: std::env::var_os("RUSTC_SANITIZER_SUPPORT").is_some(),
|
sanitizer_support: std::env::var_os("RUSTC_SANITIZER_SUPPORT").is_some(),
|
||||||
sanitizer_address: sanitizers.contains(&Sanitizer::Address),
|
sanitizer_address: sanitizers.contains(&Sanitizer::Address),
|
||||||
sanitizer_cfi: sanitizers.contains(&Sanitizer::Cfi),
|
sanitizer_cfi: sanitizers.contains(&Sanitizer::Cfi),
|
||||||
|
sanitizer_dataflow: sanitizers.contains(&Sanitizer::Dataflow),
|
||||||
sanitizer_kcfi: sanitizers.contains(&Sanitizer::Kcfi),
|
sanitizer_kcfi: sanitizers.contains(&Sanitizer::Kcfi),
|
||||||
sanitizer_kasan: sanitizers.contains(&Sanitizer::KernelAddress),
|
sanitizer_kasan: sanitizers.contains(&Sanitizer::KernelAddress),
|
||||||
sanitizer_leak: sanitizers.contains(&Sanitizer::Leak),
|
sanitizer_leak: sanitizers.contains(&Sanitizer::Leak),
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ const EXTENSION_EXCEPTION_PATHS: &[&str] = &[
|
|||||||
"tests/ui/macros/syntax-extension-source-utils-files/includeme.fragment", // more include
|
"tests/ui/macros/syntax-extension-source-utils-files/includeme.fragment", // more include
|
||||||
"tests/ui/proc-macro/auxiliary/included-file.txt", // more include
|
"tests/ui/proc-macro/auxiliary/included-file.txt", // more include
|
||||||
"tests/ui/invalid/foo.natvis.xml", // sample debugger visualizer
|
"tests/ui/invalid/foo.natvis.xml", // sample debugger visualizer
|
||||||
|
"tests/ui/sanitizer/dataflow-abilist.txt", // dataflow sanitizer ABI list file
|
||||||
"tests/ui/shell-argfiles/shell-argfiles.args", // passing args via a file
|
"tests/ui/shell-argfiles/shell-argfiles.args", // passing args via a file
|
||||||
"tests/ui/shell-argfiles/shell-argfiles-badquotes.args", // passing args via a file
|
"tests/ui/shell-argfiles/shell-argfiles-badquotes.args", // passing args via a file
|
||||||
"tests/ui/shell-argfiles/shell-argfiles-via-argfile-shell.args", // passing args via a file
|
"tests/ui/shell-argfiles/shell-argfiles-via-argfile-shell.args", // passing args via a file
|
||||||
|
|||||||
10
tests/codegen/sanitizer/dataflow-instrument-functions.rs
Normal file
10
tests/codegen/sanitizer/dataflow-instrument-functions.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// Verifies that functions are instrumented.
|
||||||
|
//
|
||||||
|
//@ needs-sanitizer-dataflow
|
||||||
|
//@ compile-flags: -Copt-level=0 -Zsanitizer=dataflow
|
||||||
|
|
||||||
|
#![crate_type="lib"]
|
||||||
|
|
||||||
|
pub fn foo() {
|
||||||
|
}
|
||||||
|
// CHECK: define{{.*}}foo{{.*}}.dfsan
|
||||||
@@ -51,13 +51,13 @@
|
|||||||
- }
|
- }
|
||||||
-
|
-
|
||||||
- bb3: {
|
- bb3: {
|
||||||
StorageLive(_9);
|
|
||||||
_9 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
|
|
||||||
StorageLive(_8);
|
StorageLive(_8);
|
||||||
_8 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
|
_8 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
|
||||||
|
StorageLive(_9);
|
||||||
|
_9 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
|
||||||
_0 = const 0_u32;
|
_0 = const 0_u32;
|
||||||
StorageDead(_8);
|
|
||||||
StorageDead(_9);
|
StorageDead(_9);
|
||||||
|
StorageDead(_8);
|
||||||
- goto -> bb4;
|
- goto -> bb4;
|
||||||
+ goto -> bb3;
|
+ goto -> bb3;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,13 +57,13 @@
|
|||||||
- }
|
- }
|
||||||
-
|
-
|
||||||
- bb4: {
|
- bb4: {
|
||||||
StorageLive(_10);
|
|
||||||
_10 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
|
|
||||||
StorageLive(_9);
|
StorageLive(_9);
|
||||||
_9 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
|
_9 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
|
||||||
|
StorageLive(_10);
|
||||||
|
_10 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
|
||||||
_0 = const 0_u32;
|
_0 = const 0_u32;
|
||||||
StorageDead(_9);
|
|
||||||
StorageDead(_10);
|
StorageDead(_10);
|
||||||
|
StorageDead(_9);
|
||||||
- goto -> bb6;
|
- goto -> bb6;
|
||||||
+ goto -> bb4;
|
+ goto -> bb4;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,13 +51,13 @@
|
|||||||
- }
|
- }
|
||||||
-
|
-
|
||||||
- bb3: {
|
- bb3: {
|
||||||
StorageLive(_9);
|
|
||||||
_9 = (((_3.1: std::option::Option<bool>) as Some).0: bool);
|
|
||||||
StorageLive(_8);
|
StorageLive(_8);
|
||||||
_8 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
|
_8 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
|
||||||
|
StorageLive(_9);
|
||||||
|
_9 = (((_3.1: std::option::Option<bool>) as Some).0: bool);
|
||||||
_0 = const 0_u32;
|
_0 = const 0_u32;
|
||||||
StorageDead(_8);
|
|
||||||
StorageDead(_9);
|
StorageDead(_9);
|
||||||
|
StorageDead(_8);
|
||||||
- goto -> bb4;
|
- goto -> bb4;
|
||||||
+ goto -> bb3;
|
+ goto -> bb3;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,16 +69,16 @@
|
|||||||
|
|
||||||
- bb4: {
|
- bb4: {
|
||||||
+ bb3: {
|
+ bb3: {
|
||||||
StorageLive(_13);
|
|
||||||
_13 = (((_4.2: std::option::Option<u32>) as Some).0: u32);
|
|
||||||
StorageLive(_12);
|
|
||||||
_12 = (((_4.1: std::option::Option<u32>) as Some).0: u32);
|
|
||||||
StorageLive(_11);
|
StorageLive(_11);
|
||||||
_11 = (((_4.0: std::option::Option<u32>) as Some).0: u32);
|
_11 = (((_4.0: std::option::Option<u32>) as Some).0: u32);
|
||||||
|
StorageLive(_12);
|
||||||
|
_12 = (((_4.1: std::option::Option<u32>) as Some).0: u32);
|
||||||
|
StorageLive(_13);
|
||||||
|
_13 = (((_4.2: std::option::Option<u32>) as Some).0: u32);
|
||||||
_0 = const 0_u32;
|
_0 = const 0_u32;
|
||||||
StorageDead(_11);
|
|
||||||
StorageDead(_12);
|
|
||||||
StorageDead(_13);
|
StorageDead(_13);
|
||||||
|
StorageDead(_12);
|
||||||
|
StorageDead(_11);
|
||||||
- goto -> bb5;
|
- goto -> bb5;
|
||||||
+ goto -> bb4;
|
+ goto -> bb4;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,12 +116,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
bb6: {
|
bb6: {
|
||||||
StorageLive(_13);
|
|
||||||
_39 = deref_copy (_4.1: &ViewportPercentageLength);
|
|
||||||
_13 = (((*_39) as Vw).0: f32);
|
|
||||||
StorageLive(_12);
|
StorageLive(_12);
|
||||||
_40 = deref_copy (_4.0: &ViewportPercentageLength);
|
_39 = deref_copy (_4.0: &ViewportPercentageLength);
|
||||||
_12 = (((*_40) as Vw).0: f32);
|
_12 = (((*_39) as Vw).0: f32);
|
||||||
|
StorageLive(_13);
|
||||||
|
_40 = deref_copy (_4.1: &ViewportPercentageLength);
|
||||||
|
_13 = (((*_40) as Vw).0: f32);
|
||||||
StorageLive(_14);
|
StorageLive(_14);
|
||||||
StorageLive(_15);
|
StorageLive(_15);
|
||||||
_15 = _12;
|
_15 = _12;
|
||||||
@@ -132,18 +132,18 @@
|
|||||||
StorageDead(_15);
|
StorageDead(_15);
|
||||||
_3 = ViewportPercentageLength::Vw(move _14);
|
_3 = ViewportPercentageLength::Vw(move _14);
|
||||||
StorageDead(_14);
|
StorageDead(_14);
|
||||||
StorageDead(_12);
|
|
||||||
StorageDead(_13);
|
StorageDead(_13);
|
||||||
|
StorageDead(_12);
|
||||||
goto -> bb10;
|
goto -> bb10;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb7: {
|
bb7: {
|
||||||
StorageLive(_18);
|
|
||||||
_41 = deref_copy (_4.1: &ViewportPercentageLength);
|
|
||||||
_18 = (((*_41) as Vh).0: f32);
|
|
||||||
StorageLive(_17);
|
StorageLive(_17);
|
||||||
_42 = deref_copy (_4.0: &ViewportPercentageLength);
|
_41 = deref_copy (_4.0: &ViewportPercentageLength);
|
||||||
_17 = (((*_42) as Vh).0: f32);
|
_17 = (((*_41) as Vh).0: f32);
|
||||||
|
StorageLive(_18);
|
||||||
|
_42 = deref_copy (_4.1: &ViewportPercentageLength);
|
||||||
|
_18 = (((*_42) as Vh).0: f32);
|
||||||
StorageLive(_19);
|
StorageLive(_19);
|
||||||
StorageLive(_20);
|
StorageLive(_20);
|
||||||
_20 = _17;
|
_20 = _17;
|
||||||
@@ -154,18 +154,18 @@
|
|||||||
StorageDead(_20);
|
StorageDead(_20);
|
||||||
_3 = ViewportPercentageLength::Vh(move _19);
|
_3 = ViewportPercentageLength::Vh(move _19);
|
||||||
StorageDead(_19);
|
StorageDead(_19);
|
||||||
StorageDead(_17);
|
|
||||||
StorageDead(_18);
|
StorageDead(_18);
|
||||||
|
StorageDead(_17);
|
||||||
goto -> bb10;
|
goto -> bb10;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb8: {
|
bb8: {
|
||||||
StorageLive(_23);
|
|
||||||
_43 = deref_copy (_4.1: &ViewportPercentageLength);
|
|
||||||
_23 = (((*_43) as Vmin).0: f32);
|
|
||||||
StorageLive(_22);
|
StorageLive(_22);
|
||||||
_44 = deref_copy (_4.0: &ViewportPercentageLength);
|
_43 = deref_copy (_4.0: &ViewportPercentageLength);
|
||||||
_22 = (((*_44) as Vmin).0: f32);
|
_22 = (((*_43) as Vmin).0: f32);
|
||||||
|
StorageLive(_23);
|
||||||
|
_44 = deref_copy (_4.1: &ViewportPercentageLength);
|
||||||
|
_23 = (((*_44) as Vmin).0: f32);
|
||||||
StorageLive(_24);
|
StorageLive(_24);
|
||||||
StorageLive(_25);
|
StorageLive(_25);
|
||||||
_25 = _22;
|
_25 = _22;
|
||||||
@@ -176,18 +176,18 @@
|
|||||||
StorageDead(_25);
|
StorageDead(_25);
|
||||||
_3 = ViewportPercentageLength::Vmin(move _24);
|
_3 = ViewportPercentageLength::Vmin(move _24);
|
||||||
StorageDead(_24);
|
StorageDead(_24);
|
||||||
StorageDead(_22);
|
|
||||||
StorageDead(_23);
|
StorageDead(_23);
|
||||||
|
StorageDead(_22);
|
||||||
goto -> bb10;
|
goto -> bb10;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb9: {
|
bb9: {
|
||||||
StorageLive(_28);
|
|
||||||
_45 = deref_copy (_4.1: &ViewportPercentageLength);
|
|
||||||
_28 = (((*_45) as Vmax).0: f32);
|
|
||||||
StorageLive(_27);
|
StorageLive(_27);
|
||||||
_46 = deref_copy (_4.0: &ViewportPercentageLength);
|
_45 = deref_copy (_4.0: &ViewportPercentageLength);
|
||||||
_27 = (((*_46) as Vmax).0: f32);
|
_27 = (((*_45) as Vmax).0: f32);
|
||||||
|
StorageLive(_28);
|
||||||
|
_46 = deref_copy (_4.1: &ViewportPercentageLength);
|
||||||
|
_28 = (((*_46) as Vmax).0: f32);
|
||||||
StorageLive(_29);
|
StorageLive(_29);
|
||||||
StorageLive(_30);
|
StorageLive(_30);
|
||||||
_30 = _27;
|
_30 = _27;
|
||||||
@@ -198,8 +198,8 @@
|
|||||||
StorageDead(_30);
|
StorageDead(_30);
|
||||||
_3 = ViewportPercentageLength::Vmax(move _29);
|
_3 = ViewportPercentageLength::Vmax(move _29);
|
||||||
StorageDead(_29);
|
StorageDead(_29);
|
||||||
StorageDead(_27);
|
|
||||||
StorageDead(_28);
|
StorageDead(_28);
|
||||||
|
StorageDead(_27);
|
||||||
goto -> bb10;
|
goto -> bb10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,13 +59,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
bb5: {
|
bb5: {
|
||||||
StorageLive(_10);
|
|
||||||
_10 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
|
|
||||||
StorageLive(_9);
|
StorageLive(_9);
|
||||||
_9 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
|
_9 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
|
||||||
|
StorageLive(_10);
|
||||||
|
_10 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
|
||||||
_0 = const 0_u32;
|
_0 = const 0_u32;
|
||||||
StorageDead(_9);
|
|
||||||
StorageDead(_10);
|
StorageDead(_10);
|
||||||
|
StorageDead(_9);
|
||||||
goto -> bb8;
|
goto -> bb8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,7 @@ fn match_tuple(_1: (u32, bool, Option<i32>, u32)) -> u32 {
|
|||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
PlaceMention(_1);
|
PlaceMention(_1);
|
||||||
_2 = discriminant((_1.2: std::option::Option<i32>));
|
switchInt((_1.0: u32)) -> [1: bb2, 4: bb2, otherwise: bb1];
|
||||||
switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
@@ -29,11 +28,12 @@ fn match_tuple(_1: (u32, bool, Option<i32>, u32)) -> u32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bb2: {
|
bb2: {
|
||||||
switchInt((((_1.2: std::option::Option<i32>) as Some).0: i32)) -> [1: bb3, 8: bb3, otherwise: bb1];
|
_2 = discriminant((_1.2: std::option::Option<i32>));
|
||||||
|
switchInt(move _2) -> [0: bb4, 1: bb3, otherwise: bb1];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb3: {
|
bb3: {
|
||||||
switchInt((_1.0: u32)) -> [1: bb4, 4: bb4, otherwise: bb1];
|
switchInt((((_1.2: std::option::Option<i32>) as Some).0: i32)) -> [1: bb4, 8: bb4, otherwise: bb1];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
|||||||
LL | sanitize = "_UNEXPECTED_VALUE",
|
LL | sanitize = "_UNEXPECTED_VALUE",
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: expected values for `sanitize` are: `address`, `cfi`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, `thread`
|
= note: expected values for `sanitize` are: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, `thread`
|
||||||
= note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
|
= note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
|
||||||
|
|
||||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
error[E0282]: type annotations needed
|
error[E0282]: type annotations needed
|
||||||
--> $DIR/hidden-type-is-opaque-2.rs:8:17
|
--> $DIR/hidden-type-is-opaque-2.rs:10:17
|
||||||
|
|
|
|
||||||
LL | Thunk::new(|mut cont| {
|
LL | Thunk::new(|mut cont| {
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
@@ -13,7 +13,7 @@ LL | Thunk::new(|mut cont: /* Type */| {
|
|||||||
| ++++++++++++
|
| ++++++++++++
|
||||||
|
|
||||||
error[E0282]: type annotations needed
|
error[E0282]: type annotations needed
|
||||||
--> $DIR/hidden-type-is-opaque-2.rs:18:17
|
--> $DIR/hidden-type-is-opaque-2.rs:20:17
|
||||||
|
|
|
|
||||||
LL | Thunk::new(|mut cont| {
|
LL | Thunk::new(|mut cont| {
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
31
tests/ui/impl-trait/hidden-type-is-opaque-2.next.stderr
Normal file
31
tests/ui/impl-trait/hidden-type-is-opaque-2.next.stderr
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
error[E0282]: type annotations needed
|
||||||
|
--> $DIR/hidden-type-is-opaque-2.rs:10:17
|
||||||
|
|
|
||||||
|
LL | Thunk::new(|mut cont| {
|
||||||
|
| ^^^^^^^^
|
||||||
|
LL |
|
||||||
|
LL | cont.reify_as();
|
||||||
|
| ---- type must be known at this point
|
||||||
|
|
|
||||||
|
help: consider giving this closure parameter an explicit type
|
||||||
|
|
|
||||||
|
LL | Thunk::new(|mut cont: /* Type */| {
|
||||||
|
| ++++++++++++
|
||||||
|
|
||||||
|
error[E0282]: type annotations needed
|
||||||
|
--> $DIR/hidden-type-is-opaque-2.rs:20:17
|
||||||
|
|
|
||||||
|
LL | Thunk::new(|mut cont| {
|
||||||
|
| ^^^^^^^^
|
||||||
|
LL |
|
||||||
|
LL | cont.reify_as();
|
||||||
|
| ---- type must be known at this point
|
||||||
|
|
|
||||||
|
help: consider giving this closure parameter an explicit type
|
||||||
|
|
|
||||||
|
LL | Thunk::new(|mut cont: /* Type */| {
|
||||||
|
| ++++++++++++
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0282`.
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
// This doesn't work, because we don't flow information from opaque types
|
// This doesn't work, because we don't flow information from opaque types
|
||||||
// into function arguments via the function's generic parameters
|
// into function arguments via the function's generic parameters
|
||||||
// FIXME(oli-obk): make `expected_inputs_for_expected_output` support this
|
// FIXME(oli-obk): make `expected_inputs_for_expected_output` support this
|
||||||
|
//@ revisions: default next
|
||||||
|
//@[next] compile-flags: -Znext-solver
|
||||||
|
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
|||||||
17
tests/ui/pattern/bindings-after-at/bind-by-copy-or-pat.rs
Normal file
17
tests/ui/pattern/bindings-after-at/bind-by-copy-or-pat.rs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
//@ known-bug: unknown
|
||||||
|
#![allow(unused)]
|
||||||
|
|
||||||
|
struct A(u32);
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
// The or-pattern bindings are lowered after `x`, which triggers the error.
|
||||||
|
let x @ (A(a) | A(a)) = A(10);
|
||||||
|
// ERROR: use of moved value
|
||||||
|
assert!(x.0 == 10);
|
||||||
|
assert!(a == 10);
|
||||||
|
|
||||||
|
// This works.
|
||||||
|
let (x @ A(a) | x @ A(a)) = A(10);
|
||||||
|
assert!(x.0 == 10);
|
||||||
|
assert!(a == 10);
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
error[E0382]: use of moved value
|
||||||
|
--> $DIR/bind-by-copy-or-pat.rs:8:16
|
||||||
|
|
|
||||||
|
LL | let x @ (A(a) | A(a)) = A(10);
|
||||||
|
| - ^ ----- move occurs because value has type `A`, which does not implement the `Copy` trait
|
||||||
|
| | |
|
||||||
|
| | value used here after move
|
||||||
|
| value moved here
|
||||||
|
|
|
||||||
|
help: borrow this binding in the pattern to avoid moving the value
|
||||||
|
|
|
||||||
|
LL | let ref x @ (A(a) | A(a)) = A(10);
|
||||||
|
| +++
|
||||||
|
|
||||||
|
error[E0382]: use of moved value
|
||||||
|
--> $DIR/bind-by-copy-or-pat.rs:8:23
|
||||||
|
|
|
||||||
|
LL | let x @ (A(a) | A(a)) = A(10);
|
||||||
|
| - ^ ----- move occurs because value has type `A`, which does not implement the `Copy` trait
|
||||||
|
| | |
|
||||||
|
| | value used here after move
|
||||||
|
| value moved here
|
||||||
|
|
|
||||||
|
help: borrow this binding in the pattern to avoid moving the value
|
||||||
|
|
|
||||||
|
LL | let ref x @ (A(a) | A(a)) = A(10);
|
||||||
|
| +++
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0382`.
|
||||||
505
tests/ui/sanitizer/dataflow-abilist.txt
Normal file
505
tests/ui/sanitizer/dataflow-abilist.txt
Normal file
@@ -0,0 +1,505 @@
|
|||||||
|
fun:main=uninstrumented
|
||||||
|
fun:main=discard
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# DFSan interface functions
|
||||||
|
###############################################################################
|
||||||
|
fun:dfsan_union=uninstrumented
|
||||||
|
fun:dfsan_union=discard
|
||||||
|
fun:dfsan_create_label=uninstrumented
|
||||||
|
fun:dfsan_create_label=discard
|
||||||
|
fun:dfsan_set_label=uninstrumented
|
||||||
|
fun:dfsan_set_label=discard
|
||||||
|
fun:dfsan_add_label=uninstrumented
|
||||||
|
fun:dfsan_add_label=discard
|
||||||
|
fun:dfsan_get_label=uninstrumented
|
||||||
|
fun:dfsan_get_label=custom
|
||||||
|
fun:dfsan_read_label=uninstrumented
|
||||||
|
fun:dfsan_read_label=discard
|
||||||
|
fun:dfsan_get_label_count=uninstrumented
|
||||||
|
fun:dfsan_get_label_count=discard
|
||||||
|
fun:dfsan_get_label_info=uninstrumented
|
||||||
|
fun:dfsan_get_label_info=discard
|
||||||
|
fun:dfsan_has_label=uninstrumented
|
||||||
|
fun:dfsan_has_label=discard
|
||||||
|
fun:dfsan_has_label_with_desc=uninstrumented
|
||||||
|
fun:dfsan_has_label_with_desc=discard
|
||||||
|
fun:dfsan_set_write_callback=uninstrumented
|
||||||
|
fun:dfsan_set_write_callback=custom
|
||||||
|
fun:dfsan_flush=uninstrumented
|
||||||
|
fun:dfsan_flush=discard
|
||||||
|
fun:dfsan_print_origin_trace=uninstrumented
|
||||||
|
fun:dfsan_print_origin_trace=discard
|
||||||
|
fun:dfsan_print_origin_id_trace=uninstrumented
|
||||||
|
fun:dfsan_print_origin_id_trace=discard
|
||||||
|
fun:dfsan_sprint_origin_trace=uninstrumented
|
||||||
|
fun:dfsan_sprint_origin_trace=discard
|
||||||
|
fun:dfsan_sprint_origin_id_trace=uninstrumented
|
||||||
|
fun:dfsan_sprint_origin_id_trace=discard
|
||||||
|
fun:dfsan_sprint_stack_trace=uninstrumented
|
||||||
|
fun:dfsan_sprint_stack_trace=discard
|
||||||
|
fun:dfsan_get_origin=uninstrumented
|
||||||
|
fun:dfsan_get_origin=custom
|
||||||
|
fun:dfsan_read_origin_of_first_taint=uninstrumented
|
||||||
|
fun:dfsan_read_origin_of_first_taint=discard
|
||||||
|
fun:dfsan_get_init_origin=uninstrumented
|
||||||
|
fun:dfsan_get_init_origin=discard
|
||||||
|
fun:dfsan_get_track_origins=uninstrumented
|
||||||
|
fun:dfsan_get_track_origins=discard
|
||||||
|
fun:dfsan_set_conditional_callback=uninstrumented
|
||||||
|
fun:dfsan_set_conditional_callback=discard
|
||||||
|
fun:dfsan_get_labels_in_signal_conditional=uninstrumented
|
||||||
|
fun:dfsan_get_labels_in_signal_conditional=discard
|
||||||
|
fun:dfsan_set_reaches_function_callback=uninstrumented
|
||||||
|
fun:dfsan_set_reaches_function_callback=discard
|
||||||
|
fun:dfsan_get_labels_in_signal_reaches_function=uninstrumented
|
||||||
|
fun:dfsan_get_labels_in_signal_reaches_function=discard
|
||||||
|
fun:dfsan_reaches_function_callback=uninstrumented
|
||||||
|
fun:dfsan_reaches_function_callback=discard
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# glibc
|
||||||
|
###############################################################################
|
||||||
|
# Functions of memory allocators
|
||||||
|
fun:__libc_memalign=discard
|
||||||
|
fun:aligned_alloc=discard
|
||||||
|
fun:calloc=discard
|
||||||
|
fun:cfree=discard
|
||||||
|
fun:mallinfo=discard
|
||||||
|
fun:malloc=discard
|
||||||
|
fun:free=discard
|
||||||
|
fun:malloc_stats=discard
|
||||||
|
fun:malloc_usable_size=discard
|
||||||
|
fun:mallopt=discard
|
||||||
|
fun:memalign=discard
|
||||||
|
fun:posix_memalign=discard
|
||||||
|
fun:pvalloc=discard
|
||||||
|
fun:realloc=discard
|
||||||
|
fun:reallocarray=discard
|
||||||
|
fun:valloc=discard
|
||||||
|
|
||||||
|
# Functions that return a value that depends on the input, but the output might
|
||||||
|
# not be necessarily data-dependent on the input.
|
||||||
|
fun:isalpha=functional
|
||||||
|
fun:isdigit=functional
|
||||||
|
fun:isprint=functional
|
||||||
|
fun:isxdigit=functional
|
||||||
|
fun:isalnum=functional
|
||||||
|
fun:ispunct=functional
|
||||||
|
fun:isspace=functional
|
||||||
|
fun:tolower=functional
|
||||||
|
fun:_tolower=functional
|
||||||
|
fun:toupper=functional
|
||||||
|
|
||||||
|
# Functions that return a value that is data-dependent on the input.
|
||||||
|
fun:__isinf=functional
|
||||||
|
fun:__isinff=functional
|
||||||
|
fun:__signbit=functional
|
||||||
|
fun:__signbitf=functional
|
||||||
|
fun:__signbitl=functional
|
||||||
|
fun:btowc=functional
|
||||||
|
fun:exp=functional
|
||||||
|
fun:exp2=functional
|
||||||
|
fun:expf=functional
|
||||||
|
fun:expl=functional
|
||||||
|
fun:fabs=functional
|
||||||
|
fun:finite=functional
|
||||||
|
fun:finitef=functional
|
||||||
|
fun:finitel=functional
|
||||||
|
fun:floor=functional
|
||||||
|
fun:fmod=functional
|
||||||
|
fun:isinf=functional
|
||||||
|
fun:isinff=functional
|
||||||
|
fun:isinfl=functional
|
||||||
|
fun:isnan=functional
|
||||||
|
fun:isnanf=functional
|
||||||
|
fun:isnanl=functional
|
||||||
|
fun:log=functional
|
||||||
|
fun:log1p=functional
|
||||||
|
fun:log1pf=functional
|
||||||
|
fun:log1pl=functional
|
||||||
|
fun:log2=functional
|
||||||
|
fun:log2f=functional
|
||||||
|
fun:log2l=functional
|
||||||
|
fun:modf=functional
|
||||||
|
fun:nextafter=functional
|
||||||
|
fun:nextafterf=functional
|
||||||
|
fun:nextafterl=functional
|
||||||
|
fun:nexttoward=functional
|
||||||
|
fun:nexttowardf=functional
|
||||||
|
fun:nexttowardl=functional
|
||||||
|
fun:pow=functional
|
||||||
|
fun:powf=functional
|
||||||
|
fun:powl=functional
|
||||||
|
fun:round=functional
|
||||||
|
fun:sqrt=functional
|
||||||
|
fun:sqrtf=functional
|
||||||
|
fun:sqrtl=functional
|
||||||
|
fun:wctob=functional
|
||||||
|
|
||||||
|
# Functions that produce an output that does not depend on the input (shadow is
|
||||||
|
# zeroed automatically).
|
||||||
|
fun:__assert_fail=discard
|
||||||
|
fun:__cmsg_nxthdr=discard
|
||||||
|
fun:__ctype_b_loc=discard
|
||||||
|
fun:__cxa_atexit=discard
|
||||||
|
fun:__errno_location=discard
|
||||||
|
fun:__newlocale=discard
|
||||||
|
fun:__sbrk=discard
|
||||||
|
fun:__sigsetjmp=discard
|
||||||
|
fun:__uselocale=discard
|
||||||
|
fun:__wctype_l=discard
|
||||||
|
fun:access=discard
|
||||||
|
fun:alarm=discard
|
||||||
|
fun:atexit=discard
|
||||||
|
fun:bind=discard
|
||||||
|
fun:chdir=discard
|
||||||
|
fun:close=discard
|
||||||
|
fun:closedir=discard
|
||||||
|
fun:connect=discard
|
||||||
|
fun:creat=discard
|
||||||
|
fun:dladdr=discard
|
||||||
|
fun:dlclose=discard
|
||||||
|
fun:epoll_create=discard
|
||||||
|
fun:epoll_create1=discard
|
||||||
|
fun:epoll_ctl=discard
|
||||||
|
fun:fclose=discard
|
||||||
|
fun:feof=discard
|
||||||
|
fun:ferror=discard
|
||||||
|
fun:fflush=discard
|
||||||
|
fun:fileno=discard
|
||||||
|
fun:fopen=discard
|
||||||
|
fun:fprintf=discard
|
||||||
|
fun:fputc=discard
|
||||||
|
fun:fputc=discard
|
||||||
|
fun:fputs=discard
|
||||||
|
fun:fputs=discard
|
||||||
|
fun:fseek=discard
|
||||||
|
fun:ftell=discard
|
||||||
|
fun:fwrite=discard
|
||||||
|
fun:getenv=discard
|
||||||
|
fun:getuid=discard
|
||||||
|
fun:geteuid=discard
|
||||||
|
fun:getpagesize=discard
|
||||||
|
fun:getpid=discard
|
||||||
|
fun:kill=discard
|
||||||
|
fun:listen=discard
|
||||||
|
fun:lseek=discard
|
||||||
|
fun:mkdir=discard
|
||||||
|
fun:mmap=discard
|
||||||
|
fun:munmap=discard
|
||||||
|
fun:open=discard
|
||||||
|
fun:openat=discard
|
||||||
|
fun:pipe=discard
|
||||||
|
fun:posix_fadvise=discard
|
||||||
|
fun:prctl=discard
|
||||||
|
fun:printf=discard
|
||||||
|
fun:pthread_sigmask=discard
|
||||||
|
fun:putc=discard
|
||||||
|
fun:putchar=discard
|
||||||
|
fun:puts=discard
|
||||||
|
fun:rand=discard
|
||||||
|
fun:random=discard
|
||||||
|
fun:remove=discard
|
||||||
|
fun:sched_getcpu=discard
|
||||||
|
fun:sched_get_priority_max=discard
|
||||||
|
fun:sched_setaffinity=discard
|
||||||
|
fun:sched_yield=discard
|
||||||
|
fun:sem_destroy=discard
|
||||||
|
fun:sem_init=discard
|
||||||
|
fun:sem_post=discard
|
||||||
|
fun:sem_wait=discard
|
||||||
|
fun:send=discard
|
||||||
|
fun:sendmsg=discard
|
||||||
|
fun:sendto=discard
|
||||||
|
fun:setsockopt=discard
|
||||||
|
fun:shutdown=discard
|
||||||
|
fun:sleep=discard
|
||||||
|
fun:socket=discard
|
||||||
|
fun:strerror=discard
|
||||||
|
fun:strspn=discard
|
||||||
|
fun:strcspn=discard
|
||||||
|
fun:symlink=discard
|
||||||
|
fun:syscall=discard
|
||||||
|
fun:unlink=discard
|
||||||
|
fun:uselocale=discard
|
||||||
|
fun:vfprintf=discard
|
||||||
|
|
||||||
|
# Functions that produce output does not depend on the input (need to zero the
|
||||||
|
# shadow manually).
|
||||||
|
fun:_dl_get_tls_static_info=custom
|
||||||
|
fun:clock_gettime=custom
|
||||||
|
fun:dlopen=custom
|
||||||
|
fun:epoll_wait=custom
|
||||||
|
fun:fgets=custom
|
||||||
|
fun:fstat=custom
|
||||||
|
fun:getcwd=custom
|
||||||
|
fun:get_current_dir_name=custom
|
||||||
|
fun:getentropy=custom
|
||||||
|
fun:gethostname=custom
|
||||||
|
fun:getpeername=custom
|
||||||
|
fun:getrlimit=custom
|
||||||
|
fun:getrusage=custom
|
||||||
|
fun:getsockname=custom
|
||||||
|
fun:getsockopt=custom
|
||||||
|
fun:nanosleep=custom
|
||||||
|
fun:pread=custom
|
||||||
|
fun:read=custom
|
||||||
|
fun:recvmmsg=custom
|
||||||
|
fun:recvmsg=custom
|
||||||
|
fun:sigaltstack=custom
|
||||||
|
fun:socketpair=custom
|
||||||
|
fun:stat=custom
|
||||||
|
fun:time=custom
|
||||||
|
|
||||||
|
# Functions that produce an output that depend on the input (propagate the
|
||||||
|
# shadow manually).
|
||||||
|
fun:ctime_r=custom
|
||||||
|
fun:inet_pton=custom
|
||||||
|
fun:localtime_r=custom
|
||||||
|
fun:memcpy=custom
|
||||||
|
fun:memmove=custom
|
||||||
|
fun:memset=custom
|
||||||
|
fun:strcpy=custom
|
||||||
|
fun:strdup=custom
|
||||||
|
fun:strncpy=custom
|
||||||
|
fun:strtod=custom
|
||||||
|
fun:strtol=custom
|
||||||
|
fun:strtoll=custom
|
||||||
|
fun:strtoul=custom
|
||||||
|
fun:strtoull=custom
|
||||||
|
fun:strcat=custom
|
||||||
|
fun:strncat=custom
|
||||||
|
fun:__isoc23_strtod=custom
|
||||||
|
fun:__isoc23_strtol=custom
|
||||||
|
fun:__isoc23_strtoll=custom
|
||||||
|
fun:__isoc23_strtoul=custom
|
||||||
|
fun:__isoc23_strtoull=custom
|
||||||
|
|
||||||
|
# Functions that produce an output that is computed from the input, but is not
|
||||||
|
# necessarily data dependent.
|
||||||
|
fun:bcmp=custom
|
||||||
|
fun:memchr=custom
|
||||||
|
fun:memcmp=custom
|
||||||
|
fun:strcasecmp=custom
|
||||||
|
fun:strchr=custom
|
||||||
|
fun:strcmp=custom
|
||||||
|
fun:strlen=custom
|
||||||
|
fun:strnlen=custom
|
||||||
|
fun:strncasecmp=custom
|
||||||
|
fun:strncmp=custom
|
||||||
|
fun:strpbrk=custom
|
||||||
|
fun:strrchr=custom
|
||||||
|
fun:strstr=custom
|
||||||
|
fun:strsep=custom
|
||||||
|
|
||||||
|
# Functions which take action based on global state, such as running a callback
|
||||||
|
# set by a separate function.
|
||||||
|
fun:write=custom
|
||||||
|
|
||||||
|
# Functions that take a callback (wrap the callback manually).
|
||||||
|
fun:dl_iterate_phdr=custom
|
||||||
|
|
||||||
|
fun:getpwuid_r=custom
|
||||||
|
fun:poll=custom
|
||||||
|
fun:sched_getaffinity=custom
|
||||||
|
fun:select=custom
|
||||||
|
fun:sigemptyset=custom
|
||||||
|
fun:sigaction=custom
|
||||||
|
fun:signal=custom
|
||||||
|
fun:gettimeofday=custom
|
||||||
|
|
||||||
|
# sprintf-like
|
||||||
|
fun:sprintf=custom
|
||||||
|
fun:snprintf=custom
|
||||||
|
|
||||||
|
# scanf-like
|
||||||
|
fun:sscanf=custom
|
||||||
|
fun:__isoc99_sscanf=custom
|
||||||
|
fun:__isoc23_sscanf=custom
|
||||||
|
|
||||||
|
# TODO: custom
|
||||||
|
fun:asprintf=discard
|
||||||
|
fun:qsort=discard
|
||||||
|
|
||||||
|
# fork
|
||||||
|
fun:fork=custom
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# pthread
|
||||||
|
###############################################################################
|
||||||
|
fun:__pthread_register_cancel=discard
|
||||||
|
fun:__pthread_unregister_cancel=discard
|
||||||
|
fun:pthread_attr_destroy=discard
|
||||||
|
fun:pthread_attr_getaffinity_np=discard
|
||||||
|
fun:pthread_attr_getdetachstate=discard
|
||||||
|
fun:pthread_attr_getguardsize=discard
|
||||||
|
fun:pthread_attr_getinheritsched=discard
|
||||||
|
fun:pthread_attr_getschedparam=discard
|
||||||
|
fun:pthread_attr_getschedpolicy=discard
|
||||||
|
fun:pthread_attr_getscope=discard
|
||||||
|
fun:pthread_attr_getstack=discard
|
||||||
|
fun:pthread_attr_getstackaddr=disacrd
|
||||||
|
fun:pthread_attr_getstacksize=discard
|
||||||
|
fun:pthread_attr_init=discard
|
||||||
|
fun:pthread_attr_setaffinity_np=discard
|
||||||
|
fun:pthread_attr_setdetachstate=discard
|
||||||
|
fun:pthread_attr_setguardsize=discard
|
||||||
|
fun:pthread_attr_setinheritsched=discard
|
||||||
|
fun:pthread_attr_setschedparam=discard
|
||||||
|
fun:pthread_attr_setschedpolicy=discard
|
||||||
|
fun:pthread_attr_setscope=discard
|
||||||
|
fun:pthread_attr_setstack=discard
|
||||||
|
fun:pthread_attr_setstackaddr=discard
|
||||||
|
fun:pthread_attr_setstacksize=discard
|
||||||
|
fun:pthread_equal=discard
|
||||||
|
fun:pthread_getschedparam=discard
|
||||||
|
fun:pthread_getspecific=discard
|
||||||
|
fun:pthread_key_create=discard
|
||||||
|
fun:pthread_key_delete=discard
|
||||||
|
fun:pthread_mutex_destroy=discard
|
||||||
|
fun:pthread_mutex_init=discard
|
||||||
|
fun:pthread_mutex_lock=discard
|
||||||
|
fun:pthread_mutex_trylock=discard
|
||||||
|
fun:pthread_mutex_unlock=discard
|
||||||
|
fun:pthread_mutexattr_destroy=discard
|
||||||
|
fun:pthread_mutexattr_init=discard
|
||||||
|
fun:pthread_mutexattr_settype=discard
|
||||||
|
fun:pthread_rwlock_destroy=discard
|
||||||
|
fun:pthread_rwlock_init=discard
|
||||||
|
fun:pthread_rwlock_rdlock=discard
|
||||||
|
fun:pthread_rwlock_timedrdlock=discard
|
||||||
|
fun:pthread_rwlock_timedwrlock=discard
|
||||||
|
fun:pthread_rwlock_tryrdlock=discard
|
||||||
|
fun:pthread_rwlock_trywrlock=discard
|
||||||
|
fun:pthread_rwlock_wrlock=discard
|
||||||
|
fun:pthread_rwlock_unlock=discard
|
||||||
|
fun:pthread_setschedparam=discard
|
||||||
|
fun:pthread_setname_np=discard
|
||||||
|
fun:pthread_once=discard
|
||||||
|
fun:pthread_self=discard
|
||||||
|
fun:pthread_setspecific=discard
|
||||||
|
|
||||||
|
# Functions that take a callback (wrap the callback manually).
|
||||||
|
fun:pthread_create=custom
|
||||||
|
|
||||||
|
# Functions that produce output does not depend on the input (need to zero the
|
||||||
|
# shadow manually).
|
||||||
|
fun:pthread_join=custom
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# libffi/libgo
|
||||||
|
###############################################################################
|
||||||
|
# Functions that are written in asm or are called from asm.
|
||||||
|
fun:ffi_call_unix64=uninstrumented
|
||||||
|
fun:ffi_call_unix64=discard
|
||||||
|
fun:ffi_closure_unix64_inner=uninstrumented
|
||||||
|
fun:ffi_closure_unix64_inner=discard
|
||||||
|
fun:ffi_closure_unix64=uninstrumented
|
||||||
|
fun:ffi_closure_unix64=discard
|
||||||
|
fun:__go_get_closure=uninstrumented
|
||||||
|
fun:__go_get_closure=discard
|
||||||
|
fun:__go_makefunc_can_recover=uninstrumented
|
||||||
|
fun:__go_makefunc_can_recover=discard
|
||||||
|
fun:__go_makefunc_returning=uninstrumented
|
||||||
|
fun:__go_makefunc_returning=discard
|
||||||
|
fun:reflect.MakeFuncStubGo=uninstrumented
|
||||||
|
fun:reflect.MakeFuncStubGo=discard
|
||||||
|
fun:reflect.makeFuncStub=uninstrumented
|
||||||
|
fun:reflect.makeFuncStub=discard
|
||||||
|
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# lib/Fuzzer
|
||||||
|
###############################################################################
|
||||||
|
# Replaces __sanitizer_cov_trace_cmp with __dfsw___sanitizer_cov_trace_cmp
|
||||||
|
fun:__sanitizer_cov_trace_cmp1=custom
|
||||||
|
fun:__sanitizer_cov_trace_cmp1=uninstrumented
|
||||||
|
fun:__sanitizer_cov_trace_cmp2=custom
|
||||||
|
fun:__sanitizer_cov_trace_cmp2=uninstrumented
|
||||||
|
fun:__sanitizer_cov_trace_cmp4=custom
|
||||||
|
fun:__sanitizer_cov_trace_cmp4=uninstrumented
|
||||||
|
fun:__sanitizer_cov_trace_cmp8=custom
|
||||||
|
fun:__sanitizer_cov_trace_cmp8=uninstrumented
|
||||||
|
fun:__sanitizer_cov_trace_const_cmp1=custom
|
||||||
|
fun:__sanitizer_cov_trace_const_cmp1=uninstrumented
|
||||||
|
fun:__sanitizer_cov_trace_const_cmp2=custom
|
||||||
|
fun:__sanitizer_cov_trace_const_cmp2=uninstrumented
|
||||||
|
fun:__sanitizer_cov_trace_const_cmp4=custom
|
||||||
|
fun:__sanitizer_cov_trace_const_cmp4=uninstrumented
|
||||||
|
fun:__sanitizer_cov_trace_const_cmp8=custom
|
||||||
|
fun:__sanitizer_cov_trace_const_cmp8=uninstrumented
|
||||||
|
# Similar for __sanitizer_cov_trace_switch
|
||||||
|
fun:__sanitizer_cov_trace_switch=custom
|
||||||
|
fun:__sanitizer_cov_trace_switch=uninstrumented
|
||||||
|
|
||||||
|
# Ignores all other __sanitizer callbacks.
|
||||||
|
fun:__sanitizer_cov=uninstrumented
|
||||||
|
fun:__sanitizer_cov=discard
|
||||||
|
fun:__sanitizer_cov_module_init=uninstrumented
|
||||||
|
fun:__sanitizer_cov_module_init=discard
|
||||||
|
fun:__sanitizer_cov_with_check=uninstrumented
|
||||||
|
fun:__sanitizer_cov_with_check=discard
|
||||||
|
fun:__sanitizer_set_death_callback=uninstrumented
|
||||||
|
fun:__sanitizer_set_death_callback=discard
|
||||||
|
fun:__sanitizer_update_counter_bitset_and_clear_counters=uninstrumented
|
||||||
|
fun:__sanitizer_update_counter_bitset_and_clear_counters=discard
|
||||||
|
fun:__sanitizer_cov_trace_pc*=uninstrumented
|
||||||
|
fun:__sanitizer_cov_trace_pc*=discard
|
||||||
|
fun:__sanitizer_cov_pcs_init=uninstrumented
|
||||||
|
fun:__sanitizer_cov_pcs_init=discard
|
||||||
|
|
||||||
|
fun:__sanitizer_get_current_allocated_bytes=uninstrumented
|
||||||
|
fun:__sanitizer_get_current_allocated_bytes=discard
|
||||||
|
fun:__sanitizer_get_heap_size=uninstrumented
|
||||||
|
fun:__sanitizer_get_heap_size=discard
|
||||||
|
fun:__sanitizer_get_free_bytes=uninstrumented
|
||||||
|
fun:__sanitizer_get_free_bytes=discard
|
||||||
|
fun:__sanitizer_get_unmapped_bytes=uninstrumented
|
||||||
|
fun:__sanitizer_get_unmapped_bytes=discard
|
||||||
|
fun:__sanitizer_get_estimated_allocated_size=uninstrumented
|
||||||
|
fun:__sanitizer_get_estimated_allocated_size=discard
|
||||||
|
fun:__sanitizer_get_ownership=uninstrumented
|
||||||
|
fun:__sanitizer_get_ownership=discard
|
||||||
|
fun:__sanitizer_get_allocated_begin=uninstrumented
|
||||||
|
fun:__sanitizer_get_allocated_begin=discard
|
||||||
|
fun:__sanitizer_get_allocated_size=uninstrumented
|
||||||
|
fun:__sanitizer_get_allocated_size=discard
|
||||||
|
fun:__sanitizer_get_allocated_size_fast=uninstrumented
|
||||||
|
fun:__sanitizer_get_allocated_size_fast=discard
|
||||||
|
fun:__sanitizer_print_stack_trace=uninstrumented
|
||||||
|
fun:__sanitizer_print_stack_trace=discard
|
||||||
|
|
||||||
|
fun:TcmallocSlab_Internal_PushBatch_FixedShift=uninstrumented
|
||||||
|
fun:TcmallocSlab_Internal_PushBatch_FixedShift=discard
|
||||||
|
fun:TcmallocSlab_Internal_PushBatch_FixedShift_VCPU=uninstrumented
|
||||||
|
fun:TcmallocSlab_Internal_PushBatch_FixedShift_VCPU=discard
|
||||||
|
fun:TcmallocSlab_Internal_PerCpuCmpxchg64=uninstrumented
|
||||||
|
fun:TcmallocSlab_Internal_PerCpuCmpxchg64=discard
|
||||||
|
fun:TcmallocSlab_Internal_PerCpuCmpxchg64_VCPU=uninstrumented
|
||||||
|
fun:TcmallocSlab_Internal_PerCpuCmpxchg64_VCPU=discard
|
||||||
|
fun:TcmallocSlab_Internal_PopBatch_FixedShift=uninstrumented
|
||||||
|
fun:TcmallocSlab_Internal_PopBatch_FixedShift=discard
|
||||||
|
fun:TcmallocSlab_Internal_PopBatch_FixedShift_VCPU=uninstrumented
|
||||||
|
fun:TcmallocSlab_Internal_PopBatch_FixedShift_VCPU=discard
|
||||||
|
|
||||||
|
# Ignores the dfsan wrappers.
|
||||||
|
fun:__dfsw_*=uninstrumented
|
||||||
|
fun:__dfsw_*=discard
|
||||||
|
fun:__dfso_*=uninstrumented
|
||||||
|
fun:__dfso_*=discard
|
||||||
|
|
||||||
|
# Rust functions.
|
||||||
|
fun:__rdl_alloc=uninstrumented
|
||||||
|
fun:__rdl_alloc_zeroed=uninstrumented
|
||||||
|
fun:__rdl_dealloc=uninstrumented
|
||||||
|
fun:__rdl_realloc=uninstrumented
|
||||||
|
fun:__rg_oom=uninstrumented
|
||||||
|
fun:__rust_alloc=uninstrumented
|
||||||
|
fun:__rust_alloc_error_handler=uninstrumented
|
||||||
|
fun:__rust_alloc_zeroed=uninstrumented
|
||||||
|
fun:__rust_dealloc=uninstrumented
|
||||||
|
fun:__rust_realloc=uninstrumented
|
||||||
|
fun:_ZN4core*=uninstrumented
|
||||||
|
fun:_ZN3std*=uninstrumented
|
||||||
|
fun:rust_eh_personality=uninstrumented
|
||||||
60
tests/ui/sanitizer/dataflow.rs
Normal file
60
tests/ui/sanitizer/dataflow.rs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
// Verifies that labels are propagated through loads and stores.
|
||||||
|
//
|
||||||
|
//@ needs-sanitizer-support
|
||||||
|
//@ needs-sanitizer-dataflow
|
||||||
|
//@ run-pass
|
||||||
|
//@ compile-flags: -Zsanitizer=dataflow -Zsanitizer-dataflow-abilist={{src-base}}/sanitizer/dataflow-abilist.txt
|
||||||
|
|
||||||
|
use std::mem::size_of;
|
||||||
|
use std::os::raw::{c_int, c_long, c_void};
|
||||||
|
|
||||||
|
type dfsan_label = u8;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn dfsan_add_label(label: dfsan_label, addr: *mut c_void, size: usize);
|
||||||
|
fn dfsan_get_label(data: c_long) -> dfsan_label;
|
||||||
|
fn dfsan_has_label(label: dfsan_label, elem: dfsan_label) -> c_int;
|
||||||
|
fn dfsan_read_label(addr: *const c_void, size: usize) -> dfsan_label;
|
||||||
|
fn dfsan_set_label(label: dfsan_label, addr: *mut c_void, size: usize);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate2(i: &i64) -> i64 {
|
||||||
|
i.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate(i: i64) -> i64 {
|
||||||
|
let v = vec!(i, 1, 2, 3);
|
||||||
|
let j = v.iter().sum();
|
||||||
|
propagate2(&j)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let mut i = 1i64;
|
||||||
|
let i_ptr = &mut i as *mut i64;
|
||||||
|
let i_label: dfsan_label = 1;
|
||||||
|
unsafe {
|
||||||
|
dfsan_set_label(i_label, i_ptr as *mut c_void, size_of::<i64>());
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_label = unsafe { dfsan_get_label(i) };
|
||||||
|
assert_eq!(i_label, new_label);
|
||||||
|
|
||||||
|
let read_label = unsafe { dfsan_read_label(i_ptr as *const c_void, size_of::<i64>()) };
|
||||||
|
assert_eq!(i_label, read_label);
|
||||||
|
|
||||||
|
let j_label: dfsan_label = 2;
|
||||||
|
unsafe {
|
||||||
|
dfsan_add_label(j_label, i_ptr as *mut c_void, size_of::<i64>());
|
||||||
|
}
|
||||||
|
|
||||||
|
let read_label = unsafe { dfsan_read_label(i_ptr as *const c_void, size_of::<i64>()) };
|
||||||
|
assert_eq!(unsafe { dfsan_has_label(read_label, i_label) }, 1);
|
||||||
|
assert_eq!(unsafe { dfsan_has_label(read_label, j_label) }, 1);
|
||||||
|
|
||||||
|
let mut new_i = propagate(i);
|
||||||
|
let new_i_ptr = &mut new_i as *mut i64;
|
||||||
|
let read_label = unsafe { dfsan_read_label(new_i_ptr as *const c_void, size_of::<i64>()) };
|
||||||
|
assert_eq!(unsafe { dfsan_has_label(read_label, i_label) }, 1);
|
||||||
|
assert_eq!(unsafe { dfsan_has_label(read_label, j_label) }, 1);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user