diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs index 89de5c1bc8af8..565b65a8b50d4 100644 --- a/src/libcore/hint.rs +++ b/src/libcore/hint.rs @@ -62,13 +62,6 @@ pub unsafe fn unreachable_unchecked() -> ! { #[inline] #[unstable(feature = "renamed_spin_loop", issue = "55002")] pub fn spin_loop() { - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - unsafe { - asm!("pause" ::: "memory" : "volatile"); - } - - #[cfg(target_arch = "aarch64")] - unsafe { - asm!("yield" ::: "memory" : "volatile"); - } + #[cfg(not(stage0))] + intrinsics::spin_loop_hint(); } diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index e6098b1b24cc0..67e16411157fc 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1308,6 +1308,9 @@ extern "rust-intrinsic" { /// Emits a `!nontemporal` store according to LLVM (see their docs). /// Probably will never become stable. pub fn nontemporal_store(ptr: *mut T, val: T); + + #[cfg(not(stage0))] + pub fn spin_loop_hint(); } mod real_intrinsics { diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 3268af396a2f4..96e19b9852960 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -19,7 +19,7 @@ use rustc::ty::{self, Ty}; use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Primitive}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc::hir; -use syntax::ast::{self, FloatTy}; +use syntax::ast::{self, FloatTy, AsmDialect}; use syntax::symbol::Symbol; use rustc_codegen_ssa::traits::*; @@ -28,6 +28,7 @@ use rustc::session::Session; use syntax_pos::Span; use std::cmp::Ordering; +use std::ffi::CStr; use std::{iter, i128, u128}; fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Value> { @@ -689,6 +690,27 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { return; } + "spin_loop_hint" => { + let asm = match &*self.tcx().sess.target.target.arch { + "x86" | "x86_64" => b"pause\0", + "aarch64" => b"yield\0", + _ => return, + }; + let r = self.inline_asm_call( + CStr::from_bytes_with_nul(asm).unwrap(), + CStr::from_bytes_with_nul(b"r,~{memory}\0").unwrap(), + &[], + self.type_void(), + true, + false, + AsmDialect::Att, + ); + if r.is_none() { + bug!("broken spin_loop_hint"); + } + return; + } + _ => bug!("unknown intrinsic '{}'", name), }; diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 924ced2e2a3c7..f1b182a32a9f4 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -70,7 +70,8 @@ pub fn intrisic_operation_unsafety(intrinsic: &str) -> hir::Unsafety { "overflowing_add" | "overflowing_sub" | "overflowing_mul" | "saturating_add" | "saturating_sub" | "rotate_left" | "rotate_right" | - "ctpop" | "ctlz" | "cttz" | "bswap" | "bitreverse" + "ctpop" | "ctlz" | "cttz" | "bswap" | "bitreverse" | + "spin_loop_hint" => hir::Unsafety::Normal, _ => hir::Unsafety::Unsafe, } @@ -379,6 +380,8 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (1, vec![ tcx.mk_mut_ptr(param(0)), param(0) ], tcx.mk_unit()) } + "spin_loop_hint" => (0, vec![], tcx.mk_unit()), + ref other => { struct_span_err!(tcx.sess, it.span, E0093, "unrecognized intrinsic function: `{}`",