mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 16:54:01 +00:00
Rollup merge of #87916 - nbdd0121:black_box, r=nagisa
Implement `black_box` using intrinsic Introduce `black_box` intrinsic, as suggested in https://github.com/rust-lang/rust/pull/87590#discussion_r680468700. This is still codegenned as empty inline assembly for LLVM. For MIR interpretation and cranelift it's treated as identity. cc `@Amanieu` as this is related to inline assembly cc `@bjorn3` for rustc_codegen_cranelift changes cc `@RalfJung` as this affects MIRI r? `@nagisa` I suppose
This commit is contained in:
commit
df23264f80
@ -1136,6 +1136,11 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
|
||||
};
|
||||
ret.write_cvalue(fx, CValue::by_val(is_eq_value, ret.layout()));
|
||||
};
|
||||
|
||||
black_box, (c a) {
|
||||
// FIXME implement black_box semantics
|
||||
ret.write_cvalue(fx, a);
|
||||
};
|
||||
}
|
||||
|
||||
if let Some((_, dest)) = destination {
|
||||
|
@ -425,7 +425,7 @@ impl AsmMethods for CodegenCx<'ll, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn inline_asm_call(
|
||||
pub(crate) fn inline_asm_call(
|
||||
bx: &mut Builder<'a, 'll, 'tcx>,
|
||||
asm: &str,
|
||||
cons: &str,
|
||||
|
@ -7,6 +7,7 @@ use crate::type_of::LayoutLlvmExt;
|
||||
use crate::va_arg::emit_va_arg;
|
||||
use crate::value::Value;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh};
|
||||
use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
|
||||
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
|
||||
@ -327,6 +328,31 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
sym::black_box => {
|
||||
args[0].val.store(self, result);
|
||||
|
||||
// We need to "use" the argument in some way LLVM can't introspect, and on
|
||||
// targets that support it we can typically leverage inline assembly to do
|
||||
// this. LLVM's interpretation of inline assembly is that it's, well, a black
|
||||
// box. This isn't the greatest implementation since it probably deoptimizes
|
||||
// more than we want, but it's so far good enough.
|
||||
crate::asm::inline_asm_call(
|
||||
self,
|
||||
"",
|
||||
"r,~{memory}",
|
||||
&[result.llval],
|
||||
self.type_void(),
|
||||
true,
|
||||
false,
|
||||
ast::LlvmAsmDialect::Att,
|
||||
&[span],
|
||||
)
|
||||
.unwrap_or_else(|| bug!("failed to generate inline asm call for `black_box`"));
|
||||
|
||||
// We have copied the value to `result` already.
|
||||
return;
|
||||
}
|
||||
|
||||
_ if name_str.starts_with("simd_") => {
|
||||
match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) {
|
||||
Ok(llval) => llval,
|
||||
|
@ -465,7 +465,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
);
|
||||
self.copy_op(&self.operand_index(&args[0], index)?, dest)?;
|
||||
}
|
||||
sym::likely | sym::unlikely => {
|
||||
sym::likely | sym::unlikely | sym::black_box => {
|
||||
// These just return their argument
|
||||
self.copy_op(&args[0], dest)?;
|
||||
}
|
||||
|
@ -335,6 +335,7 @@ symbols! {
|
||||
bitreverse,
|
||||
bitxor,
|
||||
bitxor_assign,
|
||||
black_box,
|
||||
block,
|
||||
bool,
|
||||
borrowck_graphviz_format,
|
||||
|
@ -102,6 +102,7 @@ pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
|
||||
| sym::maxnumf64
|
||||
| sym::type_name
|
||||
| sym::forget
|
||||
| sym::black_box
|
||||
| sym::variant_count => hir::Unsafety::Normal,
|
||||
_ => hir::Unsafety::Unsafe,
|
||||
}
|
||||
@ -387,6 +388,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
||||
(1, vec![param_ty; 2], tcx.types.bool)
|
||||
}
|
||||
|
||||
sym::black_box => (1, vec![param(0)], param(0)),
|
||||
|
||||
other => {
|
||||
tcx.sess.emit_err(UnrecognizedIntrinsicFunction { span: it.span, name: other });
|
||||
return;
|
||||
|
@ -152,23 +152,19 @@ pub fn spin_loop() {
|
||||
/// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
|
||||
///
|
||||
/// [`std::convert::identity`]: crate::convert::identity
|
||||
#[cfg_attr(not(miri), inline)]
|
||||
#[cfg_attr(miri, inline(never))]
|
||||
#[inline]
|
||||
#[unstable(feature = "bench_black_box", issue = "64102")]
|
||||
#[cfg_attr(miri, allow(unused_mut))]
|
||||
#[cfg_attr(not(bootstrap), allow(unused_mut))]
|
||||
pub fn black_box<T>(mut dummy: T) -> T {
|
||||
// We need to "use" the argument in some way LLVM can't introspect, and on
|
||||
// targets that support it we can typically leverage inline assembly to do
|
||||
// this. LLVM's interpretation of inline assembly is that it's, well, a black
|
||||
// box. This isn't the greatest implementation since it probably deoptimizes
|
||||
// more than we want, but it's so far good enough.
|
||||
|
||||
#[cfg(not(miri))] // This is just a hint, so it is fine to skip in Miri.
|
||||
#[cfg(bootstrap)]
|
||||
// SAFETY: the inline assembly is a no-op.
|
||||
unsafe {
|
||||
// FIXME: Cannot use `asm!` because it doesn't support MIPS and other architectures.
|
||||
llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile");
|
||||
dummy
|
||||
}
|
||||
|
||||
dummy
|
||||
#[cfg(not(bootstrap))]
|
||||
{
|
||||
crate::intrinsics::black_box(dummy)
|
||||
}
|
||||
}
|
||||
|
@ -1933,6 +1933,12 @@ extern "rust-intrinsic" {
|
||||
/// which is UB if any of their inputs are `undef`.)
|
||||
#[rustc_const_unstable(feature = "const_intrinsic_raw_eq", issue = "none")]
|
||||
pub fn raw_eq<T>(a: &T, b: &T) -> bool;
|
||||
|
||||
/// See documentation of [`std::hint::black_box`] for details.
|
||||
///
|
||||
/// [`std::hint::black_box`]: crate::hint::black_box
|
||||
#[cfg(not(bootstrap))]
|
||||
pub fn black_box<T>(dummy: T) -> T;
|
||||
}
|
||||
|
||||
// Some functions are defined here because they accidentally got made
|
||||
|
@ -6,7 +6,7 @@
|
||||
// run-fail
|
||||
// error-pattern: MemorySanitizer: use-of-uninitialized-value
|
||||
// error-pattern: Uninitialized value was created by an allocation
|
||||
// error-pattern: in the stack frame of function 'random'
|
||||
// error-pattern: in the stack frame of function 'main'
|
||||
//
|
||||
// This test case intentionally limits the usage of the std,
|
||||
// since it will be linked with an uninstrumented version of it.
|
||||
|
Loading…
Reference in New Issue
Block a user