diff --git a/src/doc/unstable-book/src/abi-msp430-interrupt.md b/src/doc/unstable-book/src/abi-msp430-interrupt.md index 9b2c7f298979d..b10bc41cb1439 100644 --- a/src/doc/unstable-book/src/abi-msp430-interrupt.md +++ b/src/doc/unstable-book/src/abi-msp430-interrupt.md @@ -5,3 +5,38 @@ The tracking issue for this feature is: [#38487] [#38487]: https://github.com/rust-lang/rust/issues/38487 ------------------------ + +In the MSP430 architecture, interrupt handlers have a special calling +convention. You can use the `"msp430-interrupt"` ABI to make the compiler apply +the right calling convention to the interrupt handlers you define. + + + +``` rust,ignore +#![feature(abi_msp430_interrupt)] +#![no_std] + +// Place the interrupt handler at the appropriate memory address +// (Alternatively, you can use `#[used]` and remove `pub` and `#[no_mangle]`) +#[link_section = "__interrupt_vector_10"] +#[no_mangle] +pub static TIM0_VECTOR: extern "msp430-interrupt" fn() = tim0; + +// The interrupt handler +extern "msp430-interrupt" fn tim0() { + // .. +} +``` + +``` text +$ msp430-elf-objdump -CD ./target/msp430/release/app +Disassembly of section __interrupt_vector_10: + +0000fff2 : + fff2: 00 c0 interrupt service routine at 0xc000 + +Disassembly of section .text: + +0000c000 : + c000: 00 13 reti +``` diff --git a/src/doc/unstable-book/src/abi-ptx.md b/src/doc/unstable-book/src/abi-ptx.md index 9c1b8868aceb4..0ded3ceeaef2c 100644 --- a/src/doc/unstable-book/src/abi-ptx.md +++ b/src/doc/unstable-book/src/abi-ptx.md @@ -1,5 +1,60 @@ # `abi_ptx` -The tracking issue for this feature is: None. +The tracking issue for this feature is: [#38788] + +[#38788]: https://github.com/rust-lang/rust/issues/38788 ------------------------ + +When emitting PTX code, all vanilla Rust functions (`fn`) get translated to +"device" functions. These functions are *not* callable from the host via the +CUDA API so a crate with only device functions is not too useful! + +OTOH, "global" functions *can* be called by the host; you can think of them +as the real public API of your crate. To produce a global function use the +`"ptx-kernel"` ABI. + + + +``` rust,ignore +#![feature(abi_ptx)] +#![no_std] + +pub unsafe extern "ptx-kernel" fn global_function() { + device_function(); +} + +pub fn device_function() { + // .. +} +``` + +``` text +$ xargo rustc --target nvptx64-nvidia-cuda --release -- --emit=asm + +$ cat $(find -name '*.s') +// +// Generated by LLVM NVPTX Back-End +// + +.version 3.2 +.target sm_20 +.address_size 64 + + // .globl _ZN6kernel15global_function17h46111ebe6516b382E + +.visible .entry _ZN6kernel15global_function17h46111ebe6516b382E() +{ + + + ret; +} + + // .globl _ZN6kernel15device_function17hd6a0e4993bbf3f78E +.visible .func _ZN6kernel15device_function17hd6a0e4993bbf3f78E() +{ + + + ret; +} +``` diff --git a/src/doc/unstable-book/src/compiler-builtins-lib.md b/src/doc/unstable-book/src/compiler-builtins-lib.md index 8986b968ca6c4..5da8968fd0ce2 100644 --- a/src/doc/unstable-book/src/compiler-builtins-lib.md +++ b/src/doc/unstable-book/src/compiler-builtins-lib.md @@ -1,5 +1,35 @@ # `compiler_builtins_lib` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: None. ------------------------ + +This feature is required to link to the `compiler_builtins` crate which contains +"compiler intrinsics". Compiler intrinsics are software implementations of basic +operations like multiplication of `u64`s. These intrinsics are only required on +platforms where these operations don't directly map to a hardware instruction. + +You should never need to explicitly link to the `compiler_builtins` crate when +building "std" programs as `compiler_builtins` is already in the dependency +graph of `std`. But you may need it when building `no_std` **binary** crates. If +you get a *linker* error like: + +``` text +$PWD/src/main.rs:11: undefined reference to `__aeabi_lmul' +$PWD/src/main.rs:11: undefined reference to `__aeabi_uldivmod' +``` + +That means that you need to link to this crate. + +When you link to this crate, make sure it only appears once in your crate +dependency graph. Also, it doesn't matter where in the dependency graph, you +place the `compiler_builtins` crate. + + + +``` rust,ignore +#![feature(compiler_builtins_lib)] +#![no_std] + +extern crate compiler_builtins; +``` diff --git a/src/doc/unstable-book/src/compiler-builtins.md b/src/doc/unstable-book/src/compiler-builtins.md index 3ec3cba257a99..52fac575b6e86 100644 --- a/src/doc/unstable-book/src/compiler-builtins.md +++ b/src/doc/unstable-book/src/compiler-builtins.md @@ -1,6 +1,5 @@ # `compiler_builtins` -The tracking issue for this feature is: None. +This feature is internal to the Rust compiler and is not intended for general use. ------------------------ - diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 2e1058bfc3413..a4050f271eb99 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -539,17 +539,16 @@ impl AtomicBool { // We can't use atomic_nand here because it can result in a bool with // an invalid value. This happens because the atomic operation is done // with an 8-bit integer internally, which would set the upper 7 bits. - // So we just use a compare-exchange loop instead, which is what the - // intrinsic actually expands to anyways on many platforms. - let mut old = self.load(Relaxed); - loop { - let new = !(old && val); - match self.compare_exchange_weak(old, new, order, Relaxed) { - Ok(_) => break, - Err(x) => old = x, - } + // So we just use fetch_xor or swap instead. + if val { + // !(x & true) == !x + // We must invert the bool. + self.fetch_xor(true, order) + } else { + // !(x & false) == true + // We must set the bool to true. + self.swap(true, order) } - old } /// Logical "or" with a boolean value. diff --git a/src/libcore/tests/atomic.rs b/src/libcore/tests/atomic.rs index b6bb5fddf4a4b..9babe24a98563 100644 --- a/src/libcore/tests/atomic.rs +++ b/src/libcore/tests/atomic.rs @@ -24,10 +24,23 @@ fn bool_() { #[test] fn bool_and() { let a = AtomicBool::new(true); - assert_eq!(a.fetch_and(false, SeqCst),true); + assert_eq!(a.fetch_and(false, SeqCst), true); assert_eq!(a.load(SeqCst),false); } +#[test] +fn bool_nand() { + let a = AtomicBool::new(false); + assert_eq!(a.fetch_nand(false, SeqCst), false); + assert_eq!(a.load(SeqCst), true); + assert_eq!(a.fetch_nand(false, SeqCst), true); + assert_eq!(a.load(SeqCst), true); + assert_eq!(a.fetch_nand(true, SeqCst), true); + assert_eq!(a.load(SeqCst), false); + assert_eq!(a.fetch_nand(true, SeqCst), false); + assert_eq!(a.load(SeqCst), true); +} + #[test] fn uint_and() { let x = AtomicUsize::new(0xf731); diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 550f1160bed85..c68e2ae34687b 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -408,7 +408,7 @@ declare_features! ( // Allows the definition recursive static items. (accepted, static_recursion, "1.17.0", Some(29719)), // pub(restricted) visibilities (RFC 1422) - (accepted, pub_restricted, "1.17.0", Some(32409)), + (accepted, pub_restricted, "1.18.0", Some(32409)), // The #![windows_subsystem] attribute (accepted, windows_subsystem, "1.18.0", Some(37499)), );