Add singlethreaded fence intrinsics.
These new intrinsics are comparable to `atomic_signal_fence` in C++, ensuring the compiler will not reorder memory accesses across the barrier, nor will it emit any machine instructions for it. Closes #24118, implementing RFC 888.
This commit is contained in:
parent
0d8309ec0b
commit
998c10d6b6
7 changed files with 43 additions and 11 deletions
|
@ -139,6 +139,21 @@ extern "rust-intrinsic" {
|
||||||
pub fn atomic_fence_rel();
|
pub fn atomic_fence_rel();
|
||||||
pub fn atomic_fence_acqrel();
|
pub fn atomic_fence_acqrel();
|
||||||
|
|
||||||
|
/// A compiler-only memory barrier.
|
||||||
|
///
|
||||||
|
/// Memory accesses will never be reordered across this barrier by the compiler,
|
||||||
|
/// but no instructions will be emitted for it. This is appropriate for operations
|
||||||
|
/// on the same thread that may be preempted, such as when interacting with signal
|
||||||
|
/// handlers.
|
||||||
|
#[cfg(not(stage0))] // SNAP 5520801
|
||||||
|
pub fn atomic_singlethreadfence();
|
||||||
|
#[cfg(not(stage0))] // SNAP 5520801
|
||||||
|
pub fn atomic_singlethreadfence_acq();
|
||||||
|
#[cfg(not(stage0))] // SNAP 5520801
|
||||||
|
pub fn atomic_singlethreadfence_rel();
|
||||||
|
#[cfg(not(stage0))] // SNAP 5520801
|
||||||
|
pub fn atomic_singlethreadfence_acqrel();
|
||||||
|
|
||||||
/// Aborts the execution of the process.
|
/// Aborts the execution of the process.
|
||||||
pub fn abort() -> !;
|
pub fn abort() -> !;
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ pub use self::RealPredicate::*;
|
||||||
pub use self::TypeKind::*;
|
pub use self::TypeKind::*;
|
||||||
pub use self::AtomicBinOp::*;
|
pub use self::AtomicBinOp::*;
|
||||||
pub use self::AtomicOrdering::*;
|
pub use self::AtomicOrdering::*;
|
||||||
|
pub use self::SynchronizationScope::*;
|
||||||
pub use self::FileType::*;
|
pub use self::FileType::*;
|
||||||
pub use self::MetadataType::*;
|
pub use self::MetadataType::*;
|
||||||
pub use self::AsmDialect::*;
|
pub use self::AsmDialect::*;
|
||||||
|
@ -361,6 +362,13 @@ pub enum AtomicOrdering {
|
||||||
SequentiallyConsistent = 7
|
SequentiallyConsistent = 7
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub enum SynchronizationScope {
|
||||||
|
SingleThread = 0,
|
||||||
|
CrossThread = 1
|
||||||
|
}
|
||||||
|
|
||||||
// Consts for the LLVMCodeGenFileType type (in include/llvm/c/TargetMachine.h)
|
// Consts for the LLVMCodeGenFileType type (in include/llvm/c/TargetMachine.h)
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
@ -1534,7 +1542,9 @@ extern {
|
||||||
SingleThreaded: Bool)
|
SingleThreaded: Bool)
|
||||||
-> ValueRef;
|
-> ValueRef;
|
||||||
|
|
||||||
pub fn LLVMBuildAtomicFence(B: BuilderRef, Order: AtomicOrdering);
|
pub fn LLVMBuildAtomicFence(B: BuilderRef,
|
||||||
|
Order: AtomicOrdering,
|
||||||
|
Scope: SynchronizationScope);
|
||||||
|
|
||||||
|
|
||||||
/* Selected entries from the downcasts. */
|
/* Selected entries from the downcasts. */
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use llvm;
|
use llvm;
|
||||||
use llvm::{CallConv, AtomicBinOp, AtomicOrdering, AsmDialect, AttrBuilder};
|
use llvm::{CallConv, AtomicBinOp, AtomicOrdering, SynchronizationScope, AsmDialect, AttrBuilder};
|
||||||
use llvm::{Opcode, IntPredicate, RealPredicate};
|
use llvm::{Opcode, IntPredicate, RealPredicate};
|
||||||
use llvm::{ValueRef, BasicBlockRef};
|
use llvm::{ValueRef, BasicBlockRef};
|
||||||
use trans::common::*;
|
use trans::common::*;
|
||||||
|
@ -965,9 +965,9 @@ pub fn CallWithConv(cx: Block,
|
||||||
B(cx).call_with_conv(fn_, args, conv, attributes)
|
B(cx).call_with_conv(fn_, args, conv, attributes)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn AtomicFence(cx: Block, order: AtomicOrdering) {
|
pub fn AtomicFence(cx: Block, order: AtomicOrdering, scope: SynchronizationScope) {
|
||||||
if cx.unreachable.get() { return; }
|
if cx.unreachable.get() { return; }
|
||||||
B(cx).atomic_fence(order)
|
B(cx).atomic_fence(order, scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn Select(cx: Block, if_: ValueRef, then: ValueRef, else_: ValueRef) -> ValueRef {
|
pub fn Select(cx: Block, if_: ValueRef, then: ValueRef, else_: ValueRef) -> ValueRef {
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#![allow(dead_code)] // FFI wrappers
|
#![allow(dead_code)] // FFI wrappers
|
||||||
|
|
||||||
use llvm;
|
use llvm;
|
||||||
use llvm::{CallConv, AtomicBinOp, AtomicOrdering, AsmDialect, AttrBuilder};
|
use llvm::{CallConv, AtomicBinOp, AtomicOrdering, SynchronizationScope, AsmDialect, AttrBuilder};
|
||||||
use llvm::{Opcode, IntPredicate, RealPredicate, False};
|
use llvm::{Opcode, IntPredicate, RealPredicate, False};
|
||||||
use llvm::{ValueRef, BasicBlockRef, BuilderRef, ModuleRef};
|
use llvm::{ValueRef, BasicBlockRef, BuilderRef, ModuleRef};
|
||||||
use trans::base;
|
use trans::base;
|
||||||
|
@ -989,9 +989,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn atomic_fence(&self, order: AtomicOrdering) {
|
pub fn atomic_fence(&self, order: AtomicOrdering, scope: SynchronizationScope) {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMBuildAtomicFence(self.llbuilder, order);
|
llvm::LLVMBuildAtomicFence(self.llbuilder, order, scope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -763,7 +763,12 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
"fence" => {
|
"fence" => {
|
||||||
AtomicFence(bcx, order);
|
AtomicFence(bcx, order, llvm::CrossThread);
|
||||||
|
C_nil(ccx)
|
||||||
|
}
|
||||||
|
|
||||||
|
"singlethreadfence" => {
|
||||||
|
AtomicFence(bcx, order, llvm::SingleThread);
|
||||||
C_nil(ccx)
|
C_nil(ccx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4812,7 +4812,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
|
||||||
(1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
|
(1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
|
||||||
param(ccx, 0))
|
param(ccx, 0))
|
||||||
}
|
}
|
||||||
"fence" => {
|
"fence" | "singlethreadfence" => {
|
||||||
(0, Vec::new(), ty::mk_nil(tcx))
|
(0, Vec::new(), ty::mk_nil(tcx))
|
||||||
}
|
}
|
||||||
op => {
|
op => {
|
||||||
|
|
|
@ -189,8 +189,10 @@ extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B,
|
||||||
failure_order
|
failure_order
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B, AtomicOrdering order) {
|
extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B,
|
||||||
return wrap(unwrap(B)->CreateFence(order));
|
AtomicOrdering order,
|
||||||
|
SynchronizationScope scope) {
|
||||||
|
return wrap(unwrap(B)->CreateFence(order, scope));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void LLVMSetDebug(int Enabled) {
|
extern "C" void LLVMSetDebug(int Enabled) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue