miri: fail when calling a function that requires an unavailable target feature
miri will report an UB when calling a function that has a `#[target_feature(enable = ...)]` attribute is called and the required feature is not available. "Available features" are the same that `is_x86_feature_detected!` (or equivalent) reports to be available during miri execution (which can be enabled or disabled with the `-C target-feature` flag).
This commit is contained in:
parent
ad963232d9
commit
b5fde0dae0
5 changed files with 60 additions and 0 deletions
|
@ -399,6 +399,9 @@ const_eval_unallowed_mutable_refs_raw =
|
|||
const_eval_unallowed_op_in_const_context =
|
||||
{$msg}
|
||||
|
||||
const_eval_unavailable_target_features_for_fn =
|
||||
calling a function that requires unavailable target features: {$unavailable_feats}
|
||||
|
||||
const_eval_undefined_behavior =
|
||||
it is undefined behavior to use this value
|
||||
|
||||
|
|
|
@ -503,6 +503,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
}
|
||||
}
|
||||
|
||||
let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
|
||||
let missing_features: Vec<_> = attrs
|
||||
.target_features
|
||||
.iter()
|
||||
.copied()
|
||||
.filter(|feature| !self.tcx.sess.target_features.contains(feature))
|
||||
.collect();
|
||||
if !missing_features.is_empty() {
|
||||
let mut missing_features_str = String::from(missing_features[0].as_str());
|
||||
for missing_feature in missing_features[1..].iter() {
|
||||
missing_features_str.push(',');
|
||||
missing_features_str.push_str(missing_feature.as_str());
|
||||
}
|
||||
throw_ub_custom!(
|
||||
fluent::const_eval_unavailable_target_features_for_fn,
|
||||
unavailable_feats = missing_features_str,
|
||||
);
|
||||
}
|
||||
|
||||
if !callee_fn_abi.can_unwind {
|
||||
// The callee cannot unwind, so force the `Unreachable` unwind handling.
|
||||
unwind = mir::UnwindAction::Unreachable;
|
||||
|
|
11
src/tools/miri/tests/fail/function_calls/target_feature.rs
Normal file
11
src/tools/miri/tests/fail/function_calls/target_feature.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
//@only-target-x86_64: uses x86 target features
|
||||
|
||||
fn main() {
|
||||
assert!(!is_x86_feature_detected!("ssse3"));
|
||||
unsafe {
|
||||
ssse3_fn(); //~ ERROR: calling a function that requires unavailable target features: ssse3
|
||||
}
|
||||
}
|
||||
|
||||
#[target_feature(enable = "ssse3")]
|
||||
unsafe fn ssse3_fn() {}
|
|
@ -0,0 +1,15 @@
|
|||
error: Undefined Behavior: calling a function that requires unavailable target features: ssse3
|
||||
--> $DIR/target_feature.rs:LL:CC
|
||||
|
|
||||
LL | ssse3_fn();
|
||||
| ^^^^^^^^^^ calling a function that requires unavailable target features: ssse3
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
= note: BACKTRACE:
|
||||
= note: inside `main` at $DIR/target_feature.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to previous error
|
||||
|
12
src/tools/miri/tests/pass/function_calls/target_feature.rs
Normal file
12
src/tools/miri/tests/pass/function_calls/target_feature.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
//@only-target-x86_64: uses x86 target features
|
||||
//@compile-flags: -C target-feature=+ssse3
|
||||
|
||||
fn main() {
|
||||
assert!(is_x86_feature_detected!("ssse3"));
|
||||
unsafe {
|
||||
ssse3_fn();
|
||||
}
|
||||
}
|
||||
|
||||
#[target_feature(enable = "ssse3")]
|
||||
unsafe fn ssse3_fn() {}
|
Loading…
Add table
Add a link
Reference in a new issue