1
Fork 0

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:
Manish Goregaokar 2021-08-12 10:04:07 -07:00 committed by GitHub
commit df23264f80
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 52 additions and 15 deletions

View file

@ -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 {

View file

@ -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,

View file

@ -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,

View file

@ -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)?;
}

View file

@ -335,6 +335,7 @@ symbols! {
bitreverse,
bitxor,
bitxor_assign,
black_box,
block,
bool,
borrowck_graphviz_format,

View file

@ -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;