about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libcore/hint.rs36
-rw-r--r--src/libcore/internal_macros.rs81
-rw-r--r--src/libtest/lib.rs18
-rw-r--r--src/tools/tidy/src/pal.rs4
4 files changed, 122 insertions, 17 deletions
diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs
index b2f82ef0d17..d1ccc148654 100644
--- a/src/libcore/hint.rs
+++ b/src/libcore/hint.rs
@@ -91,3 +91,39 @@ pub fn spin_loop() {
         }
     }
 }
+
+/// A function that is opaque to the optimizer, to allow benchmarks to
+/// pretend to use outputs to assist in avoiding dead-code
+/// elimination.
+///
+/// This function is a no-op, and does not even read from `dummy`.
+#[inline]
+#[unstable(feature = "test", issue = "27812")]
+pub fn black_box<T>(dummy: T) -> T {
+    cfg_if! {
+        if #[cfg(any(
+            target_arch = "asmjs",
+            all(
+                target_arch = "wasm32",
+                target_os = "emscripten"
+            )
+        ))] {
+            #[inline]
+            unsafe fn black_box_impl<T>(d: T) -> T {
+                // these targets do not support inline assembly
+                let ret = crate::ptr::read_volatile(&d);
+                crate::mem::forget(d);
+                ret
+            }
+        } else {
+            #[inline]
+            unsafe fn black_box_impl<T>(d: T) -> T {
+                // we need to "use" the argument in some way LLVM can't
+                // introspect.
+                asm!("" : : "r"(&d));
+                d
+            }
+        }
+    }
+    unsafe { black_box_impl(dummy) }
+}
diff --git a/src/libcore/internal_macros.rs b/src/libcore/internal_macros.rs
index b5c20582986..ee6b7d3db48 100644
--- a/src/libcore/internal_macros.rs
+++ b/src/libcore/internal_macros.rs
@@ -119,3 +119,84 @@ macro_rules! impl_fn_for_zst {
         )+
     }
 }
+
+/// A macro for defining `#[cfg]` if-else statements.
+///
+/// The macro provided by this crate, `cfg_if`, is similar to the `if/elif` C
+/// preprocessor macro by allowing definition of a cascade of `#[cfg]` cases,
+/// emitting the implementation which matches first.
+///
+/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
+/// without having to rewrite each clause multiple times.
+///
+/// # Example
+///
+/// ```
+/// #[macro_use]
+/// extern crate cfg_if;
+///
+/// cfg_if! {
+///     if #[cfg(unix)] {
+///         fn foo() { /* unix specific functionality */ }
+///     } else if #[cfg(target_pointer_width = "32")] {
+///         fn foo() { /* non-unix, 32-bit functionality */ }
+///     } else {
+///         fn foo() { /* fallback implementation */ }
+///     }
+/// }
+///
+/// # fn main() {}
+/// ```
+macro_rules! cfg_if {
+    // match if/else chains with a final `else`
+    ($(
+        if #[cfg($($meta:meta),*)] { $($it:item)* }
+    ) else * else {
+        $($it2:item)*
+    }) => {
+        cfg_if! {
+            @__items
+            () ;
+            $( ( ($($meta),*) ($($it)*) ), )*
+            ( () ($($it2)*) ),
+        }
+    };
+
+    // match if/else chains lacking a final `else`
+    (
+        if #[cfg($($i_met:meta),*)] { $($i_it:item)* }
+        $(
+            else if #[cfg($($e_met:meta),*)] { $($e_it:item)* }
+        )*
+    ) => {
+        cfg_if! {
+            @__items
+            () ;
+            ( ($($i_met),*) ($($i_it)*) ),
+            $( ( ($($e_met),*) ($($e_it)*) ), )*
+            ( () () ),
+        }
+    };
+
+    // Internal and recursive macro to emit all the items
+    //
+    // Collects all the negated cfgs in a list at the beginning and after the
+    // semicolon is all the remaining items
+    (@__items ($($not:meta,)*) ; ) => {};
+    (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => {
+        // Emit all items within one block, applying an approprate #[cfg]. The
+        // #[cfg] will require all `$m` matchers specified and must also negate
+        // all previous matchers.
+        cfg_if! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* }
+
+        // Recurse to emit all other items in `$rest`, and when we do so add all
+        // our `$m` matchers to the list of `$not` matchers as future emissions
+        // will have to negate everything we just matched as well.
+        cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* }
+    };
+
+    // Internal macro to Apply a cfg attribute to a list of items
+    (@__apply $m:meta, $($it:item)*) => {
+        $(#[$m] $it)*
+    };
+}
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index cb0ce480e42..5c91c0ec43b 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -27,23 +27,7 @@ pub use libtest::{
     TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk, stats::Summary
 };
 
-/// A function that is opaque to the optimizer, to allow benchmarks to
-/// pretend to use outputs to assist in avoiding dead-code
-/// elimination.
-///
-/// This function is a no-op, and does not even read from `dummy`.
-#[cfg(not(any(target_arch = "asmjs", target_arch = "wasm32")))]
-pub fn black_box<T>(dummy: T) -> T {
-    // we need to "use" the argument in some way LLVM can't
-    // introspect.
-    unsafe { asm!("" : : "r"(&dummy)) }
-    dummy
-}
-#[cfg(any(target_arch = "asmjs", target_arch = "wasm32"))]
-#[inline(never)]
-pub fn black_box<T>(dummy: T) -> T {
-    dummy
-}
+pub use std::hint::black_box;
 
 #[cfg(test)]
 mod tests {
diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs
index 0be3ec839e9..b725fbe3d74 100644
--- a/src/tools/tidy/src/pal.rs
+++ b/src/tools/tidy/src/pal.rs
@@ -42,6 +42,10 @@ const EXCEPTION_PATHS: &[&str] = &[
     "src/libpanic_abort",
     "src/libpanic_unwind",
     "src/libunwind",
+    // black_box implementation is LLVM-version specific and it uses
+    // target_os to tell targets with different LLVM-versions appart
+    // (e.g. `wasm32-unknown-emscripten` vs `wasm32-unknown-unknown`):
+    "src/libcore/hint.rs",
     "src/libstd/sys/", // Platform-specific code for std lives here.
                        // This has the trailing slash so that sys_common is not excepted.
     "src/libstd/os", // Platform-specific public interfaces