diff --git a/src/Cargo.lock b/src/Cargo.lock index 569a24055bb..db896b59ba4 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -444,6 +444,7 @@ dependencies = [ name = "core" version = "0.0.0" dependencies = [ + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml index 0b01cfc488b..2de1fa521e8 100644 --- a/src/libcore/Cargo.toml +++ b/src/libcore/Cargo.toml @@ -21,3 +21,6 @@ path = "../libcore/benches/lib.rs" [dev-dependencies] rand = "0.5" + +[build-dependencies] +cc = "1.0" diff --git a/src/libcore/build.rs b/src/libcore/build.rs new file mode 100644 index 00000000000..beca373d397 --- /dev/null +++ b/src/libcore/build.rs @@ -0,0 +1,22 @@ +// Copyright 2019 King's College London. +// Created by the Software Development Team . +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate cc; + +fn main() { + let mut c_build = cc::Build::new(); + + c_build.file("yk_swt_impl.c"); + c_build.compile("yk_swt_impl"); + c_build.flag("-std=c11"); + c_build.warnings(true); + c_build.extra_warnings(true); + + println!("cargo:rerun-if-changed=yk_swt_impl.c"); +} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 6da694209a0..1fa82178705 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -229,7 +229,9 @@ mod nonzero; mod tuple; mod unit; -mod yk_swt; +/// Yorick software tracing. +#[unstable(feature = "yk_swt", issue = "0")] +pub mod yk_swt; // Pull in the `coresimd` crate directly into libcore. This is where all the // architecture-specific (and vendor-specific) intrinsics are defined. AKA diff --git a/src/libcore/yk_swt.rs b/src/libcore/yk_swt.rs index 8e80965c447..36a17930254 100644 --- a/src/libcore/yk_swt.rs +++ b/src/libcore/yk_swt.rs @@ -7,20 +7,91 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/// The software trace recorder function. -/// This is a weak language item, it actually resides in libstd. It has to be weak to allow libcore -/// to call up to libstd (libstd is not a dependency of libcore). -extern "Rust" { - #[cfg_attr(not(stage0), lang="yk_swt_rec_loc")] - fn yk_swt_rec_loc(crate_hash: u64, def_idx: u32, bb: u32); +/// The result of `yk_swt_stop_tracing_impl()` is an array of this C struct. +#[repr(C)] +#[derive(Debug)] +pub struct MirLoc { + /// Unique identifier for the crate. + pub crate_hash: u64, + /// The definition index. + pub def_idx: u32, + /// The basic block index. + pub bb_idx: u32, +} + +/// Wraps the raw C trace buffer and exposes a more "Rusty" interface to it. +#[derive(Debug)] +#[allow(dead_code)] +pub struct SWTrace { + /// A heap allocated array of `MirLoc` structs, which the consumer must free. Ideally we'd + /// have this struct implement `std::ops::Drop` or at least provide a method to do the freeing, + /// but we can do neither due to libcore restrictions. + buf: *mut MirLoc, + /// The number of items in the above array. + len: usize, } -/// Wrapper lang item to call the above wrapper function. -/// This has to be a lang item too, as a MIR terminator cannot call a weak language item directly. +impl SWTrace { + /// Returns the number of MIR locations recorded in the trace. + pub fn len(&self) -> usize { + self.len + } + + /// Return a pointer to the raw trace buffer. The consumer *must* free this pointer. + pub fn buf(self) -> *mut MirLoc { + self.buf + } + + /// Returns the location at index `idx` or `None` if the index is out of bounds. + pub fn loc<'a>(&'a self, idx: usize) -> &'a MirLoc { + if idx >= self.len { + panic!("software trace index out of bounds: len={}, idx={}", self.len, idx); + } else { + if idx > isize::max_value() as usize { + panic!("index too large for ptr arithmetic"); + } + unsafe { &*self.buf.offset(idx as isize) } + } + } +} + +/// The software trace recorder function. +/// This is implemented in C so that: the `yk_swt_calls` MIR pass doesn't see inside. #[allow(dead_code)] // Used only indirectly in a MIR pass. -#[cfg_attr(not(stage0), lang="yk_swt_rec_loc_wrap")] +#[cfg_attr(not(stage0), lang="yk_swt_rec_loc")] +#[cfg_attr(not(stage0), no_trace)] +#[cfg(not(test))] +fn yk_swt_rec_loc(crate_hash: u64, def_idx: u32, bb_idx: u32) { + extern "C" { fn yk_swt_rec_loc_impl(crate_hash: u64, def_idx: u32, bb_idx: u32); } + unsafe { yk_swt_rec_loc_impl(crate_hash, def_idx, bb_idx); } +} + +/// Start software tracing on the current thread. The current thread must not already be tracing. #[cfg_attr(not(stage0), no_trace)] -fn yk_swt_rec_loc_wrap(crate_hash: u64, def_idx: u32, bb: u32) { - unsafe { yk_swt_rec_loc(crate_hash, def_idx, bb) }; +pub fn start_tracing() { + extern "C" { fn yk_swt_start_tracing_impl(); } + unsafe { yk_swt_start_tracing_impl(); } } +/// Stop software tracing and return the trace, or `None` if the trace was invalidated. +/// The current thread must already be tracing. +#[cfg_attr(not(stage0), no_trace)] +pub fn stop_tracing() -> Option { + let len: usize = 0; + + extern "C" { fn yk_swt_stop_tracing_impl(ret_len: &usize) -> *mut MirLoc; } + let buf = unsafe { yk_swt_stop_tracing_impl(&len) }; + + if buf.is_null() { + None + } else { + Some(SWTrace { buf, len }) + } +} + +/// Invalidate the software trace, if one is being collected. +#[cfg_attr(not(stage0), no_trace)] +pub fn invalidate_trace() { + extern "C" { fn yk_swt_invalidate_trace_impl(); } + unsafe { yk_swt_invalidate_trace_impl(); } +} diff --git a/src/libcore/yk_swt_impl.c b/src/libcore/yk_swt_impl.c new file mode 100644 index 00000000000..85b025e0bcb --- /dev/null +++ b/src/libcore/yk_swt_impl.c @@ -0,0 +1,130 @@ +// Copyright 2019 King's College London. +// Created by the Software Development Team . +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#include +#include +#include +#include +#include + +struct mir_loc { + uint64_t crate_hash; + uint32_t def_idx; + uint32_t bb_idx; +}; + +#define TL_TRACE_INIT_CAP 1024 +#define TL_TRACE_REALLOC_CAP 1024 + +void yk_swt_start_tracing_impl(void); +void yk_swt_rec_loc_impl(uint64_t crate_hash, uint32_t def_idx, uint32_t bb_idx); +struct mir_loc *yk_swt_stop_tracing_impl(size_t *ret_trace_len); +void yk_swt_invalidate_trace_impl(void); + +// The trace buffer. +static __thread struct mir_loc *trace_buf = NULL; +// The number of elements in the trace buffer. +static __thread size_t trace_buf_len = 0; +// The allocation capacity of the trace buffer (in elements). +static __thread size_t trace_buf_cap = 0; +// Is the current thread tracing? +// true = we are tracing, false = we are not tracing or an error occurred. +static __thread volatile atomic_bool tracing = false; + +// Start tracing on the current thread. +// A new trace buffer is allocated and MIR locations will be written into it on +// subsequent calls to `yk_swt_rec_loc_impl`. If the current thread is already +// tracing, calling this will lead to undefined behaviour. +void +yk_swt_start_tracing_impl(void) { + trace_buf = calloc(TL_TRACE_INIT_CAP, sizeof(struct mir_loc)); + if (trace_buf == NULL) { + err(EXIT_FAILURE, "%s: calloc: ", __func__); + } + + trace_buf_cap = TL_TRACE_INIT_CAP; + atomic_store_explicit(&tracing, true, memory_order_relaxed); +} + +// Record a location into the trace buffer if tracing is enabled on the current thread. +void +yk_swt_rec_loc_impl(uint64_t crate_hash, uint32_t def_idx, uint32_t bb_idx) +{ + if (!atomic_load_explicit(&tracing, memory_order_relaxed)) { + return; + } + + // Check if we need more space and reallocate if necessary. + if (trace_buf_len == trace_buf_cap) { + if (trace_buf_cap >= SIZE_MAX - TL_TRACE_REALLOC_CAP) { + // Trace capacity would overflow. + atomic_store_explicit(&tracing, false, memory_order_relaxed); + return; + } + size_t new_cap = trace_buf_cap + TL_TRACE_REALLOC_CAP; + + if (new_cap > SIZE_MAX / sizeof(struct mir_loc)) { + // New buffer size would overflow. + atomic_store_explicit(&tracing, false, memory_order_relaxed); + return; + } + size_t new_size = new_cap * sizeof(struct mir_loc); + + trace_buf = realloc(trace_buf, new_size); + if (trace_buf == NULL) { + atomic_store_explicit(&tracing, false, memory_order_relaxed); + return; + } + + trace_buf_cap = new_cap; + } + + struct mir_loc loc = { crate_hash, def_idx, bb_idx }; + trace_buf[trace_buf_len] = loc; + trace_buf_len ++; +} + + +// Stop tracing on the current thread. +// On success the trace buffer is returned and the number of locations it +// holds is written to `*ret_trace_len`. It is the responsibility of the caller +// to free the returned trace buffer. A NULL pointer is returned on error. +// Calling this function when tracing was not started with +// `yk_swt_start_tracing_impl()` results in undefined behaviour. +struct mir_loc * +yk_swt_stop_tracing_impl(size_t *ret_trace_len) { + if (!atomic_load_explicit(&tracing, memory_order_relaxed)) { + free(trace_buf); + trace_buf = NULL; + trace_buf_len = 0; + } + + // We hand ownership of the trace to Rust now. Rust is responsible for + // freeing the trace. + struct mir_loc *ret_trace = trace_buf; + *ret_trace_len = trace_buf_len; + + // Now reset all off the recorder's state. + // We reset `trace_invalid` when tracing is restarted, because signals + // handlers which set this flag may arrive in the meantime. + trace_buf = NULL; + tracing = false; + trace_buf_len = 0; + trace_buf_cap = 0; + + return ret_trace; +} + +// Call this to safely mark the trace invalid. +void +yk_swt_invalidate_trace_impl(void) { + // We don't free the trace buffer here, as this may be called in a signal + // handler and thus needs to be reentrant. + atomic_store_explicit(&tracing, false, memory_order_relaxed); +} diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 38d131643bd..75e7e999d83 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -377,7 +377,6 @@ language_item_table! { U128ShroFnLangItem, "u128_shro", u128_shro_fn, Target::Fn; YkSwtRecLocLangItem, "yk_swt_rec_loc", yk_swt_rec_loc, Target::Fn; - YkSwtRecLocWrapLangItem, "yk_swt_rec_loc_wrap",yk_swt_rec_loc_wrap, Target::Fn; // Align offset for stride != 1, must not panic. AlignOffsetLangItem, "align_offset", align_offset_fn, Target::Fn; diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index acbb951a453..0d407765c9e 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -168,5 +168,4 @@ weak_lang_items! { eh_personality, EhPersonalityLangItem, rust_eh_personality; eh_unwind_resume, EhUnwindResumeLangItem, rust_eh_unwind_resume; oom, OomLangItem, rust_oom; - yk_swt_rec_loc, YkSwtRecLocLangItem, rust_yk_swt_rec_loc; } diff --git a/src/librustc_mir/transform/add_yk_swt_calls.rs b/src/librustc_mir/transform/add_yk_swt_calls.rs index e7b3a809f45..cfb9af6011d 100644 --- a/src/librustc_mir/transform/add_yk_swt_calls.rs +++ b/src/librustc_mir/transform/add_yk_swt_calls.rs @@ -51,7 +51,7 @@ impl MirPass for AddYkSWTCalls { return; } - let rec_fn_defid = tcx.get_lang_items(LOCAL_CRATE).yk_swt_rec_loc_wrap() + let rec_fn_defid = tcx.get_lang_items(LOCAL_CRATE).yk_swt_rec_loc() .expect("couldn't find software trace recorder function"); let unit_ty = tcx.mk_unit(); diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 2a6691a9712..623cefacc2c 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -310,6 +310,7 @@ #![feature(panic_info_message)] #![feature(non_exhaustive)] #![feature(alloc_layout_extra)] +#![feature(yk_swt)] #![default_lib_allocator] @@ -518,10 +519,6 @@ mod coresimd { #[cfg(all(not(stage0), not(test)))] pub use stdsimd::arch; -/// Yorick software tracing. -#[unstable(feature = "yk_swt", issue = "0")] -pub mod yk_swt; - // Include a number of private modules that exist solely to provide // the rustdoc documentation for primitive types. Using `include!` // because rustdoc only looks for these modules at the crate level. diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index 40453f9b8a1..a4ed53d1c0a 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -97,6 +97,10 @@ mod imp { unsafe extern fn signal_handler(signum: libc::c_int, info: *mut libc::siginfo_t, _data: *mut libc::c_void) { + // A signal handler can corrupt a software trace. + use core::yk_swt; + yk_swt::invalidate_trace(); + use sys_common::util::report_overflow; let guard = thread_info::stack_guard().unwrap_or(0..0); diff --git a/src/libstd/yk_swt.rs b/src/libstd/yk_swt.rs deleted file mode 100644 index c5690af2a03..00000000000 --- a/src/libstd/yk_swt.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2018 King's College London. -// Created by the Software Development Team . -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/// The software trace recorder function. -/// The `AddYkSWTCalls` MIR pass injects a call this for every MIR block. The call is done -/// indirectly via a wrapper in libcore. -#[cfg_attr(not(stage0), lang="yk_swt_rec_loc")] -#[allow(unused_variables,dead_code)] -#[cfg_attr(not(stage0), no_trace)] -#[cfg(not(test))] -fn rec_loc(crate_hash: u64, def_idx: u32, bb_idx: u32) { - // Not implemented. -} diff --git a/src/test/compile-fail/two-panic-runtimes.rs b/src/test/compile-fail/two-panic-runtimes.rs index 4809d92f62b..36ed000e344 100644 --- a/src/test/compile-fail/two-panic-runtimes.rs +++ b/src/test/compile-fail/two-panic-runtimes.rs @@ -22,6 +22,3 @@ extern crate panic_runtime_unwind2; extern crate panic_runtime_lang_items; fn main() {} - -#[lang = "yk_swt_rec_loc"] -fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {} diff --git a/src/test/run-fail/yk_swt/oob-trace-idx.rs b/src/test/run-fail/yk_swt/oob-trace-idx.rs new file mode 100644 index 00000000000..df1819f472d --- /dev/null +++ b/src/test/run-fail/yk_swt/oob-trace-idx.rs @@ -0,0 +1,39 @@ +// Copyright 2019 King's College London. +// Created by the Software Development Team . +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern: software trace index out of bounds + +#![feature(yk_swt)] +#![feature(libc)] +#![feature(test)] + +extern crate core; +extern crate libc; +extern crate test; + +use core::yk_swt::{start_tracing, stop_tracing}; +use test::black_box; + +pub fn main() { + start_tracing(); + black_box(work()); + let trace = stop_tracing().unwrap(); + + // By reading one past the end of the trace buffer, we should cause the test to panic. + trace.loc(trace.len()); +} + +#[inline(never)] +fn work() -> u64{ + let mut res = 100; + for i in 0..100 { + res += res / 2 + i; + } + res +} diff --git a/src/test/run-make-fulldeps/issue-51671/app.rs b/src/test/run-make-fulldeps/issue-51671/app.rs index 510e4836388..4066214f4b4 100644 --- a/src/test/run-make-fulldeps/issue-51671/app.rs +++ b/src/test/run-make-fulldeps/issue-51671/app.rs @@ -16,9 +16,6 @@ use core::alloc::Layout; use core::panic::PanicInfo; -#[lang = "yk_swt_rec_loc"] -fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {} - #[panic_handler] fn panic(_: &PanicInfo) -> ! { loop {} diff --git a/src/test/run-make-fulldeps/issue-53964/app.rs b/src/test/run-make-fulldeps/issue-53964/app.rs index f5fa02d35f7..621e7e99263 100644 --- a/src/test/run-make-fulldeps/issue-53964/app.rs +++ b/src/test/run-make-fulldeps/issue-53964/app.rs @@ -5,8 +5,5 @@ #![deny(unused_extern_crates)] #![feature(lang_items)] -#[lang = "yk_swt_rec_loc"] -fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {} - // `panic` provides a `panic_handler` so it shouldn't trip the `unused_extern_crates` lint extern crate panic; diff --git a/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs b/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs index aa4dc8aeb88..0b11df6347c 100644 --- a/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs +++ b/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs @@ -12,9 +12,6 @@ #![no_std] #![feature(lang_items)] -#[lang = "yk_swt_rec_loc"] -fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {} - use core::panic::PanicInfo; #[panic_handler] diff --git a/src/test/run-pass/thinlto/thin-lto-inlines2.rs b/src/test/run-pass/thinlto/thin-lto-inlines2.rs index 84809b09785..33fe3b0c5b4 100644 --- a/src/test/run-pass/thinlto/thin-lto-inlines2.rs +++ b/src/test/run-pass/thinlto/thin-lto-inlines2.rs @@ -20,6 +20,8 @@ // praying two functions go into separate codegen units and then assuming that // if inlining *doesn't* happen the first byte of the functions will differ. +#![no_trace] + extern crate thin_lto_inlines_aux as bar; pub fn foo() -> u32 { diff --git a/src/test/run-pass/yk_swt/collect-trace-twice.rs b/src/test/run-pass/yk_swt/collect-trace-twice.rs new file mode 100644 index 00000000000..ca356afbcb3 --- /dev/null +++ b/src/test/run-pass/yk_swt/collect-trace-twice.rs @@ -0,0 +1,53 @@ +// Copyright 2019 King's College London. +// Created by the Software Development Team . +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(yk_swt)] +#![feature(libc)] +#![feature(test)] + +extern crate core; +extern crate libc; +extern crate test; + +use core::yk_swt::{start_tracing, stop_tracing}; +use test::black_box; + +// Collect two traces sequentially in the same thread. +pub fn main() { + start_tracing(); + black_box(work1()); + let trace1 = stop_tracing().unwrap(); + + start_tracing(); + black_box(work2()); + let trace2 = stop_tracing().unwrap(); + + assert!(trace1.len() > trace2.len()); + + unsafe { libc::free(trace1.buf() as *mut libc::c_void) }; + unsafe { libc::free(trace2.buf() as *mut libc::c_void) }; +} + +#[inline(never)] +fn work1() -> u64{ + let mut res = 100; + for _ in 0..9000 { + res += 1; + } + res +} + +#[inline(never)] +fn work2() -> u64{ + let mut res = 6000; + for _ in 0..3000 { + res -= 1; + } + res +} diff --git a/src/test/run-pass/yk_swt/collect-trace.rs b/src/test/run-pass/yk_swt/collect-trace.rs new file mode 100644 index 00000000000..4e0e9c9e809 --- /dev/null +++ b/src/test/run-pass/yk_swt/collect-trace.rs @@ -0,0 +1,45 @@ +// Copyright 2019 King's College London. +// Created by the Software Development Team . +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(yk_swt)] +#![feature(libc)] +#![feature(test)] + +extern crate core; +extern crate libc; +extern crate test; + +use core::yk_swt::{start_tracing, stop_tracing}; +use test::black_box; + +pub fn main() { + start_tracing(); + black_box(work()); + let trace = stop_tracing().unwrap(); + + let len = trace.len(); + // The default capacity of the trace buffer is 1024. We want to be sure we've tested the case + // where it had to be reallocated beyond its starting capacity. + assert!(len > 1024); + + for idx in 0..len { + trace.loc(idx); // All indices are in bounds, so should not panic. + } + + unsafe { libc::free(trace.buf() as *mut libc::c_void) }; +} + +#[inline(never)] +fn work() -> u64{ + let mut res = 100; + for i in 0..3000 { + res += res / 2 + i; + } + res +} diff --git a/src/test/run-pass/yk_swt/collect-traces-threaded.rs b/src/test/run-pass/yk_swt/collect-traces-threaded.rs new file mode 100644 index 00000000000..7f336737501 --- /dev/null +++ b/src/test/run-pass/yk_swt/collect-traces-threaded.rs @@ -0,0 +1,70 @@ +// Copyright 2019 King's College London. +// Created by the Software Development Team . +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(yk_swt)] +#![feature(libc)] +#![feature(test)] + +extern crate core; +extern crate libc; +extern crate test; + +use core::yk_swt::{start_tracing, stop_tracing, SWTrace}; +use std::thread; +use test::black_box; + +// Run tracing in two separate threads with different work and check that the traces are different. +fn main() { + let thr2 = thread::spawn(move || { + start_tracing(); + let _ = work2(); + let raw_trace2 = stop_tracing().unwrap(); + let trace2 = trace_to_vec(&raw_trace2); + unsafe { libc::free(raw_trace2.buf() as *mut libc::c_void) }; + trace2 + }); + + start_tracing(); + black_box(work1()); + let raw_trace1 = stop_tracing().unwrap(); + let trace1 = trace_to_vec(&raw_trace1); + unsafe { libc::free(raw_trace1.buf() as *mut libc::c_void) }; + + let trace2 = thr2.join().unwrap(); + + assert_ne!(trace1, trace2); // They should have been thread local. +} + +// Copies a trace into a plain Rust Vec of tuples so we can compare them. +fn trace_to_vec(t: &SWTrace) -> Vec<(u64, u32, u32)> { + let mut v = Vec::new(); + for i in 0..t.len() { + let loc = t.loc(i); + v.push((loc.crate_hash, loc.def_idx, loc.bb_idx)); + } + v +} + +#[inline(never)] +fn work1() -> u64{ + let mut res = 2000; + for _ in 0..1000 { + res -= 1; + } + res +} + +#[inline(never)] +fn work2() -> u64{ + let mut res = 0; + for i in 0..2000 { + res += i + 1; + } + res +} diff --git a/src/test/run-pass/yk_swt/invalidate-trace.rs b/src/test/run-pass/yk_swt/invalidate-trace.rs new file mode 100644 index 00000000000..9fd8a068637 --- /dev/null +++ b/src/test/run-pass/yk_swt/invalidate-trace.rs @@ -0,0 +1,36 @@ +// Copyright 2019 King's College London. +// Created by the Software Development Team . +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(yk_swt)] +#![feature(libc)] +#![feature(test)] + +extern crate core; +extern crate libc; +extern crate test; + +use core::yk_swt::{start_tracing, stop_tracing, invalidate_trace}; +use test::black_box; + +// Check that invalidating a trace works. +fn main() { + start_tracing(); + black_box(work()); + invalidate_trace(); + assert!(stop_tracing().is_none()); +} + +#[inline(never)] +fn work() -> u64{ + let mut res = 2000; + for _ in 0..100 { + res -= 1; + } + res +} diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.rs b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.rs index 4204fe2d6bc..e98f22b301e 100644 --- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.rs +++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.rs @@ -26,6 +26,3 @@ fn oom( #[panic_handler] fn panic(_: &core::panic::PanicInfo) -> ! { loop {} } - -#[lang = "yk_swt_rec_loc"] -fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {} diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.rs b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.rs index 4cadf03676d..e2a9a7fd69a 100644 --- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.rs +++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.rs @@ -25,6 +25,3 @@ fn oom( #[panic_handler] fn panic(_: &core::panic::PanicInfo) -> ! { loop {} } - -#[lang = "yk_swt_rec_loc"] -fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {} diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs index 2e465909723..0ab71160852 100644 --- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs +++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs @@ -23,6 +23,3 @@ fn oom() -> ! { //~ ERROR function should have one argument #[panic_handler] fn panic(_: &core::panic::PanicInfo) -> ! { loop {} } - -#[lang = "yk_swt_rec_loc"] -fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {} diff --git a/src/test/ui/consts/const-eval/const_panic_libcore_main.rs b/src/test/ui/consts/const-eval/const_panic_libcore_main.rs index d8301e11767..03365ae46ab 100644 --- a/src/test/ui/consts/const-eval/const_panic_libcore_main.rs +++ b/src/test/ui/consts/const-eval/const_panic_libcore_main.rs @@ -34,6 +34,3 @@ fn eh_unwind_resume() {} fn panic(_info: &PanicInfo) -> ! { loop {} } - -#[lang = "yk_swt_rec_loc"] -fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {} diff --git a/src/test/ui/missing/missing-alloc_error_handler.rs b/src/test/ui/missing/missing-alloc_error_handler.rs index d4a7feaddd4..89c368456b1 100644 --- a/src/test/ui/missing/missing-alloc_error_handler.rs +++ b/src/test/ui/missing/missing-alloc_error_handler.rs @@ -31,6 +31,3 @@ unsafe impl core::alloc::GlobalAlloc for MyAlloc { unsafe fn alloc(&self, _: core::alloc::Layout) -> *mut u8 { 0 as _ } unsafe fn dealloc(&self, _: *mut u8, _: core::alloc::Layout) {} } - -#[lang = "yk_swt_rec_loc"] -fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {} diff --git a/src/test/ui/missing/missing-allocator.rs b/src/test/ui/missing/missing-allocator.rs index 5650ec5907b..f4405d1f8fb 100644 --- a/src/test/ui/missing/missing-allocator.rs +++ b/src/test/ui/missing/missing-allocator.rs @@ -26,6 +26,3 @@ fn oom(_: core::alloc::Layout) -> ! { } extern crate alloc; - -#[lang = "yk_swt_rec_loc"] -fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {} diff --git a/src/test/ui/no_owned_box_lang_item.rs b/src/test/ui/no_owned_box_lang_item.rs index 49546e32bbb..34d1075f9b7 100644 --- a/src/test/ui/no_owned_box_lang_item.rs +++ b/src/test/ui/no_owned_box_lang_item.rs @@ -24,4 +24,3 @@ fn main() { #[lang = "eh_personality"] extern fn eh_personality() {} #[lang = "eh_unwind_resume"] extern fn eh_unwind_resume() {} #[lang = "panic_impl"] fn panic_impl(panic: &PanicInfo) -> ! { loop {} } -#[lang = "yk_swt_rec_loc"] fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {} diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-1.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-1.rs index ee2d554a646..b82a2274390 100644 --- a/src/test/ui/panic-handler/panic-handler-bad-signature-1.rs +++ b/src/test/ui/panic-handler/panic-handler-bad-signature-1.rs @@ -22,6 +22,3 @@ fn panic( ) -> () //~ ERROR return type should be `!` { } - -#[lang = "yk_swt_rec_loc"] -fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {} diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-2.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-2.rs index ccb79410aa1..ccc9dfd7aaa 100644 --- a/src/test/ui/panic-handler/panic-handler-bad-signature-2.rs +++ b/src/test/ui/panic-handler/panic-handler-bad-signature-2.rs @@ -23,6 +23,3 @@ fn panic( { loop {} } - -#[lang = "yk_swt_rec_loc"] -fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {} diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-3.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-3.rs index 041303fca5f..03be5307986 100644 --- a/src/test/ui/panic-handler/panic-handler-bad-signature-3.rs +++ b/src/test/ui/panic-handler/panic-handler-bad-signature-3.rs @@ -20,6 +20,3 @@ use core::panic::PanicInfo; fn panic() -> ! { //~ ERROR function should have one argument loop {} } - -#[lang = "yk_swt_rec_loc"] -fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {} diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-4.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-4.rs index d21962085b8..ba013b87e37 100644 --- a/src/test/ui/panic-handler/panic-handler-bad-signature-4.rs +++ b/src/test/ui/panic-handler/panic-handler-bad-signature-4.rs @@ -21,6 +21,3 @@ fn panic(pi: &PanicInfo) -> ! { //~^ ERROR should have no type parameters loop {} } - -#[lang = "yk_swt_rec_loc"] -fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {} diff --git a/src/test/ui/panic-handler/panic-handler-duplicate.rs b/src/test/ui/panic-handler/panic-handler-duplicate.rs index 1e45727439c..c4fb4903e00 100644 --- a/src/test/ui/panic-handler/panic-handler-duplicate.rs +++ b/src/test/ui/panic-handler/panic-handler-duplicate.rs @@ -25,6 +25,3 @@ fn panic(info: &PanicInfo) -> ! { fn panic2(info: &PanicInfo) -> ! { //~ ERROR duplicate lang item found: `panic_impl`. loop {} } - -#[lang = "yk_swt_rec_loc"] -fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {} diff --git a/src/test/ui/panic-handler/panic-handler-wrong-location.rs b/src/test/ui/panic-handler/panic-handler-wrong-location.rs index 5434b28795c..8d0b655515d 100644 --- a/src/test/ui/panic-handler/panic-handler-wrong-location.rs +++ b/src/test/ui/panic-handler/panic-handler-wrong-location.rs @@ -17,6 +17,3 @@ #[panic_handler] #[no_mangle] static X: u32 = 42; - -#[lang = "yk_swt_rec_loc"] -fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {} diff --git a/src/test/ui/panic-runtime/transitive-link-a-bunch.rs b/src/test/ui/panic-runtime/transitive-link-a-bunch.rs index 2f6af734d22..e40706b7935 100644 --- a/src/test/ui/panic-runtime/transitive-link-a-bunch.rs +++ b/src/test/ui/panic-runtime/transitive-link-a-bunch.rs @@ -24,6 +24,3 @@ extern crate wants_panic_runtime_abort; extern crate panic_runtime_lang_items; fn main() {} - -#[lang = "yk_swt_rec_loc"] -fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {} diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort.rs b/src/test/ui/panic-runtime/want-unwind-got-abort.rs index f04e302cbd5..38de5d4407b 100644 --- a/src/test/ui/panic-runtime/want-unwind-got-abort.rs +++ b/src/test/ui/panic-runtime/want-unwind-got-abort.rs @@ -20,6 +20,3 @@ extern crate panic_runtime_abort; extern crate panic_runtime_lang_items; fn main() {} - -#[lang = "yk_swt_rec_loc"] -fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {} diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort2.rs b/src/test/ui/panic-runtime/want-unwind-got-abort2.rs index 3dd2501ad54..bb47dc84904 100644 --- a/src/test/ui/panic-runtime/want-unwind-got-abort2.rs +++ b/src/test/ui/panic-runtime/want-unwind-got-abort2.rs @@ -21,6 +21,3 @@ extern crate wants_panic_runtime_abort; extern crate panic_runtime_lang_items; fn main() {} - -#[lang = "yk_swt_rec_loc"] -fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {} diff --git a/src/test/ui/range/issue-54505-no-std.rs b/src/test/ui/range/issue-54505-no-std.rs index 4032ebf144d..22cf15fb2e4 100644 --- a/src/test/ui/range/issue-54505-no-std.rs +++ b/src/test/ui/range/issue-54505-no-std.rs @@ -55,6 +55,3 @@ fn main() { //~| HELP consider borrowing here //~| SUGGESTION &(..=42) } - -#[lang = "yk_swt_rec_loc"] -fn yk_swt_rec_loc(_crate_hash: u64, _def_idx: u32, _bb: u32) {}