From 78ebaa82f1a1ba5d373b979e2bb4f3434255154c Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 10 Aug 2021 11:50:33 +0100 Subject: [PATCH 1/4] Implement `black_box` using intrinsic --- .../src/intrinsics/mod.rs | 4 +++ compiler/rustc_codegen_llvm/src/asm.rs | 2 +- compiler/rustc_codegen_llvm/src/intrinsic.rs | 26 +++++++++++++++++++ .../rustc_mir/src/interpret/intrinsics.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_typeck/src/check/intrinsic.rs | 3 +++ library/core/src/hint.rs | 19 +++++--------- library/core/src/intrinsics.rs | 6 +++++ 8 files changed, 49 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 8669846074749..37a1e3dc04f33 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -1136,6 +1136,10 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( }; ret.write_cvalue(fx, CValue::by_val(is_eq_value, ret.layout())); }; + + black_box, (c a) { + ret.write_cvalue(fx, a); + }; } if let Some((_, dest)) = destination { diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index ebc3773df57cd..4790b44bd19ef 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -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, diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index ed48418586517..8c52481c929de 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -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(); + + // 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, diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs index dc1f9053b61f0..bfab886b6ee4f 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics.rs @@ -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)?; } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3f5d8273b38b8..6d03f1a37329e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -335,6 +335,7 @@ symbols! { bitreverse, bitxor, bitxor_assign, + black_box, block, bool, borrowck_graphviz_format, diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs index 6661df21ed952..664954b0eb7a2 100644 --- a/compiler/rustc_typeck/src/check/intrinsic.rs +++ b/compiler/rustc_typeck/src/check/intrinsic.rs @@ -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; diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index a0b65399da2c5..cd40924ab669e 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -152,23 +152,18 @@ 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))] #[unstable(feature = "bench_black_box", issue = "64102")] -#[cfg_attr(miri, allow(unused_mut))] +#[cfg_attr(not(bootstrap), allow(unused_mut))] pub fn black_box(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) + } } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index d15ac89668fa3..272b1e3a1d75e 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -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(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(dummy: T) -> T; } // Some functions are defined here because they accidentally got made From 3cf2a69e92320a383557713f30206f302678d443 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 10 Aug 2021 16:05:34 +0100 Subject: [PATCH 2/4] `bug!`-ify unwrap --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 8c52481c929de..fe2ed21c1e3b0 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -347,7 +347,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { ast::LlvmAsmDialect::Att, &[span], ) - .unwrap(); + .unwrap_or_else(|| bug!("failed to generate inline asm call for `black_box`")); // We have copied the value to `result` already. return; From fbc5f67c8926e18f47cbf94596f61280ee7331df Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 10 Aug 2021 18:01:04 +0100 Subject: [PATCH 3/4] Add `#[inline]` back to `black_box` --- library/core/src/hint.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index cd40924ab669e..a4924554919b0 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -152,6 +152,7 @@ pub fn spin_loop() { /// backend used. Programs cannot rely on `black_box` for *correctness* in any way. /// /// [`std::convert::identity`]: crate::convert::identity +#[inline] #[unstable(feature = "bench_black_box", issue = "64102")] #[cfg_attr(not(bootstrap), allow(unused_mut))] pub fn black_box(mut dummy: T) -> T { From f98d5406525423fe468dffed195ce1ee1079f9f2 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 10 Aug 2021 19:11:15 +0100 Subject: [PATCH 4/4] Add a fixme to black_box lowering in cg_clif Co-authored-by: bjorn3 --- compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 37a1e3dc04f33..1c4d307fc50e1 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -1138,6 +1138,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( }; black_box, (c a) { + // FIXME implement black_box semantics ret.write_cvalue(fx, a); }; }